xref: /freebsd/contrib/sendmail/src/map.c (revision d39bd2c1388b520fcba9abed1932acacead60fba)
1c2aa98e2SPeter Wemm /*
25dd76dd0SGregory Neil Shapiro  * Copyright (c) 1998-2008 Proofpoint, Inc. and its suppliers.
306f25ae9SGregory Neil Shapiro  *	All rights reserved.
4c2aa98e2SPeter Wemm  * Copyright (c) 1992, 1995-1997 Eric P. Allman.  All rights reserved.
5c2aa98e2SPeter Wemm  * Copyright (c) 1992, 1993
6c2aa98e2SPeter Wemm  *	The Regents of the University of California.  All rights reserved.
7c2aa98e2SPeter Wemm  *
8c2aa98e2SPeter Wemm  * By using this file, you agree to the terms and conditions set
9c2aa98e2SPeter Wemm  * forth in the LICENSE file which can be found at the top level of
10c2aa98e2SPeter Wemm  * the sendmail distribution.
11c2aa98e2SPeter Wemm  *
12c2aa98e2SPeter Wemm  */
13c2aa98e2SPeter Wemm 
1406f25ae9SGregory Neil Shapiro #include <sendmail.h>
1506f25ae9SGregory Neil Shapiro 
164313cc83SGregory Neil Shapiro SM_RCSID("@(#)$Id: map.c,v 8.713 2013-11-22 20:51:55 ca Exp $")
172fb4f839SGregory Neil Shapiro #include <sm/sendmail.h>
18c2aa98e2SPeter Wemm 
1940266059SGregory Neil Shapiro #if LDAPMAP
2040266059SGregory Neil Shapiro # include <sm/ldap.h>
215b0945b5SGregory Neil Shapiro #endif
2240266059SGregory Neil Shapiro 
2340266059SGregory Neil Shapiro #if NDBM
24c2aa98e2SPeter Wemm # include <ndbm.h>
25c2aa98e2SPeter Wemm # ifdef R_FIRST
262fb4f839SGregory Neil Shapiro #  error "README: You are running the Berkeley DB version of ndbm.h.  See"
272fb4f839SGregory Neil Shapiro #  error "README: the README file about tweaking Berkeley DB so it can"
282fb4f839SGregory Neil Shapiro #  error "README: coexist with NDBM, or delete -DNDBM from the Makefile"
292fb4f839SGregory Neil Shapiro #  error "README: and use -DNEWDB instead."
3006f25ae9SGregory Neil Shapiro # endif /* R_FIRST */
3106f25ae9SGregory Neil Shapiro #endif /* NDBM */
3240266059SGregory Neil Shapiro #if NEWDB
3313bd1963SGregory Neil Shapiro # include "sm/bdb.h"
345b0945b5SGregory Neil Shapiro #endif
3540266059SGregory Neil Shapiro #if NIS
36c2aa98e2SPeter Wemm   struct dom_binding;	/* forward reference needed on IRIX */
37c2aa98e2SPeter Wemm # include <rpcsvc/ypclnt.h>
3840266059SGregory Neil Shapiro # if NDBM
39c2aa98e2SPeter Wemm #  define NDBM_YP_COMPAT	/* create YP-compatible NDBM files */
405b0945b5SGregory Neil Shapiro # endif
4106f25ae9SGregory Neil Shapiro #endif /* NIS */
425b0945b5SGregory Neil Shapiro #if CDB
435b0945b5SGregory Neil Shapiro # include <cdb.h>
445b0945b5SGregory Neil Shapiro #endif
4506f25ae9SGregory Neil Shapiro 
46d0cef73dSGregory Neil Shapiro #include "map.h"
47d0cef73dSGregory Neil Shapiro 
4840266059SGregory Neil Shapiro #if NEWDB
4906f25ae9SGregory Neil Shapiro # if DB_VERSION_MAJOR < 2
5006f25ae9SGregory Neil Shapiro static bool	db_map_open __P((MAP *, int, char *, DBTYPE, const void *));
515b0945b5SGregory Neil Shapiro # endif
5206f25ae9SGregory Neil Shapiro # if DB_VERSION_MAJOR == 2
5306f25ae9SGregory Neil Shapiro static bool	db_map_open __P((MAP *, int, char *, DBTYPE, DB_INFO *));
545b0945b5SGregory Neil Shapiro # endif
5506f25ae9SGregory Neil Shapiro # if DB_VERSION_MAJOR > 2
5606f25ae9SGregory Neil Shapiro static bool	db_map_open __P((MAP *, int, char *, DBTYPE, void **));
575b0945b5SGregory Neil Shapiro # endif
5806f25ae9SGregory Neil Shapiro #endif /* NEWDB */
59602a2b1bSGregory Neil Shapiro static bool	extract_canonname __P((char *, char *, char *, char[], int));
6006f25ae9SGregory Neil Shapiro static void	map_close __P((STAB *, int));
6106f25ae9SGregory Neil Shapiro static void	map_init __P((STAB *, int));
6240266059SGregory Neil Shapiro #ifdef LDAPMAP
6340266059SGregory Neil Shapiro static STAB	*ldapmap_findconn __P((SM_LDAP_STRUCT *));
645b0945b5SGregory Neil Shapiro #endif
6540266059SGregory Neil Shapiro #if NISPLUS
6606f25ae9SGregory Neil Shapiro static bool	nisplus_getcanonname __P((char *, int, int *));
675b0945b5SGregory Neil Shapiro #endif
6840266059SGregory Neil Shapiro #if NIS
6906f25ae9SGregory Neil Shapiro static bool	nis_getcanonname __P((char *, int, int *));
705b0945b5SGregory Neil Shapiro #endif
7106f25ae9SGregory Neil Shapiro #if NETINFO
7206f25ae9SGregory Neil Shapiro static bool	ni_getcanonname __P((char *, int, int *));
735b0945b5SGregory Neil Shapiro #endif
7406f25ae9SGregory Neil Shapiro static bool	text_getcanonname __P((char *, int, int *));
75e92d3f3fSGregory Neil Shapiro #if SOCKETMAP
76e92d3f3fSGregory Neil Shapiro static STAB	*socket_map_findconn __P((const char*));
77e92d3f3fSGregory Neil Shapiro 
78e92d3f3fSGregory Neil Shapiro /* XXX arbitrary limit for sanity */
79e92d3f3fSGregory Neil Shapiro # define SOCKETMAP_MAXL 1000000
80e92d3f3fSGregory Neil Shapiro #endif /* SOCKETMAP */
81c2aa98e2SPeter Wemm 
8240266059SGregory Neil Shapiro /* default error message for trying to open a map in write mode */
8340266059SGregory Neil Shapiro #ifdef ENOSYS
8440266059SGregory Neil Shapiro # define SM_EMAPCANTWRITE	ENOSYS
8540266059SGregory Neil Shapiro #else /* ENOSYS */
8640266059SGregory Neil Shapiro # ifdef EFTYPE
8740266059SGregory Neil Shapiro #  define SM_EMAPCANTWRITE	EFTYPE
885b0945b5SGregory Neil Shapiro # else
8940266059SGregory Neil Shapiro #  define SM_EMAPCANTWRITE	ENXIO
905b0945b5SGregory Neil Shapiro # endif
9140266059SGregory Neil Shapiro #endif /* ENOSYS */
9240266059SGregory Neil Shapiro 
93c2aa98e2SPeter Wemm /*
94*d39bd2c1SGregory Neil Shapiro **  MAP_HAS_CHGED -- check whether fd was updated or fn refers to a different file
95*d39bd2c1SGregory Neil Shapiro **
96*d39bd2c1SGregory Neil Shapiro **	Parameters:
97*d39bd2c1SGregory Neil Shapiro **		map -- map being checked
98*d39bd2c1SGregory Neil Shapiro **		fn -- (full) file name of map.
99*d39bd2c1SGregory Neil Shapiro **		fd -- fd of map.
100*d39bd2c1SGregory Neil Shapiro **
101*d39bd2c1SGregory Neil Shapiro **	Returns:
102*d39bd2c1SGregory Neil Shapiro **		true iff file referenced by fd was updated
103*d39bd2c1SGregory Neil Shapiro **		     or fn refers to a different file.
104*d39bd2c1SGregory Neil Shapiro */
105*d39bd2c1SGregory Neil Shapiro 
106*d39bd2c1SGregory Neil Shapiro static bool map_has_chged __P((MAP *, const char *, int));
107*d39bd2c1SGregory Neil Shapiro 
108*d39bd2c1SGregory Neil Shapiro static bool
map_has_chged(map,fn,fd)109*d39bd2c1SGregory Neil Shapiro map_has_chged(map, fn, fd)
110*d39bd2c1SGregory Neil Shapiro 	MAP *map;
111*d39bd2c1SGregory Neil Shapiro 	const char *fn;
112*d39bd2c1SGregory Neil Shapiro 	int fd;
113*d39bd2c1SGregory Neil Shapiro {
114*d39bd2c1SGregory Neil Shapiro 	struct stat stbuf;
115*d39bd2c1SGregory Neil Shapiro #if _FFR_MAP_CHK_FILE
116*d39bd2c1SGregory Neil Shapiro 	struct stat nstbuf;
117*d39bd2c1SGregory Neil Shapiro #endif
118*d39bd2c1SGregory Neil Shapiro 
119*d39bd2c1SGregory Neil Shapiro #if _FFR_MAP_CHK_FILE > 1
120*d39bd2c1SGregory Neil Shapiro 	if (tTd(38, 8))
121*d39bd2c1SGregory Neil Shapiro 		sm_dprintf("map_has_chged: fn=%s, fd=%d, checked=%d\n",
122*d39bd2c1SGregory Neil Shapiro 			fn, fd, bitset(MF_CHKED_CHGD, map->map_mflags));
123*d39bd2c1SGregory Neil Shapiro 	if (fd < 0)
124*d39bd2c1SGregory Neil Shapiro 		return true;
125*d39bd2c1SGregory Neil Shapiro 
126*d39bd2c1SGregory Neil Shapiro 	/* XXX check can be disabled via -d38.101 for testing */
127*d39bd2c1SGregory Neil Shapiro 	if (bitset(MF_CHKED_CHGD, map->map_mflags) && !tTd(38, 101))
128*d39bd2c1SGregory Neil Shapiro 		return false;
129*d39bd2c1SGregory Neil Shapiro 	map->map_mflags |= MF_CHKED_CHGD;
130*d39bd2c1SGregory Neil Shapiro #endif
131*d39bd2c1SGregory Neil Shapiro 	if (fd < 0 || fstat(fd, &stbuf) < 0 || stbuf.st_mtime > map->map_mtime)
132*d39bd2c1SGregory Neil Shapiro 	{
133*d39bd2c1SGregory Neil Shapiro 		if (tTd(38, 4))
134*d39bd2c1SGregory Neil Shapiro 			sm_dprintf("reopen map: name=%s, fd=%d\n", map->map_mname, fd);
135*d39bd2c1SGregory Neil Shapiro 		return true;
136*d39bd2c1SGregory Neil Shapiro 	}
137*d39bd2c1SGregory Neil Shapiro #if _FFR_MAP_CHK_FILE
138*d39bd2c1SGregory Neil Shapiro 	if (stat(fn, &nstbuf) == 0 &&
139*d39bd2c1SGregory Neil Shapiro 	    (nstbuf.st_dev != stbuf.st_dev || nstbuf.st_ino != stbuf.st_ino))
140*d39bd2c1SGregory Neil Shapiro 	{
141*d39bd2c1SGregory Neil Shapiro 		if (tTd(38, 4) && stat(fn, &nstbuf) == 0)
142*d39bd2c1SGregory Neil Shapiro 			sm_dprintf("reopen map: fn=%s, ndev=%d, dev=%d, nino=%d, ino=%d\n",
143*d39bd2c1SGregory Neil Shapiro 				fn, (int) nstbuf.st_dev, (int) stbuf.st_dev,
144*d39bd2c1SGregory Neil Shapiro 				(int) nstbuf.st_ino, (int) stbuf.st_ino);
145*d39bd2c1SGregory Neil Shapiro 		return true;
146*d39bd2c1SGregory Neil Shapiro 	}
147*d39bd2c1SGregory Neil Shapiro #endif
148*d39bd2c1SGregory Neil Shapiro 	return false;
149*d39bd2c1SGregory Neil Shapiro }
150*d39bd2c1SGregory Neil Shapiro 
151*d39bd2c1SGregory Neil Shapiro #if _FFR_MAP_CHK_FILE > 1
152*d39bd2c1SGregory Neil Shapiro 
153*d39bd2c1SGregory Neil Shapiro /*
154*d39bd2c1SGregory Neil Shapiro **  MAP_RESET_CHGD -- reset MF_CHKED_CHGD in a map
155*d39bd2c1SGregory Neil Shapiro **
156*d39bd2c1SGregory Neil Shapiro **	Parameters:
157*d39bd2c1SGregory Neil Shapiro **		s -- STAB entry: if map: reset MF_CHKED_CHGD
158*d39bd2c1SGregory Neil Shapiro **		unused -- unused variable
159*d39bd2c1SGregory Neil Shapiro **
160*d39bd2c1SGregory Neil Shapiro **	Returns:
161*d39bd2c1SGregory Neil Shapiro **		none.
162*d39bd2c1SGregory Neil Shapiro */
163*d39bd2c1SGregory Neil Shapiro 
164*d39bd2c1SGregory Neil Shapiro static void map_reset_chged __P((STAB *, int));
165*d39bd2c1SGregory Neil Shapiro 
166*d39bd2c1SGregory Neil Shapiro /* ARGSUSED1 */
167*d39bd2c1SGregory Neil Shapiro static void
map_reset_chged(s,unused)168*d39bd2c1SGregory Neil Shapiro map_reset_chged(s, unused)
169*d39bd2c1SGregory Neil Shapiro 	STAB *s;
170*d39bd2c1SGregory Neil Shapiro 	int unused;
171*d39bd2c1SGregory Neil Shapiro {
172*d39bd2c1SGregory Neil Shapiro 	MAP *map;
173*d39bd2c1SGregory Neil Shapiro 
174*d39bd2c1SGregory Neil Shapiro 	/* has to be a map */
175*d39bd2c1SGregory Neil Shapiro 	if (ST_MAP != s->s_symtype
176*d39bd2c1SGregory Neil Shapiro #if _FFR_DYN_CLASS
177*d39bd2c1SGregory Neil Shapiro 	   && ST_DYNMAP != s->s_symtype
178*d39bd2c1SGregory Neil Shapiro #endif
179*d39bd2c1SGregory Neil Shapiro 	   )
180*d39bd2c1SGregory Neil Shapiro 		return;
181*d39bd2c1SGregory Neil Shapiro 	map = &s->s_map;
182*d39bd2c1SGregory Neil Shapiro 	if (!bitset(MF_VALID, map->map_mflags))
183*d39bd2c1SGregory Neil Shapiro 		return;
184*d39bd2c1SGregory Neil Shapiro 	if (tTd(38, 8))
185*d39bd2c1SGregory Neil Shapiro 		sm_dprintf("map_reset_chged: name=%s, checked=%d\n",
186*d39bd2c1SGregory Neil Shapiro 			map->map_mname, bitset(MF_CHKED_CHGD, map->map_mflags));
187*d39bd2c1SGregory Neil Shapiro 	map->map_mflags &= ~MF_CHKED_CHGD;
188*d39bd2c1SGregory Neil Shapiro }
189*d39bd2c1SGregory Neil Shapiro 
190*d39bd2c1SGregory Neil Shapiro /*
191*d39bd2c1SGregory Neil Shapiro **  MAPS_RESET_CHGD -- reset MF_CHKED_CHGD in all maps
192*d39bd2c1SGregory Neil Shapiro **
193*d39bd2c1SGregory Neil Shapiro **	Parameters:
194*d39bd2c1SGregory Neil Shapiro **		msg - caller (for debugging)
195*d39bd2c1SGregory Neil Shapiro **
196*d39bd2c1SGregory Neil Shapiro **	Returns:
197*d39bd2c1SGregory Neil Shapiro **		none.
198*d39bd2c1SGregory Neil Shapiro */
199*d39bd2c1SGregory Neil Shapiro 
200*d39bd2c1SGregory Neil Shapiro void
maps_reset_chged(msg)201*d39bd2c1SGregory Neil Shapiro maps_reset_chged(msg)
202*d39bd2c1SGregory Neil Shapiro 	const char *msg;
203*d39bd2c1SGregory Neil Shapiro {
204*d39bd2c1SGregory Neil Shapiro 	if (tTd(38, 16))
205*d39bd2c1SGregory Neil Shapiro 		sm_dprintf("maps_reset_chged: msg=%s\n", msg);
206*d39bd2c1SGregory Neil Shapiro 	stabapply(map_reset_chged, 0);
207*d39bd2c1SGregory Neil Shapiro }
208*d39bd2c1SGregory Neil Shapiro #endif /* _FFR_MAP_CHK_FILE > 1 */
209*d39bd2c1SGregory Neil Shapiro 
210*d39bd2c1SGregory Neil Shapiro 
211*d39bd2c1SGregory Neil Shapiro #if NEWDB || CDB || (NDBM && _FFR_MAP_CHK_FILE)
212*d39bd2c1SGregory Neil Shapiro static bool	smdb_add_extension __P((char *, int, char *, char *));
213*d39bd2c1SGregory Neil Shapiro 
214*d39bd2c1SGregory Neil Shapiro /*
215*d39bd2c1SGregory Neil Shapiro **  SMDB_ADD_EXTENSION -- Adds an extension to a file name.
216*d39bd2c1SGregory Neil Shapiro **
217*d39bd2c1SGregory Neil Shapiro **	Just adds a . followed by a string to a db_name if there
218*d39bd2c1SGregory Neil Shapiro **	is room and the db_name does not already have that extension.
219*d39bd2c1SGregory Neil Shapiro **
220*d39bd2c1SGregory Neil Shapiro **	Parameters:
221*d39bd2c1SGregory Neil Shapiro **		full_name -- The final file name.
222*d39bd2c1SGregory Neil Shapiro **		max_full_name_len -- The max length for full_name.
223*d39bd2c1SGregory Neil Shapiro **		db_name -- The name of the db.
224*d39bd2c1SGregory Neil Shapiro **		extension -- The extension to add.
225*d39bd2c1SGregory Neil Shapiro **
226*d39bd2c1SGregory Neil Shapiro **	Returns:
227*d39bd2c1SGregory Neil Shapiro **		SMDBE_OK -- Success.
228*d39bd2c1SGregory Neil Shapiro **		Anything else is an error. Look up more info about the
229*d39bd2c1SGregory Neil Shapiro **		error in the comments for the specific open() used.
230*d39bd2c1SGregory Neil Shapiro */
231*d39bd2c1SGregory Neil Shapiro 
232*d39bd2c1SGregory Neil Shapiro static bool
smdb_add_extension(full_name,max_full_name_len,db_name,extension)233*d39bd2c1SGregory Neil Shapiro smdb_add_extension(full_name, max_full_name_len, db_name, extension)
234*d39bd2c1SGregory Neil Shapiro 	char *full_name;
235*d39bd2c1SGregory Neil Shapiro 	int max_full_name_len;
236*d39bd2c1SGregory Neil Shapiro 	char *db_name;
237*d39bd2c1SGregory Neil Shapiro 	char *extension;
238*d39bd2c1SGregory Neil Shapiro {
239*d39bd2c1SGregory Neil Shapiro 	int extension_len;
240*d39bd2c1SGregory Neil Shapiro 	int db_name_len;
241*d39bd2c1SGregory Neil Shapiro 
242*d39bd2c1SGregory Neil Shapiro 	if (full_name == NULL || db_name == NULL || extension == NULL)
243*d39bd2c1SGregory Neil Shapiro 		return false; /* SMDBE_INVALID_PARAMETER; */
244*d39bd2c1SGregory Neil Shapiro 
245*d39bd2c1SGregory Neil Shapiro 	extension_len = strlen(extension);
246*d39bd2c1SGregory Neil Shapiro 	db_name_len = strlen(db_name);
247*d39bd2c1SGregory Neil Shapiro 
248*d39bd2c1SGregory Neil Shapiro 	if (extension_len + db_name_len + 2 > max_full_name_len)
249*d39bd2c1SGregory Neil Shapiro 		return false; /* SMDBE_DB_NAME_TOO_LONG; */
250*d39bd2c1SGregory Neil Shapiro 
251*d39bd2c1SGregory Neil Shapiro 	if (db_name_len < extension_len + 1 ||
252*d39bd2c1SGregory Neil Shapiro 	    db_name[db_name_len - extension_len - 1] != '.' ||
253*d39bd2c1SGregory Neil Shapiro 	    strcmp(&db_name[db_name_len - extension_len], extension) != 0)
254*d39bd2c1SGregory Neil Shapiro 		(void) sm_snprintf(full_name, max_full_name_len, "%s.%s",
255*d39bd2c1SGregory Neil Shapiro 				   db_name, extension);
256*d39bd2c1SGregory Neil Shapiro 	else
257*d39bd2c1SGregory Neil Shapiro 		(void) sm_strlcpy(full_name, db_name, max_full_name_len);
258*d39bd2c1SGregory Neil Shapiro 
259*d39bd2c1SGregory Neil Shapiro 	return true;
260*d39bd2c1SGregory Neil Shapiro }
261*d39bd2c1SGregory Neil Shapiro #endif /* NEWDB || CDB || (NDBM && _FFR_MAP_CHK_FILE) */
262*d39bd2c1SGregory Neil Shapiro 
263*d39bd2c1SGregory Neil Shapiro /*
264c2aa98e2SPeter Wemm **  MAP.C -- implementations for various map classes.
265c2aa98e2SPeter Wemm **
266c2aa98e2SPeter Wemm **	Each map class implements a series of functions:
267c2aa98e2SPeter Wemm **
268c2aa98e2SPeter Wemm **	bool map_parse(MAP *map, char *args)
26940266059SGregory Neil Shapiro **		Parse the arguments from the config file.  Return true
27040266059SGregory Neil Shapiro **		if they were ok, false otherwise.  Fill in map with the
271c2aa98e2SPeter Wemm **		values.
272c2aa98e2SPeter Wemm **
273c2aa98e2SPeter Wemm **	char *map_lookup(MAP *map, char *key, char **args, int *pstat)
274c2aa98e2SPeter Wemm **		Look up the key in the given map.  If found, do any
275c2aa98e2SPeter Wemm **		rewriting the map wants (including "args" if desired)
276c2aa98e2SPeter Wemm **		and return the value.  Set *pstat to the appropriate status
277c2aa98e2SPeter Wemm **		on error and return NULL.  Args will be NULL if called
278c2aa98e2SPeter Wemm **		from the alias routines, although this should probably
279c2aa98e2SPeter Wemm **		not be relied upon.  It is suggested you call map_rewrite
280c2aa98e2SPeter Wemm **		to return the results -- it takes care of null termination
281c2aa98e2SPeter Wemm **		and uses a dynamically expanded buffer as needed.
282c2aa98e2SPeter Wemm **
283c2aa98e2SPeter Wemm **	void map_store(MAP *map, char *key, char *value)
284c2aa98e2SPeter Wemm **		Store the key:value pair in the map.
285c2aa98e2SPeter Wemm **
286c2aa98e2SPeter Wemm **	bool map_open(MAP *map, int mode)
287c2aa98e2SPeter Wemm **		Open the map for the indicated mode.  Mode should
28840266059SGregory Neil Shapiro **		be either O_RDONLY or O_RDWR.  Return true if it
28940266059SGregory Neil Shapiro **		was opened successfully, false otherwise.  If the open
29040266059SGregory Neil Shapiro **		failed and the MF_OPTIONAL flag is not set, it should
291c2aa98e2SPeter Wemm **		also print an error.  If the MF_ALIAS bit is set
292c2aa98e2SPeter Wemm **		and this map class understands the @:@ convention, it
293c2aa98e2SPeter Wemm **		should call aliaswait() before returning.
294c2aa98e2SPeter Wemm **
295c2aa98e2SPeter Wemm **	void map_close(MAP *map)
296c2aa98e2SPeter Wemm **		Close the map.
297c2aa98e2SPeter Wemm **
298c2aa98e2SPeter Wemm **	This file also includes the implementation for getcanonname.
299c2aa98e2SPeter Wemm **	It is currently implemented in a pretty ad-hoc manner; it ought
300c2aa98e2SPeter Wemm **	to be more properly integrated into the map structure.
301c2aa98e2SPeter Wemm */
302c2aa98e2SPeter Wemm 
303*d39bd2c1SGregory Neil Shapiro /* XREF: conf.c must use the same expression */
304c2aa98e2SPeter Wemm #if O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL
305c2aa98e2SPeter Wemm # define LOCK_ON_OPEN	1	/* we can open/create a locked file */
3065b0945b5SGregory Neil Shapiro #else
307c2aa98e2SPeter Wemm # define LOCK_ON_OPEN	0	/* no such luck -- bend over backwards */
3085b0945b5SGregory Neil Shapiro #endif
309c2aa98e2SPeter Wemm 
31040266059SGregory Neil Shapiro /*
311c2aa98e2SPeter Wemm **  MAP_PARSEARGS -- parse config line arguments for database lookup
312c2aa98e2SPeter Wemm **
313c2aa98e2SPeter Wemm **	This is a generic version of the map_parse method.
314c2aa98e2SPeter Wemm **
315c2aa98e2SPeter Wemm **	Parameters:
316c2aa98e2SPeter Wemm **		map -- the map being initialized.
317c2aa98e2SPeter Wemm **		ap -- a pointer to the args on the config line.
318c2aa98e2SPeter Wemm **
319c2aa98e2SPeter Wemm **	Returns:
32040266059SGregory Neil Shapiro **		true -- if everything parsed OK.
32140266059SGregory Neil Shapiro **		false -- otherwise.
322c2aa98e2SPeter Wemm **
323c2aa98e2SPeter Wemm **	Side Effects:
324c2aa98e2SPeter Wemm **		null terminates the filename; stores it in map
325c2aa98e2SPeter Wemm */
326c2aa98e2SPeter Wemm 
327c2aa98e2SPeter Wemm bool
map_parseargs(map,ap)328c2aa98e2SPeter Wemm map_parseargs(map, ap)
329c2aa98e2SPeter Wemm 	MAP *map;
330c2aa98e2SPeter Wemm 	char *ap;
331c2aa98e2SPeter Wemm {
332c2aa98e2SPeter Wemm 	register char *p = ap;
333c2aa98e2SPeter Wemm 
33406f25ae9SGregory Neil Shapiro 	/*
33540266059SGregory Neil Shapiro 	**  There is no check whether there is really an argument,
33640266059SGregory Neil Shapiro 	**  but that's not important enough to warrant extra code.
33706f25ae9SGregory Neil Shapiro 	*/
33840266059SGregory Neil Shapiro 
339c2aa98e2SPeter Wemm 	map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL;
34006f25ae9SGregory Neil Shapiro 	map->map_spacesub = SpaceSub;	/* default value */
341c2aa98e2SPeter Wemm 	for (;;)
342c2aa98e2SPeter Wemm 	{
3435b0945b5SGregory Neil Shapiro 		while (SM_ISSPACE(*p))
344c2aa98e2SPeter Wemm 			p++;
345c2aa98e2SPeter Wemm 		if (*p != '-')
346c2aa98e2SPeter Wemm 			break;
347c2aa98e2SPeter Wemm 		switch (*++p)
348c2aa98e2SPeter Wemm 		{
349c2aa98e2SPeter Wemm 		  case 'A':
350c2aa98e2SPeter Wemm 			map->map_mflags |= MF_APPEND;
351c2aa98e2SPeter Wemm 			break;
352c2aa98e2SPeter Wemm 
353c2aa98e2SPeter Wemm 		  case 'a':
354c2aa98e2SPeter Wemm 			map->map_app = ++p;
355c2aa98e2SPeter Wemm 			break;
356c2aa98e2SPeter Wemm 
3575b0945b5SGregory Neil Shapiro 		  case 'D':
3585b0945b5SGregory Neil Shapiro 			map->map_mflags |= MF_DEFER;
3595b0945b5SGregory Neil Shapiro 			break;
3605b0945b5SGregory Neil Shapiro 
361da7d7b9cSGregory Neil Shapiro 		  case 'd':
362da7d7b9cSGregory Neil Shapiro 			{
363da7d7b9cSGregory Neil Shapiro 				char *h;
364da7d7b9cSGregory Neil Shapiro 
365da7d7b9cSGregory Neil Shapiro 				++p;
366da7d7b9cSGregory Neil Shapiro 				h = strchr(p, ' ');
367da7d7b9cSGregory Neil Shapiro 				if (h != NULL)
368da7d7b9cSGregory Neil Shapiro 					*h = '\0';
369da7d7b9cSGregory Neil Shapiro 				map->map_timeout = convtime(p, 's');
370da7d7b9cSGregory Neil Shapiro 				if (h != NULL)
371da7d7b9cSGregory Neil Shapiro 					*h = ' ';
372da7d7b9cSGregory Neil Shapiro 			}
373da7d7b9cSGregory Neil Shapiro 			break;
374da7d7b9cSGregory Neil Shapiro 
3755b0945b5SGregory Neil Shapiro 		  case 'f':
3765b0945b5SGregory Neil Shapiro 			map->map_mflags |= MF_NOFOLDCASE;
377c2aa98e2SPeter Wemm 			break;
378c2aa98e2SPeter Wemm 
379c2aa98e2SPeter Wemm 		  case 'k':
380c2aa98e2SPeter Wemm 			while (isascii(*++p) && isspace(*p))
381c2aa98e2SPeter Wemm 				continue;
382c2aa98e2SPeter Wemm 			map->map_keycolnm = p;
383c2aa98e2SPeter Wemm 			break;
384c2aa98e2SPeter Wemm 
3855b0945b5SGregory Neil Shapiro 		  case 'm':
3865b0945b5SGregory Neil Shapiro 			map->map_mflags |= MF_MATCHONLY;
3875b0945b5SGregory Neil Shapiro 			break;
3885b0945b5SGregory Neil Shapiro 
3895b0945b5SGregory Neil Shapiro 		  case 'N':
3905b0945b5SGregory Neil Shapiro 			map->map_mflags |= MF_INCLNULL;
3915b0945b5SGregory Neil Shapiro 			map->map_mflags &= ~MF_TRY0NULL;
3925b0945b5SGregory Neil Shapiro 			break;
3935b0945b5SGregory Neil Shapiro 
3945b0945b5SGregory Neil Shapiro 		  case 'O':
3955b0945b5SGregory Neil Shapiro 			map->map_mflags &= ~MF_TRY1NULL;
3965b0945b5SGregory Neil Shapiro 			break;
3975b0945b5SGregory Neil Shapiro 
3985b0945b5SGregory Neil Shapiro 		  case 'o':
3995b0945b5SGregory Neil Shapiro 			map->map_mflags |= MF_OPTIONAL;
4005b0945b5SGregory Neil Shapiro 			break;
4015b0945b5SGregory Neil Shapiro 
4025b0945b5SGregory Neil Shapiro 		  case 'q':
4035b0945b5SGregory Neil Shapiro 			map->map_mflags |= MF_KEEPQUOTES;
4045b0945b5SGregory Neil Shapiro 			break;
4055b0945b5SGregory Neil Shapiro 
4065b0945b5SGregory Neil Shapiro 		  case 'S':
4075b0945b5SGregory Neil Shapiro 			map->map_spacesub = *++p;
4085b0945b5SGregory Neil Shapiro 			break;
4095b0945b5SGregory Neil Shapiro 
4105b0945b5SGregory Neil Shapiro 		  case 'T':
4115b0945b5SGregory Neil Shapiro 			map->map_tapp = ++p;
4125b0945b5SGregory Neil Shapiro 			break;
4135b0945b5SGregory Neil Shapiro 
4145b0945b5SGregory Neil Shapiro 		  case 't':
4155b0945b5SGregory Neil Shapiro 			map->map_mflags |= MF_NODEFER;
4165b0945b5SGregory Neil Shapiro 			break;
4175b0945b5SGregory Neil Shapiro 
418c2aa98e2SPeter Wemm 		  case 'v':
419c2aa98e2SPeter Wemm 			while (isascii(*++p) && isspace(*p))
420c2aa98e2SPeter Wemm 				continue;
421c2aa98e2SPeter Wemm 			map->map_valcolnm = p;
422c2aa98e2SPeter Wemm 			break;
423c2aa98e2SPeter Wemm 
424c2aa98e2SPeter Wemm 		  case 'z':
425c2aa98e2SPeter Wemm 			if (*++p != '\\')
426c2aa98e2SPeter Wemm 				map->map_coldelim = *p;
427c2aa98e2SPeter Wemm 			else
428c2aa98e2SPeter Wemm 			{
429c2aa98e2SPeter Wemm 				switch (*++p)
430c2aa98e2SPeter Wemm 				{
431c2aa98e2SPeter Wemm 				  case 'n':
432c2aa98e2SPeter Wemm 					map->map_coldelim = '\n';
433c2aa98e2SPeter Wemm 					break;
434c2aa98e2SPeter Wemm 
435c2aa98e2SPeter Wemm 				  case 't':
436c2aa98e2SPeter Wemm 					map->map_coldelim = '\t';
437c2aa98e2SPeter Wemm 					break;
438c2aa98e2SPeter Wemm 
439c2aa98e2SPeter Wemm 				  default:
440c2aa98e2SPeter Wemm 					map->map_coldelim = '\\';
441c2aa98e2SPeter Wemm 				}
442c2aa98e2SPeter Wemm 			}
443c2aa98e2SPeter Wemm 			break;
444c2aa98e2SPeter Wemm 
44506f25ae9SGregory Neil Shapiro 		  default:
44606f25ae9SGregory Neil Shapiro 			syserr("Illegal option %c map %s", *p, map->map_mname);
44706f25ae9SGregory Neil Shapiro 			break;
448c2aa98e2SPeter Wemm 		}
4495b0945b5SGregory Neil Shapiro 		while (*p != '\0' && !(SM_ISSPACE(*p)))
450c2aa98e2SPeter Wemm 			p++;
451c2aa98e2SPeter Wemm 		if (*p != '\0')
452c2aa98e2SPeter Wemm 			*p++ = '\0';
453c2aa98e2SPeter Wemm 	}
454c2aa98e2SPeter Wemm 	if (map->map_app != NULL)
455c2aa98e2SPeter Wemm 		map->map_app = newstr(map->map_app);
456c2aa98e2SPeter Wemm 	if (map->map_tapp != NULL)
457c2aa98e2SPeter Wemm 		map->map_tapp = newstr(map->map_tapp);
458c2aa98e2SPeter Wemm 	if (map->map_keycolnm != NULL)
459c2aa98e2SPeter Wemm 		map->map_keycolnm = newstr(map->map_keycolnm);
460c2aa98e2SPeter Wemm 	if (map->map_valcolnm != NULL)
461c2aa98e2SPeter Wemm 		map->map_valcolnm = newstr(map->map_valcolnm);
462c2aa98e2SPeter Wemm 
463c2aa98e2SPeter Wemm 	if (*p != '\0')
464c2aa98e2SPeter Wemm 	{
465c2aa98e2SPeter Wemm 		map->map_file = p;
4665b0945b5SGregory Neil Shapiro 		while (*p != '\0' && !(SM_ISSPACE(*p)))
467c2aa98e2SPeter Wemm 			p++;
468c2aa98e2SPeter Wemm 		if (*p != '\0')
469c2aa98e2SPeter Wemm 			*p++ = '\0';
470c2aa98e2SPeter Wemm 		map->map_file = newstr(map->map_file);
471c2aa98e2SPeter Wemm 	}
472c2aa98e2SPeter Wemm 
4735b0945b5SGregory Neil Shapiro 	while (*p != '\0' && SM_ISSPACE(*p))
474c2aa98e2SPeter Wemm 		p++;
475c2aa98e2SPeter Wemm 	if (*p != '\0')
476c2aa98e2SPeter Wemm 		map->map_rebuild = newstr(p);
477c2aa98e2SPeter Wemm 
478c2aa98e2SPeter Wemm 	if (map->map_file == NULL &&
479c2aa98e2SPeter Wemm 	    !bitset(MCF_OPTFILE, map->map_class->map_cflags))
480c2aa98e2SPeter Wemm 	{
481c2aa98e2SPeter Wemm 		syserr("No file name for %s map %s",
482c2aa98e2SPeter Wemm 			map->map_class->map_cname, map->map_mname);
48340266059SGregory Neil Shapiro 		return false;
484c2aa98e2SPeter Wemm 	}
48540266059SGregory Neil Shapiro 	return true;
486c2aa98e2SPeter Wemm }
48740266059SGregory Neil Shapiro /*
488c2aa98e2SPeter Wemm **  MAP_REWRITE -- rewrite a database key, interpolating %n indications.
489c2aa98e2SPeter Wemm **
490c2aa98e2SPeter Wemm **	It also adds the map_app string.  It can be used as a utility
491c2aa98e2SPeter Wemm **	in the map_lookup method.
492c2aa98e2SPeter Wemm **
493c2aa98e2SPeter Wemm **	Parameters:
494c2aa98e2SPeter Wemm **		map -- the map that causes this.
495c2aa98e2SPeter Wemm **		s -- the string to rewrite, NOT necessarily null terminated.
496c2aa98e2SPeter Wemm **		slen -- the length of s.
497c2aa98e2SPeter Wemm **		av -- arguments to interpolate into buf.
498c2aa98e2SPeter Wemm **
499c2aa98e2SPeter Wemm **	Returns:
500c2aa98e2SPeter Wemm **		Pointer to rewritten result.  This is static data that
501c2aa98e2SPeter Wemm **		should be copied if it is to be saved!
502c2aa98e2SPeter Wemm */
503c2aa98e2SPeter Wemm 
504c2aa98e2SPeter Wemm char *
map_rewrite(map,s,slen,av)505c2aa98e2SPeter Wemm map_rewrite(map, s, slen, av)
506c2aa98e2SPeter Wemm 	register MAP *map;
507c2aa98e2SPeter Wemm 	register const char *s;
508c2aa98e2SPeter Wemm 	size_t slen;
509c2aa98e2SPeter Wemm 	char **av;
510c2aa98e2SPeter Wemm {
511c2aa98e2SPeter Wemm 	register char *bp;
512c2aa98e2SPeter Wemm 	register char c;
513c2aa98e2SPeter Wemm 	char **avp;
514c2aa98e2SPeter Wemm 	register char *ap;
515c2aa98e2SPeter Wemm 	size_t l;
516c2aa98e2SPeter Wemm 	size_t len;
517c2aa98e2SPeter Wemm 	static size_t buflen = 0;
518c2aa98e2SPeter Wemm 	static char *buf = NULL;
519c2aa98e2SPeter Wemm 
520c2aa98e2SPeter Wemm 	if (tTd(39, 1))
521c2aa98e2SPeter Wemm 	{
52240266059SGregory Neil Shapiro 		sm_dprintf("map_rewrite(%.*s), av =", (int) slen, s);
523c2aa98e2SPeter Wemm 		if (av == NULL)
52440266059SGregory Neil Shapiro 			sm_dprintf(" (nullv)");
525c2aa98e2SPeter Wemm 		else
526c2aa98e2SPeter Wemm 		{
527c2aa98e2SPeter Wemm 			for (avp = av; *avp != NULL; avp++)
52840266059SGregory Neil Shapiro 				sm_dprintf("\n\t%s", *avp);
529c2aa98e2SPeter Wemm 		}
53040266059SGregory Neil Shapiro 		sm_dprintf("\n");
531c2aa98e2SPeter Wemm 	}
532c2aa98e2SPeter Wemm 
533c2aa98e2SPeter Wemm 	/* count expected size of output (can safely overestimate) */
534c2aa98e2SPeter Wemm 	l = len = slen;
535c2aa98e2SPeter Wemm 	if (av != NULL)
536c2aa98e2SPeter Wemm 	{
537c2aa98e2SPeter Wemm 		const char *sp = s;
538c2aa98e2SPeter Wemm 
539c2aa98e2SPeter Wemm 		while (l-- > 0 && (c = *sp++) != '\0')
540c2aa98e2SPeter Wemm 		{
541c2aa98e2SPeter Wemm 			if (c != '%')
542c2aa98e2SPeter Wemm 				continue;
543c2aa98e2SPeter Wemm 			if (l-- <= 0)
544c2aa98e2SPeter Wemm 				break;
545c2aa98e2SPeter Wemm 			c = *sp++;
546c2aa98e2SPeter Wemm 			if (!(isascii(c) && isdigit(c)))
547c2aa98e2SPeter Wemm 				continue;
548c2aa98e2SPeter Wemm 			for (avp = av; --c >= '0' && *avp != NULL; avp++)
549c2aa98e2SPeter Wemm 				continue;
550c2aa98e2SPeter Wemm 			if (*avp == NULL)
551c2aa98e2SPeter Wemm 				continue;
552c2aa98e2SPeter Wemm 			len += strlen(*avp);
553c2aa98e2SPeter Wemm 		}
554c2aa98e2SPeter Wemm 	}
555c2aa98e2SPeter Wemm 	if (map->map_app != NULL)
556c2aa98e2SPeter Wemm 		len += strlen(map->map_app);
557c2aa98e2SPeter Wemm 	if (buflen < ++len)
558c2aa98e2SPeter Wemm 	{
559c2aa98e2SPeter Wemm 		/* need to malloc additional space */
560c2aa98e2SPeter Wemm 		buflen = len;
5612fb4f839SGregory Neil Shapiro 		SM_FREE(buf);
56240266059SGregory Neil Shapiro 		buf = sm_pmalloc_x(buflen);
563c2aa98e2SPeter Wemm 	}
564c2aa98e2SPeter Wemm 
565c2aa98e2SPeter Wemm 	bp = buf;
566c2aa98e2SPeter Wemm 	if (av == NULL)
567c2aa98e2SPeter Wemm 	{
56806f25ae9SGregory Neil Shapiro 		memmove(bp, s, slen);
569c2aa98e2SPeter Wemm 		bp += slen;
57006f25ae9SGregory Neil Shapiro 
57106f25ae9SGregory Neil Shapiro 		/* assert(len > slen); */
57206f25ae9SGregory Neil Shapiro 		len -= slen;
573c2aa98e2SPeter Wemm 	}
574c2aa98e2SPeter Wemm 	else
575c2aa98e2SPeter Wemm 	{
576c2aa98e2SPeter Wemm 		while (slen-- > 0 && (c = *s++) != '\0')
577c2aa98e2SPeter Wemm 		{
578c2aa98e2SPeter Wemm 			if (c != '%')
579c2aa98e2SPeter Wemm 			{
580c2aa98e2SPeter Wemm   pushc:
581a7ec597cSGregory Neil Shapiro 				if (len-- <= 1)
58206f25ae9SGregory Neil Shapiro 				     break;
583c2aa98e2SPeter Wemm 				*bp++ = c;
584c2aa98e2SPeter Wemm 				continue;
585c2aa98e2SPeter Wemm 			}
586c2aa98e2SPeter Wemm 			if (slen-- <= 0 || (c = *s++) == '\0')
587c2aa98e2SPeter Wemm 				c = '%';
588c2aa98e2SPeter Wemm 			if (c == '%')
589c2aa98e2SPeter Wemm 				goto pushc;
590c2aa98e2SPeter Wemm 			if (!(isascii(c) && isdigit(c)))
591c2aa98e2SPeter Wemm 			{
592a7ec597cSGregory Neil Shapiro 				if (len-- <= 1)
593a7ec597cSGregory Neil Shapiro 				     break;
594c2aa98e2SPeter Wemm 				*bp++ = '%';
595c2aa98e2SPeter Wemm 				goto pushc;
596c2aa98e2SPeter Wemm 			}
597c2aa98e2SPeter Wemm 			for (avp = av; --c >= '0' && *avp != NULL; avp++)
598c2aa98e2SPeter Wemm 				continue;
599c2aa98e2SPeter Wemm 			if (*avp == NULL)
600c2aa98e2SPeter Wemm 				continue;
601c2aa98e2SPeter Wemm 
602c2aa98e2SPeter Wemm 			/* transliterate argument into output string */
60306f25ae9SGregory Neil Shapiro 			for (ap = *avp; (c = *ap++) != '\0' && len > 0; --len)
604c2aa98e2SPeter Wemm 				*bp++ = c;
605c2aa98e2SPeter Wemm 		}
606c2aa98e2SPeter Wemm 	}
60706f25ae9SGregory Neil Shapiro 	if (map->map_app != NULL && len > 0)
60840266059SGregory Neil Shapiro 		(void) sm_strlcpy(bp, map->map_app, len);
609c2aa98e2SPeter Wemm 	else
610c2aa98e2SPeter Wemm 		*bp = '\0';
6112fb4f839SGregory Neil Shapiro #if _FFR_8BITENVADDR
6122fb4f839SGregory Neil Shapiro 	if (!bitset(MF_KEEPXFMT, map->map_mflags))
6132fb4f839SGregory Neil Shapiro 	{
6142fb4f839SGregory Neil Shapiro 		int newlen;
6152fb4f839SGregory Neil Shapiro 		char *quoted;
6162fb4f839SGregory Neil Shapiro 
6172fb4f839SGregory Neil Shapiro 		newlen = 0;
6182fb4f839SGregory Neil Shapiro 		quoted = quote_internal_chars(buf, NULL, &newlen, NULL);
6192fb4f839SGregory Neil Shapiro 		if (newlen > buflen)
6202fb4f839SGregory Neil Shapiro 		{
6212fb4f839SGregory Neil Shapiro 			buflen = newlen;
6222fb4f839SGregory Neil Shapiro 			SM_FREE(buf);
6232fb4f839SGregory Neil Shapiro 			buf = sm_pmalloc_x(buflen);
6242fb4f839SGregory Neil Shapiro 		}
6252fb4f839SGregory Neil Shapiro 		(void) sm_strlcpy(buf, quoted, buflen);
6262fb4f839SGregory Neil Shapiro 		SM_FREE(quoted);
6272fb4f839SGregory Neil Shapiro 	}
6282fb4f839SGregory Neil Shapiro #endif
629c2aa98e2SPeter Wemm 	if (tTd(39, 1))
63040266059SGregory Neil Shapiro 		sm_dprintf("map_rewrite => %s\n", buf);
631c2aa98e2SPeter Wemm 	return buf;
632c2aa98e2SPeter Wemm }
633*d39bd2c1SGregory Neil Shapiro 
634*d39bd2c1SGregory Neil Shapiro /*
635*d39bd2c1SGregory Neil Shapiro **  MAPCHOWN -- if available fchown() the fds to TrustedUid
636*d39bd2c1SGregory Neil Shapiro **
637*d39bd2c1SGregory Neil Shapiro **	Parameters:
638*d39bd2c1SGregory Neil Shapiro **		mapname - name of map (for error reporting)
639*d39bd2c1SGregory Neil Shapiro **		fd0 - first fd (must be valid)
640*d39bd2c1SGregory Neil Shapiro **		fd1 - second fd (<0: do not use)
641*d39bd2c1SGregory Neil Shapiro **		filename - name of file (for error reporting)
642*d39bd2c1SGregory Neil Shapiro **
643*d39bd2c1SGregory Neil Shapiro **	Returns:
644*d39bd2c1SGregory Neil Shapiro **		none.
645*d39bd2c1SGregory Neil Shapiro */
646*d39bd2c1SGregory Neil Shapiro 
647*d39bd2c1SGregory Neil Shapiro static void mapchown __P((const char *, int, int, const char *));
648*d39bd2c1SGregory Neil Shapiro 
649*d39bd2c1SGregory Neil Shapiro static void
mapchown(mapname,fd0,fd1,filename)650*d39bd2c1SGregory Neil Shapiro mapchown(mapname, fd0, fd1, filename)
651*d39bd2c1SGregory Neil Shapiro 	const char *mapname;
652*d39bd2c1SGregory Neil Shapiro 	int fd0;
653*d39bd2c1SGregory Neil Shapiro 	int fd1;
654*d39bd2c1SGregory Neil Shapiro 	const char *filename;
655*d39bd2c1SGregory Neil Shapiro {
656*d39bd2c1SGregory Neil Shapiro 	if (!(geteuid() == 0 && TrustedUid != 0))
657*d39bd2c1SGregory Neil Shapiro 		return;
658*d39bd2c1SGregory Neil Shapiro #if HASFCHOWN
659*d39bd2c1SGregory Neil Shapiro 	if (fchown(fd0, TrustedUid, -1) < 0 ||
660*d39bd2c1SGregory Neil Shapiro 	    (fd1 >= 0 && fchown(fd1, TrustedUid, -1) < 0))
661*d39bd2c1SGregory Neil Shapiro 	{
662*d39bd2c1SGregory Neil Shapiro 		int err = errno;
663*d39bd2c1SGregory Neil Shapiro 
664*d39bd2c1SGregory Neil Shapiro 		sm_syslog(LOG_ALERT, NOQID,
665*d39bd2c1SGregory Neil Shapiro 			  "ownership change on %s failed: %s",
666*d39bd2c1SGregory Neil Shapiro 			  filename, sm_errstring(err));
667*d39bd2c1SGregory Neil Shapiro 		message("050 ownership change on %s failed: %s",
668*d39bd2c1SGregory Neil Shapiro 			filename, sm_errstring(err));
669*d39bd2c1SGregory Neil Shapiro 	}
670*d39bd2c1SGregory Neil Shapiro #else /* HASFCHOWN */
671*d39bd2c1SGregory Neil Shapiro 	sm_syslog(LOG_ALERT, NOQID,
672*d39bd2c1SGregory Neil Shapiro 		  "no fchown(): cannot change ownership on %s",
673*d39bd2c1SGregory Neil Shapiro 		  mapname);
674*d39bd2c1SGregory Neil Shapiro 	message("050 no fchown(): cannot change ownership on %s",
675*d39bd2c1SGregory Neil Shapiro 		mapname);
676*d39bd2c1SGregory Neil Shapiro #endif /* HASFCHOWN */
677*d39bd2c1SGregory Neil Shapiro }
678*d39bd2c1SGregory Neil Shapiro 
67940266059SGregory Neil Shapiro /*
68006f25ae9SGregory Neil Shapiro **  INITMAPS -- rebuild alias maps
681c2aa98e2SPeter Wemm **
682c2aa98e2SPeter Wemm **	Parameters:
68306f25ae9SGregory Neil Shapiro **		none.
68406f25ae9SGregory Neil Shapiro **
68506f25ae9SGregory Neil Shapiro **	Returns:
68606f25ae9SGregory Neil Shapiro **		none.
68706f25ae9SGregory Neil Shapiro */
68806f25ae9SGregory Neil Shapiro 
68906f25ae9SGregory Neil Shapiro void
initmaps()69006f25ae9SGregory Neil Shapiro initmaps()
69106f25ae9SGregory Neil Shapiro {
69206f25ae9SGregory Neil Shapiro 	checkfd012("entering initmaps");
69306f25ae9SGregory Neil Shapiro 	stabapply(map_init, 0);
69406f25ae9SGregory Neil Shapiro 	checkfd012("exiting initmaps");
69506f25ae9SGregory Neil Shapiro }
696*d39bd2c1SGregory Neil Shapiro 
69740266059SGregory Neil Shapiro /*
69806f25ae9SGregory Neil Shapiro **  MAP_INIT -- rebuild a map
69906f25ae9SGregory Neil Shapiro **
70006f25ae9SGregory Neil Shapiro **	Parameters:
70106f25ae9SGregory Neil Shapiro **		s -- STAB entry: if map: try to rebuild
70206f25ae9SGregory Neil Shapiro **		unused -- unused variable
703c2aa98e2SPeter Wemm **
704c2aa98e2SPeter Wemm **	Returns:
705c2aa98e2SPeter Wemm **		none.
706c2aa98e2SPeter Wemm **
707c2aa98e2SPeter Wemm **	Side Effects:
70806f25ae9SGregory Neil Shapiro **		will close already open rebuildable map.
709c2aa98e2SPeter Wemm */
710c2aa98e2SPeter Wemm 
71106f25ae9SGregory Neil Shapiro /* ARGSUSED1 */
71206f25ae9SGregory Neil Shapiro static void
map_init(s,unused)71306f25ae9SGregory Neil Shapiro map_init(s, unused)
714c2aa98e2SPeter Wemm 	register STAB *s;
71506f25ae9SGregory Neil Shapiro 	int unused;
716c2aa98e2SPeter Wemm {
717c2aa98e2SPeter Wemm 	register MAP *map;
718c2aa98e2SPeter Wemm 
719c2aa98e2SPeter Wemm 	/* has to be a map */
72040266059SGregory Neil Shapiro 	if (s->s_symtype != ST_MAP)
721c2aa98e2SPeter Wemm 		return;
722c2aa98e2SPeter Wemm 
723c2aa98e2SPeter Wemm 	map = &s->s_map;
724c2aa98e2SPeter Wemm 	if (!bitset(MF_VALID, map->map_mflags))
725c2aa98e2SPeter Wemm 		return;
726c2aa98e2SPeter Wemm 
727c2aa98e2SPeter Wemm 	if (tTd(38, 2))
72840266059SGregory Neil Shapiro 		sm_dprintf("map_init(%s:%s, %s)\n",
729c2aa98e2SPeter Wemm 			map->map_class->map_cname == NULL ? "NULL" :
730c2aa98e2SPeter Wemm 				map->map_class->map_cname,
731c2aa98e2SPeter Wemm 			map->map_mname == NULL ? "NULL" : map->map_mname,
73206f25ae9SGregory Neil Shapiro 			map->map_file == NULL ? "NULL" : map->map_file);
733c2aa98e2SPeter Wemm 
73406f25ae9SGregory Neil Shapiro 	if (!bitset(MF_ALIAS, map->map_mflags) ||
73506f25ae9SGregory Neil Shapiro 	    !bitset(MCF_REBUILDABLE, map->map_class->map_cflags))
736c2aa98e2SPeter Wemm 	{
737c2aa98e2SPeter Wemm 		if (tTd(38, 3))
73840266059SGregory Neil Shapiro 			sm_dprintf("\tnot rebuildable\n");
739c2aa98e2SPeter Wemm 		return;
740c2aa98e2SPeter Wemm 	}
741c2aa98e2SPeter Wemm 
742c2aa98e2SPeter Wemm 	/* if already open, close it (for nested open) */
743c2aa98e2SPeter Wemm 	if (bitset(MF_OPEN, map->map_mflags))
744c2aa98e2SPeter Wemm 	{
7458774250cSGregory Neil Shapiro 		map->map_mflags |= MF_CLOSING;
746c2aa98e2SPeter Wemm 		map->map_class->map_close(map);
7478774250cSGregory Neil Shapiro 		map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING);
748c2aa98e2SPeter Wemm 	}
749c2aa98e2SPeter Wemm 
750*d39bd2c1SGregory Neil Shapiro 	(void) rebuildaliases(map);
751c2aa98e2SPeter Wemm 	return;
752c2aa98e2SPeter Wemm }
75340266059SGregory Neil Shapiro /*
75406f25ae9SGregory Neil Shapiro **  OPENMAP -- open a map
75506f25ae9SGregory Neil Shapiro **
75606f25ae9SGregory Neil Shapiro **	Parameters:
75706f25ae9SGregory Neil Shapiro **		map -- map to open (it must not be open).
75806f25ae9SGregory Neil Shapiro **
75906f25ae9SGregory Neil Shapiro **	Returns:
76006f25ae9SGregory Neil Shapiro **		whether open succeeded.
76106f25ae9SGregory Neil Shapiro */
762c2aa98e2SPeter Wemm 
76306f25ae9SGregory Neil Shapiro bool
openmap(map)76406f25ae9SGregory Neil Shapiro openmap(map)
76506f25ae9SGregory Neil Shapiro 	MAP *map;
76606f25ae9SGregory Neil Shapiro {
76740266059SGregory Neil Shapiro 	bool restore = false;
76806f25ae9SGregory Neil Shapiro 	bool savehold = HoldErrs;
76906f25ae9SGregory Neil Shapiro 	bool savequick = QuickAbort;
77006f25ae9SGregory Neil Shapiro 	int saveerrors = Errors;
77106f25ae9SGregory Neil Shapiro 
77206f25ae9SGregory Neil Shapiro 	if (!bitset(MF_VALID, map->map_mflags))
77340266059SGregory Neil Shapiro 		return false;
77406f25ae9SGregory Neil Shapiro 
77506f25ae9SGregory Neil Shapiro 	/* better safe than sorry... */
77606f25ae9SGregory Neil Shapiro 	if (bitset(MF_OPEN, map->map_mflags))
77740266059SGregory Neil Shapiro 		return true;
77806f25ae9SGregory Neil Shapiro 
77906f25ae9SGregory Neil Shapiro 	/* Don't send a map open error out via SMTP */
78006f25ae9SGregory Neil Shapiro 	if ((OnlyOneError || QuickAbort) &&
78106f25ae9SGregory Neil Shapiro 	    (OpMode == MD_SMTP || OpMode == MD_DAEMON))
78206f25ae9SGregory Neil Shapiro 	{
78340266059SGregory Neil Shapiro 		restore = true;
78440266059SGregory Neil Shapiro 		HoldErrs = true;
78540266059SGregory Neil Shapiro 		QuickAbort = false;
78606f25ae9SGregory Neil Shapiro 	}
78706f25ae9SGregory Neil Shapiro 
78806f25ae9SGregory Neil Shapiro 	errno = 0;
789c2aa98e2SPeter Wemm 	if (map->map_class->map_open(map, O_RDONLY))
790c2aa98e2SPeter Wemm 	{
791c2aa98e2SPeter Wemm 		if (tTd(38, 4))
79240266059SGregory Neil Shapiro 			sm_dprintf("openmap()\t%s:%s %s: valid\n",
793c2aa98e2SPeter Wemm 				map->map_class->map_cname == NULL ? "NULL" :
794c2aa98e2SPeter Wemm 					map->map_class->map_cname,
795c2aa98e2SPeter Wemm 				map->map_mname == NULL ? "NULL" :
796c2aa98e2SPeter Wemm 					map->map_mname,
797c2aa98e2SPeter Wemm 				map->map_file == NULL ? "NULL" :
798c2aa98e2SPeter Wemm 					map->map_file);
799c2aa98e2SPeter Wemm 		map->map_mflags |= MF_OPEN;
80040266059SGregory Neil Shapiro 		map->map_pid = CurrentPid;
801c2aa98e2SPeter Wemm 	}
802c2aa98e2SPeter Wemm 	else
803c2aa98e2SPeter Wemm 	{
804c2aa98e2SPeter Wemm 		if (tTd(38, 4))
80540266059SGregory Neil Shapiro 			sm_dprintf("openmap()\t%s:%s %s: invalid%s%s\n",
806c2aa98e2SPeter Wemm 				map->map_class->map_cname == NULL ? "NULL" :
807c2aa98e2SPeter Wemm 					map->map_class->map_cname,
808c2aa98e2SPeter Wemm 				map->map_mname == NULL ? "NULL" :
809c2aa98e2SPeter Wemm 					map->map_mname,
810c2aa98e2SPeter Wemm 				map->map_file == NULL ? "NULL" :
811c2aa98e2SPeter Wemm 					map->map_file,
81206f25ae9SGregory Neil Shapiro 				errno == 0 ? "" : ": ",
81340266059SGregory Neil Shapiro 				errno == 0 ? "" : sm_errstring(errno));
814c2aa98e2SPeter Wemm 		if (!bitset(MF_OPTIONAL, map->map_mflags))
815c2aa98e2SPeter Wemm 		{
816c2aa98e2SPeter Wemm 			extern MAPCLASS BogusMapClass;
817c2aa98e2SPeter Wemm 
81840266059SGregory Neil Shapiro 			map->map_orgclass = map->map_class;
819c2aa98e2SPeter Wemm 			map->map_class = &BogusMapClass;
82040266059SGregory Neil Shapiro 			map->map_mflags |= MF_OPEN|MF_OPENBOGUS;
82140266059SGregory Neil Shapiro 			map->map_pid = CurrentPid;
822c2aa98e2SPeter Wemm 		}
82306f25ae9SGregory Neil Shapiro 		else
82406f25ae9SGregory Neil Shapiro 		{
82506f25ae9SGregory Neil Shapiro 			/* don't try again */
82606f25ae9SGregory Neil Shapiro 			map->map_mflags &= ~MF_VALID;
827c2aa98e2SPeter Wemm 		}
828c2aa98e2SPeter Wemm 	}
82906f25ae9SGregory Neil Shapiro 
83006f25ae9SGregory Neil Shapiro 	if (restore)
83106f25ae9SGregory Neil Shapiro 	{
83206f25ae9SGregory Neil Shapiro 		Errors = saveerrors;
83306f25ae9SGregory Neil Shapiro 		HoldErrs = savehold;
83406f25ae9SGregory Neil Shapiro 		QuickAbort = savequick;
83506f25ae9SGregory Neil Shapiro 	}
83606f25ae9SGregory Neil Shapiro 
83706f25ae9SGregory Neil Shapiro 	return bitset(MF_OPEN, map->map_mflags);
83806f25ae9SGregory Neil Shapiro }
83940266059SGregory Neil Shapiro /*
840065a643dSPeter Wemm **  CLOSEMAPS -- close all open maps opened by the current pid.
841065a643dSPeter Wemm **
842065a643dSPeter Wemm **	Parameters:
84340266059SGregory Neil Shapiro **		bogus -- only close bogus maps.
844065a643dSPeter Wemm **
845065a643dSPeter Wemm **	Returns:
846065a643dSPeter Wemm **		none.
847065a643dSPeter Wemm */
848065a643dSPeter Wemm 
849065a643dSPeter Wemm void
closemaps(bogus)85040266059SGregory Neil Shapiro closemaps(bogus)
85140266059SGregory Neil Shapiro 	bool bogus;
852065a643dSPeter Wemm {
85340266059SGregory Neil Shapiro 	stabapply(map_close, bogus);
854065a643dSPeter Wemm }
85540266059SGregory Neil Shapiro /*
85606f25ae9SGregory Neil Shapiro **  MAP_CLOSE -- close a map opened by the current pid.
85706f25ae9SGregory Neil Shapiro **
85806f25ae9SGregory Neil Shapiro **	Parameters:
85940266059SGregory Neil Shapiro **		s -- STAB entry: if map: try to close
86040266059SGregory Neil Shapiro **		bogus -- only close bogus maps or MCF_NOTPERSIST maps.
86106f25ae9SGregory Neil Shapiro **
86206f25ae9SGregory Neil Shapiro **	Returns:
86306f25ae9SGregory Neil Shapiro **		none.
86406f25ae9SGregory Neil Shapiro */
865065a643dSPeter Wemm 
86606f25ae9SGregory Neil Shapiro static void
map_close(s,bogus)86740266059SGregory Neil Shapiro map_close(s, bogus)
868065a643dSPeter Wemm 	register STAB *s;
86940266059SGregory Neil Shapiro 	int bogus;	/* int because of stabapply(), used as bool */
870065a643dSPeter Wemm {
871065a643dSPeter Wemm 	MAP *map;
87240266059SGregory Neil Shapiro 	extern MAPCLASS BogusMapClass;
873065a643dSPeter Wemm 
87440266059SGregory Neil Shapiro 	if (s->s_symtype != ST_MAP)
875065a643dSPeter Wemm 		return;
876065a643dSPeter Wemm 
877065a643dSPeter Wemm 	map = &s->s_map;
878065a643dSPeter Wemm 
87940266059SGregory Neil Shapiro 	/*
88040266059SGregory Neil Shapiro 	**  close the map iff:
88140266059SGregory Neil Shapiro 	**  it is valid and open and opened by this process
88240266059SGregory Neil Shapiro 	**  and (!bogus or it's a bogus map or it is not persistent)
88340266059SGregory Neil Shapiro 	**  negate this: return iff
88440266059SGregory Neil Shapiro 	**  it is not valid or it is not open or not opened by this process
88540266059SGregory Neil Shapiro 	**  or (bogus and it's not a bogus map and it's not not-persistent)
88640266059SGregory Neil Shapiro 	*/
88740266059SGregory Neil Shapiro 
888065a643dSPeter Wemm 	if (!bitset(MF_VALID, map->map_mflags) ||
889065a643dSPeter Wemm 	    !bitset(MF_OPEN, map->map_mflags) ||
8908774250cSGregory Neil Shapiro 	    bitset(MF_CLOSING, map->map_mflags) ||
89140266059SGregory Neil Shapiro 	    map->map_pid != CurrentPid ||
89240266059SGregory Neil Shapiro 	    (bogus && map->map_class != &BogusMapClass &&
89340266059SGregory Neil Shapiro 	     !bitset(MCF_NOTPERSIST, map->map_class->map_cflags)))
894065a643dSPeter Wemm 		return;
895065a643dSPeter Wemm 
89640266059SGregory Neil Shapiro 	if (map->map_class == &BogusMapClass && map->map_orgclass != NULL &&
89740266059SGregory Neil Shapiro 	    map->map_orgclass != &BogusMapClass)
89840266059SGregory Neil Shapiro 		map->map_class = map->map_orgclass;
899065a643dSPeter Wemm 	if (tTd(38, 5))
90040266059SGregory Neil Shapiro 		sm_dprintf("closemaps: closing %s (%s)\n",
901065a643dSPeter Wemm 			map->map_mname == NULL ? "NULL" : map->map_mname,
902065a643dSPeter Wemm 			map->map_file == NULL ? "NULL" : map->map_file);
903065a643dSPeter Wemm 
90440266059SGregory Neil Shapiro 	if (!bitset(MF_OPENBOGUS, map->map_mflags))
90540266059SGregory Neil Shapiro 	{
9068774250cSGregory Neil Shapiro 		map->map_mflags |= MF_CLOSING;
907065a643dSPeter Wemm 		map->map_class->map_close(map);
908065a643dSPeter Wemm 	}
909*d39bd2c1SGregory Neil Shapiro 	map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_OPENBOGUS|MF_CLOSING|MF_CHKED_CHGD);
91040266059SGregory Neil Shapiro }
911d0cef73dSGregory Neil Shapiro 
912d0cef73dSGregory Neil Shapiro #if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN)
913d0cef73dSGregory Neil Shapiro extern int getdomainname();
914d0cef73dSGregory Neil Shapiro 
915d0cef73dSGregory Neil Shapiro /* this is mainly for backward compatibility in Sun environment */
916d0cef73dSGregory Neil Shapiro static char *
sun_init_domain()917d0cef73dSGregory Neil Shapiro sun_init_domain()
918d0cef73dSGregory Neil Shapiro {
919d0cef73dSGregory Neil Shapiro 	/*
920d0cef73dSGregory Neil Shapiro 	**  Get the domain name from the kernel.
921d0cef73dSGregory Neil Shapiro 	**  If it does not start with a leading dot, then remove
922d0cef73dSGregory Neil Shapiro 	**  the first component.  Since leading dots are funny Unix
923d0cef73dSGregory Neil Shapiro 	**  files, we treat a leading "+" the same as a leading dot.
924d0cef73dSGregory Neil Shapiro 	**  Finally, force there to be at least one dot in the domain name
925d0cef73dSGregory Neil Shapiro 	**  (i.e. top-level domains are not allowed, like "com", must be
926d0cef73dSGregory Neil Shapiro 	**  something like "sun.com").
927d0cef73dSGregory Neil Shapiro 	*/
928d0cef73dSGregory Neil Shapiro 
9292fb4f839SGregory Neil Shapiro 	char buf[MAXNAME];	/* EAI:ok (domainname) */
930d0cef73dSGregory Neil Shapiro 	char *period, *autodomain;
931d0cef73dSGregory Neil Shapiro 
932d0cef73dSGregory Neil Shapiro 	if (getdomainname(buf, sizeof buf) < 0)
933d0cef73dSGregory Neil Shapiro 		return NULL;
934d0cef73dSGregory Neil Shapiro 
935d0cef73dSGregory Neil Shapiro 	if (buf[0] == '\0')
936d0cef73dSGregory Neil Shapiro 		return NULL;
937d0cef73dSGregory Neil Shapiro 
938d0cef73dSGregory Neil Shapiro 	if (tTd(0, 20))
939d0cef73dSGregory Neil Shapiro 		printf("domainname = %s\n", buf);
940d0cef73dSGregory Neil Shapiro 
941d0cef73dSGregory Neil Shapiro 	if (buf[0] == '+')
942d0cef73dSGregory Neil Shapiro 		buf[0] = '.';
943d0cef73dSGregory Neil Shapiro 	period = strchr(buf, '.');
944d0cef73dSGregory Neil Shapiro 	if (period == NULL)
945d0cef73dSGregory Neil Shapiro 		autodomain = buf;
946d0cef73dSGregory Neil Shapiro 	else
947d0cef73dSGregory Neil Shapiro 		autodomain = period + 1;
948d0cef73dSGregory Neil Shapiro 	if (strchr(autodomain, '.') == NULL)
949d0cef73dSGregory Neil Shapiro 		return newstr(buf);
950d0cef73dSGregory Neil Shapiro 	else
951d0cef73dSGregory Neil Shapiro 		return newstr(autodomain);
952d0cef73dSGregory Neil Shapiro }
953d0cef73dSGregory Neil Shapiro #endif /* SUN_EXTENSIONS && SUN_INIT_DOMAIN */
954d0cef73dSGregory Neil Shapiro 
95540266059SGregory Neil Shapiro /*
956c2aa98e2SPeter Wemm **  GETCANONNAME -- look up name using service switch
957c2aa98e2SPeter Wemm **
958c2aa98e2SPeter Wemm **	Parameters:
959c2aa98e2SPeter Wemm **		host -- the host name to look up.
960c2aa98e2SPeter Wemm **		hbsize -- the size of the host buffer.
961c2aa98e2SPeter Wemm **		trymx -- if set, try MX records.
96240266059SGregory Neil Shapiro **		pttl -- pointer to return TTL (can be NULL).
963c2aa98e2SPeter Wemm **
964c2aa98e2SPeter Wemm **	Returns:
9655b0945b5SGregory Neil Shapiro **		>0 -- if the host was found.
9665b0945b5SGregory Neil Shapiro **		0 -- otherwise.
967c2aa98e2SPeter Wemm */
968c2aa98e2SPeter Wemm 
9695b0945b5SGregory Neil Shapiro int
getcanonname(host,hbsize,trymx,pttl)97040266059SGregory Neil Shapiro getcanonname(host, hbsize, trymx, pttl)
971c2aa98e2SPeter Wemm 	char *host;
972c2aa98e2SPeter Wemm 	int hbsize;
973c2aa98e2SPeter Wemm 	bool trymx;
97440266059SGregory Neil Shapiro 	int *pttl;
975c2aa98e2SPeter Wemm {
976c2aa98e2SPeter Wemm 	int nmaps;
977c2aa98e2SPeter Wemm 	int mapno;
97840266059SGregory Neil Shapiro 	bool found = false;
97940266059SGregory Neil Shapiro 	bool got_tempfail = false;
9809bd497b8SGregory Neil Shapiro 	auto int status = EX_UNAVAILABLE;
981c2aa98e2SPeter Wemm 	char *maptype[MAXMAPSTACK];
982c2aa98e2SPeter Wemm 	short mapreturn[MAXMAPACTIONS];
983d0cef73dSGregory Neil Shapiro #if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN)
984d0cef73dSGregory Neil Shapiro 	bool should_try_nis_domain = false;
985d0cef73dSGregory Neil Shapiro 	static char *nis_domain = NULL;
986d0cef73dSGregory Neil Shapiro #endif
9875b0945b5SGregory Neil Shapiro 	bool secure = true;	/* consider all maps secure by default */
988c2aa98e2SPeter Wemm 
989c2aa98e2SPeter Wemm 	nmaps = switch_map_find("hosts", maptype, mapreturn);
9905b0945b5SGregory Neil Shapiro 	if (pttl != NULL)
99140266059SGregory Neil Shapiro 		*pttl = SM_DEFAULT_TTL;
992c2aa98e2SPeter Wemm 	for (mapno = 0; mapno < nmaps; mapno++)
993c2aa98e2SPeter Wemm 	{
994c2aa98e2SPeter Wemm 		int i;
995c2aa98e2SPeter Wemm 
996c2aa98e2SPeter Wemm 		if (tTd(38, 20))
99740266059SGregory Neil Shapiro 			sm_dprintf("getcanonname(%s), trying %s\n",
998c2aa98e2SPeter Wemm 				host, maptype[mapno]);
999c2aa98e2SPeter Wemm 		if (strcmp("files", maptype[mapno]) == 0)
1000c2aa98e2SPeter Wemm 		{
100106f25ae9SGregory Neil Shapiro 			found = text_getcanonname(host, hbsize, &status);
1002c2aa98e2SPeter Wemm 		}
100340266059SGregory Neil Shapiro #if NIS
1004c2aa98e2SPeter Wemm 		else if (strcmp("nis", maptype[mapno]) == 0)
1005c2aa98e2SPeter Wemm 		{
100606f25ae9SGregory Neil Shapiro 			found = nis_getcanonname(host, hbsize, &status);
1007d0cef73dSGregory Neil Shapiro # if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN)
1008d0cef73dSGregory Neil Shapiro 			if (nis_domain == NULL)
1009d0cef73dSGregory Neil Shapiro 				nis_domain = sun_init_domain();
10105b0945b5SGregory Neil Shapiro # endif
1011c2aa98e2SPeter Wemm 		}
101206f25ae9SGregory Neil Shapiro #endif /* NIS */
101340266059SGregory Neil Shapiro #if NISPLUS
1014c2aa98e2SPeter Wemm 		else if (strcmp("nisplus", maptype[mapno]) == 0)
1015c2aa98e2SPeter Wemm 		{
101606f25ae9SGregory Neil Shapiro 			found = nisplus_getcanonname(host, hbsize, &status);
1017d0cef73dSGregory Neil Shapiro # if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN)
1018d0cef73dSGregory Neil Shapiro 			if (nis_domain == NULL)
1019d0cef73dSGregory Neil Shapiro 				nis_domain = sun_init_domain();
10205b0945b5SGregory Neil Shapiro # endif
1021c2aa98e2SPeter Wemm 		}
102206f25ae9SGregory Neil Shapiro #endif /* NISPLUS */
1023c2aa98e2SPeter Wemm #if NAMED_BIND
1024c2aa98e2SPeter Wemm 		else if (strcmp("dns", maptype[mapno]) == 0)
1025c2aa98e2SPeter Wemm 		{
10265b0945b5SGregory Neil Shapiro 			int r;
10275b0945b5SGregory Neil Shapiro 
10285b0945b5SGregory Neil Shapiro 			r = dns_getcanonname(host, hbsize, trymx, &status,
10295b0945b5SGregory Neil Shapiro 					pttl);
10305b0945b5SGregory Neil Shapiro 			secure = HOST_SECURE == r;
10315b0945b5SGregory Neil Shapiro 			found = r > 0;
1032c2aa98e2SPeter Wemm 		}
103306f25ae9SGregory Neil Shapiro #endif /* NAMED_BIND */
1034c2aa98e2SPeter Wemm #if NETINFO
1035c2aa98e2SPeter Wemm 		else if (strcmp("netinfo", maptype[mapno]) == 0)
1036c2aa98e2SPeter Wemm 		{
103706f25ae9SGregory Neil Shapiro 			found = ni_getcanonname(host, hbsize, &status);
1038c2aa98e2SPeter Wemm 		}
103906f25ae9SGregory Neil Shapiro #endif /* NETINFO */
1040c2aa98e2SPeter Wemm 		else
1041c2aa98e2SPeter Wemm 		{
104240266059SGregory Neil Shapiro 			found = false;
104306f25ae9SGregory Neil Shapiro 			status = EX_UNAVAILABLE;
1044c2aa98e2SPeter Wemm 		}
1045c2aa98e2SPeter Wemm 
1046c2aa98e2SPeter Wemm 		/*
1047c2aa98e2SPeter Wemm 		**  Heuristic: if $m is not set, we are running during system
1048c2aa98e2SPeter Wemm 		**  startup.  In this case, when a name is apparently found
1049c2aa98e2SPeter Wemm 		**  but has no dot, treat is as not found.  This avoids
1050c2aa98e2SPeter Wemm 		**  problems if /etc/hosts has no FQDN but is listed first
1051c2aa98e2SPeter Wemm 		**  in the service switch.
1052c2aa98e2SPeter Wemm 		*/
1053c2aa98e2SPeter Wemm 
1054c2aa98e2SPeter Wemm 		if (found &&
1055c2aa98e2SPeter Wemm 		    (macvalue('m', CurEnv) != NULL || strchr(host, '.') != NULL))
1056c2aa98e2SPeter Wemm 			break;
1057c2aa98e2SPeter Wemm 
1058d0cef73dSGregory Neil Shapiro #if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN)
1059d0cef73dSGregory Neil Shapiro 		if (found)
1060d0cef73dSGregory Neil Shapiro 			should_try_nis_domain = true;
1061d0cef73dSGregory Neil Shapiro 		/* but don't break, as we need to try all methods first */
1062d0cef73dSGregory Neil Shapiro #endif /* defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) */
1063d0cef73dSGregory Neil Shapiro 
1064c2aa98e2SPeter Wemm 		/* see if we should continue */
106506f25ae9SGregory Neil Shapiro 		if (status == EX_TEMPFAIL)
1066c2aa98e2SPeter Wemm 		{
1067c2aa98e2SPeter Wemm 			i = MA_TRYAGAIN;
106840266059SGregory Neil Shapiro 			got_tempfail = true;
1069c2aa98e2SPeter Wemm 		}
107006f25ae9SGregory Neil Shapiro 		else if (status == EX_NOTFOUND)
1071c2aa98e2SPeter Wemm 			i = MA_NOTFOUND;
1072c2aa98e2SPeter Wemm 		else
1073c2aa98e2SPeter Wemm 			i = MA_UNAVAIL;
1074c2aa98e2SPeter Wemm 		if (bitset(1 << mapno, mapreturn[i]))
1075c2aa98e2SPeter Wemm 			break;
1076c2aa98e2SPeter Wemm 	}
1077c2aa98e2SPeter Wemm 
1078c2aa98e2SPeter Wemm 	if (found)
1079c2aa98e2SPeter Wemm 	{
1080c2aa98e2SPeter Wemm 		char *d;
1081c2aa98e2SPeter Wemm 
1082c2aa98e2SPeter Wemm 		if (tTd(38, 20))
10835b0945b5SGregory Neil Shapiro 			sm_dprintf("getcanonname(%s), found, ad=%d\n", host, secure);
1084c2aa98e2SPeter Wemm 
1085c2aa98e2SPeter Wemm 		/*
1086c2aa98e2SPeter Wemm 		**  If returned name is still single token, compensate
1087c2aa98e2SPeter Wemm 		**  by tagging on $m.  This is because some sites set
1088c2aa98e2SPeter Wemm 		**  up their DNS or NIS databases wrong.
1089c2aa98e2SPeter Wemm 		*/
1090c2aa98e2SPeter Wemm 
1091c2aa98e2SPeter Wemm 		if ((d = strchr(host, '.')) == NULL || d[1] == '\0')
1092c2aa98e2SPeter Wemm 		{
1093c2aa98e2SPeter Wemm 			d = macvalue('m', CurEnv);
1094c2aa98e2SPeter Wemm 			if (d != NULL &&
1095c2aa98e2SPeter Wemm 			    hbsize > (int) (strlen(host) + strlen(d) + 1))
1096c2aa98e2SPeter Wemm 			{
1097c2aa98e2SPeter Wemm 				if (host[strlen(host) - 1] != '.')
109840266059SGregory Neil Shapiro 					(void) sm_strlcat2(host, ".", d,
109940266059SGregory Neil Shapiro 							   hbsize);
110040266059SGregory Neil Shapiro 				else
110140266059SGregory Neil Shapiro 					(void) sm_strlcat(host, d, hbsize);
1102c2aa98e2SPeter Wemm 			}
1103c2aa98e2SPeter Wemm 			else
1104d0cef73dSGregory Neil Shapiro 			{
1105d0cef73dSGregory Neil Shapiro #if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN)
1106d0cef73dSGregory Neil Shapiro 				if (VendorCode == VENDOR_SUN &&
1107d0cef73dSGregory Neil Shapiro 				    should_try_nis_domain)
1108d0cef73dSGregory Neil Shapiro 				{
1109d0cef73dSGregory Neil Shapiro 					goto try_nis_domain;
1110d0cef73dSGregory Neil Shapiro 				}
1111d0cef73dSGregory Neil Shapiro #endif /* defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) */
11125b0945b5SGregory Neil Shapiro 				return HOST_NOTFOUND;
1113c2aa98e2SPeter Wemm 			}
1114d0cef73dSGregory Neil Shapiro 		}
11155b0945b5SGregory Neil Shapiro 		return secure ? HOST_SECURE : HOST_OK;
1116c2aa98e2SPeter Wemm 	}
1117c2aa98e2SPeter Wemm 
1118d0cef73dSGregory Neil Shapiro #if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN)
1119d0cef73dSGregory Neil Shapiro 	if (VendorCode == VENDOR_SUN && should_try_nis_domain)
1120d0cef73dSGregory Neil Shapiro 	{
1121d0cef73dSGregory Neil Shapiro   try_nis_domain:
1122d0cef73dSGregory Neil Shapiro 		if (nis_domain != NULL &&
1123d0cef73dSGregory Neil Shapiro 		    strlen(nis_domain) + strlen(host) + 1 < hbsize)
1124d0cef73dSGregory Neil Shapiro 		{
1125d0cef73dSGregory Neil Shapiro 			(void) sm_strlcat2(host, ".", nis_domain, hbsize);
11265b0945b5SGregory Neil Shapiro 			return HOST_OK;
1127d0cef73dSGregory Neil Shapiro 		}
1128d0cef73dSGregory Neil Shapiro 	}
1129d0cef73dSGregory Neil Shapiro #endif /* defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN) */
1130d0cef73dSGregory Neil Shapiro 
1131c2aa98e2SPeter Wemm 	if (tTd(38, 20))
113240266059SGregory Neil Shapiro 		sm_dprintf("getcanonname(%s), failed, status=%d\n", host,
113340266059SGregory Neil Shapiro 			status);
1134c2aa98e2SPeter Wemm 
1135c2aa98e2SPeter Wemm 	if (got_tempfail)
1136602a2b1bSGregory Neil Shapiro 		SM_SET_H_ERRNO(TRY_AGAIN);
1137c2aa98e2SPeter Wemm 	else
1138602a2b1bSGregory Neil Shapiro 		SM_SET_H_ERRNO(HOST_NOT_FOUND);
113940266059SGregory Neil Shapiro 
11405b0945b5SGregory Neil Shapiro 	return HOST_NOTFOUND;
1141c2aa98e2SPeter Wemm }
114240266059SGregory Neil Shapiro /*
1143c2aa98e2SPeter Wemm **  EXTRACT_CANONNAME -- extract canonical name from /etc/hosts entry
1144c2aa98e2SPeter Wemm **
1145c2aa98e2SPeter Wemm **	Parameters:
1146c2aa98e2SPeter Wemm **		name -- the name against which to match.
1147602a2b1bSGregory Neil Shapiro **		dot -- where to reinsert '.' to get FQDN
1148c2aa98e2SPeter Wemm **		line -- the /etc/hosts line.
1149c2aa98e2SPeter Wemm **		cbuf -- the location to store the result.
1150c2aa98e2SPeter Wemm **		cbuflen -- the size of cbuf.
1151c2aa98e2SPeter Wemm **
1152c2aa98e2SPeter Wemm **	Returns:
115340266059SGregory Neil Shapiro **		true -- if the line matched the desired name.
115440266059SGregory Neil Shapiro **		false -- otherwise.
1155c2aa98e2SPeter Wemm */
1156c2aa98e2SPeter Wemm 
115706f25ae9SGregory Neil Shapiro static bool
extract_canonname(name,dot,line,cbuf,cbuflen)1158602a2b1bSGregory Neil Shapiro extract_canonname(name, dot, line, cbuf, cbuflen)
1159c2aa98e2SPeter Wemm 	char *name;
1160602a2b1bSGregory Neil Shapiro 	char *dot;
1161c2aa98e2SPeter Wemm 	char *line;
1162c2aa98e2SPeter Wemm 	char cbuf[];
1163c2aa98e2SPeter Wemm 	int cbuflen;
1164c2aa98e2SPeter Wemm {
1165c2aa98e2SPeter Wemm 	int i;
1166c2aa98e2SPeter Wemm 	char *p;
116740266059SGregory Neil Shapiro 	bool found = false;
1168c2aa98e2SPeter Wemm 
1169c2aa98e2SPeter Wemm 	cbuf[0] = '\0';
1170c2aa98e2SPeter Wemm 	if (line[0] == '#')
117140266059SGregory Neil Shapiro 		return false;
1172c2aa98e2SPeter Wemm 
1173c2aa98e2SPeter Wemm 	for (i = 1; ; i++)
1174c2aa98e2SPeter Wemm 	{
11752fb4f839SGregory Neil Shapiro 		char nbuf[MAXNAME + 1];	/* EAI:hostname */
1176c2aa98e2SPeter Wemm 
1177d0cef73dSGregory Neil Shapiro 		p = get_column(line, i, '\0', nbuf, sizeof(nbuf));
1178c2aa98e2SPeter Wemm 		if (p == NULL)
1179c2aa98e2SPeter Wemm 			break;
1180c2aa98e2SPeter Wemm 		if (*p == '\0')
1181c2aa98e2SPeter Wemm 			continue;
1182c2aa98e2SPeter Wemm 		if (cbuf[0] == '\0' ||
1183c2aa98e2SPeter Wemm 		    (strchr(cbuf, '.') == NULL && strchr(p, '.') != NULL))
1184c2aa98e2SPeter Wemm 		{
118540266059SGregory Neil Shapiro 			(void) sm_strlcpy(cbuf, p, cbuflen);
1186c2aa98e2SPeter Wemm 		}
11872fb4f839SGregory Neil Shapiro 		if (SM_STRCASEEQ(name, p))
118840266059SGregory Neil Shapiro 			found = true;
1189602a2b1bSGregory Neil Shapiro 		else if (dot != NULL)
1190602a2b1bSGregory Neil Shapiro 		{
1191602a2b1bSGregory Neil Shapiro 			/* try looking for the FQDN as well */
1192602a2b1bSGregory Neil Shapiro 			*dot = '.';
11932fb4f839SGregory Neil Shapiro 			if (SM_STRCASEEQ(name, p))
119440266059SGregory Neil Shapiro 				found = true;
1195602a2b1bSGregory Neil Shapiro 			*dot = '\0';
1196602a2b1bSGregory Neil Shapiro 		}
1197c2aa98e2SPeter Wemm 	}
1198c2aa98e2SPeter Wemm 	if (found && strchr(cbuf, '.') == NULL)
1199c2aa98e2SPeter Wemm 	{
1200c2aa98e2SPeter Wemm 		/* try to add a domain on the end of the name */
1201c2aa98e2SPeter Wemm 		char *domain = macvalue('m', CurEnv);
1202c2aa98e2SPeter Wemm 
1203c2aa98e2SPeter Wemm 		if (domain != NULL &&
120406f25ae9SGregory Neil Shapiro 		    strlen(domain) + (i = strlen(cbuf)) + 1 < (size_t) cbuflen)
1205c2aa98e2SPeter Wemm 		{
120606f25ae9SGregory Neil Shapiro 			p = &cbuf[i];
1207c2aa98e2SPeter Wemm 			*p++ = '.';
120840266059SGregory Neil Shapiro 			(void) sm_strlcpy(p, domain, cbuflen - i - 1);
1209c2aa98e2SPeter Wemm 		}
1210c2aa98e2SPeter Wemm 	}
1211c2aa98e2SPeter Wemm 	return found;
1212c2aa98e2SPeter Wemm }
121340266059SGregory Neil Shapiro 
121440266059SGregory Neil Shapiro /*
121540266059SGregory Neil Shapiro **  DNS modules
121640266059SGregory Neil Shapiro */
121740266059SGregory Neil Shapiro 
121840266059SGregory Neil Shapiro #if NAMED_BIND
121940266059SGregory Neil Shapiro # if DNSMAP
122040266059SGregory Neil Shapiro 
122140266059SGregory Neil Shapiro #  include "sm_resolve.h"
122240266059SGregory Neil Shapiro #  if NETINET || NETINET6
122340266059SGregory Neil Shapiro #   include <arpa/inet.h>
12245b0945b5SGregory Neil Shapiro #  endif
122540266059SGregory Neil Shapiro 
122640266059SGregory Neil Shapiro /*
122740266059SGregory Neil Shapiro **  DNS_MAP_OPEN -- stub to check proper value for dns map type
122840266059SGregory Neil Shapiro */
122940266059SGregory Neil Shapiro 
123040266059SGregory Neil Shapiro bool
dns_map_open(map,mode)123140266059SGregory Neil Shapiro dns_map_open(map, mode)
123240266059SGregory Neil Shapiro 	MAP *map;
123340266059SGregory Neil Shapiro 	int mode;
123440266059SGregory Neil Shapiro {
123540266059SGregory Neil Shapiro 	if (tTd(38,2))
123640266059SGregory Neil Shapiro 		sm_dprintf("dns_map_open(%s, %d)\n", map->map_mname, mode);
123740266059SGregory Neil Shapiro 
123840266059SGregory Neil Shapiro 	mode &= O_ACCMODE;
123940266059SGregory Neil Shapiro 	if (mode != O_RDONLY)
124040266059SGregory Neil Shapiro 	{
124140266059SGregory Neil Shapiro 		/* issue a pseudo-error message */
124240266059SGregory Neil Shapiro 		errno = SM_EMAPCANTWRITE;
124340266059SGregory Neil Shapiro 		return false;
124440266059SGregory Neil Shapiro 	}
124540266059SGregory Neil Shapiro 	return true;
124640266059SGregory Neil Shapiro }
124740266059SGregory Neil Shapiro 
124840266059SGregory Neil Shapiro /*
124940266059SGregory Neil Shapiro **  DNS_MAP_PARSEARGS -- parse dns map definition args.
125040266059SGregory Neil Shapiro **
125140266059SGregory Neil Shapiro **	Parameters:
125240266059SGregory Neil Shapiro **		map -- pointer to MAP
125340266059SGregory Neil Shapiro **		args -- pointer to the args on the config line.
125440266059SGregory Neil Shapiro **
125540266059SGregory Neil Shapiro **	Returns:
125640266059SGregory Neil Shapiro **		true -- if everything parsed OK.
125740266059SGregory Neil Shapiro **		false -- otherwise.
125840266059SGregory Neil Shapiro */
125940266059SGregory Neil Shapiro 
126040266059SGregory Neil Shapiro #define map_sizelimit	map_lockfd	/* overload field */
126140266059SGregory Neil Shapiro 
126240266059SGregory Neil Shapiro struct dns_map
126340266059SGregory Neil Shapiro {
126440266059SGregory Neil Shapiro 	int dns_m_type;
12655b0945b5SGregory Neil Shapiro 	unsigned int dns_m_options;
126640266059SGregory Neil Shapiro };
126740266059SGregory Neil Shapiro 
126840266059SGregory Neil Shapiro bool
dns_map_parseargs(map,args)126940266059SGregory Neil Shapiro dns_map_parseargs(map,args)
127040266059SGregory Neil Shapiro 	MAP *map;
127140266059SGregory Neil Shapiro 	char *args;
127240266059SGregory Neil Shapiro {
127340266059SGregory Neil Shapiro 	register char *p = args;
127440266059SGregory Neil Shapiro 	struct dns_map *map_p;
127540266059SGregory Neil Shapiro 
1276d0cef73dSGregory Neil Shapiro 	map_p = (struct dns_map *) xalloc(sizeof(*map_p));
12775b0945b5SGregory Neil Shapiro 	memset(map_p, '\0', sizeof(*map_p));
127840266059SGregory Neil Shapiro 	map_p->dns_m_type = -1;
127940266059SGregory Neil Shapiro 	map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL;
128040266059SGregory Neil Shapiro 
128140266059SGregory Neil Shapiro 	for (;;)
128240266059SGregory Neil Shapiro 	{
12835b0945b5SGregory Neil Shapiro 		while (SM_ISSPACE(*p))
128440266059SGregory Neil Shapiro 			p++;
128540266059SGregory Neil Shapiro 		if (*p != '-')
128640266059SGregory Neil Shapiro 			break;
128740266059SGregory Neil Shapiro 		switch (*++p)
128840266059SGregory Neil Shapiro 		{
1289*d39bd2c1SGregory Neil Shapiro #  if DNSSEC_TEST || _FFR_NAMESERVER
12905b0945b5SGregory Neil Shapiro 		  case '@':
12915b0945b5SGregory Neil Shapiro 			++p;
12925b0945b5SGregory Neil Shapiro 			if (nsportip(p) < 0)
12935b0945b5SGregory Neil Shapiro 				syserr("dns map %s: nsportip(%s)=failed",
12945b0945b5SGregory Neil Shapiro 					map->map_mname, p);
129540266059SGregory Neil Shapiro 			break;
1296*d39bd2c1SGregory Neil Shapiro #  endif /* DNSSEC_TEST || _FFR_NAMESERVER */
129740266059SGregory Neil Shapiro 
129840266059SGregory Neil Shapiro 		  case 'A':
129940266059SGregory Neil Shapiro 			map->map_mflags |= MF_APPEND;
130040266059SGregory Neil Shapiro 			break;
130140266059SGregory Neil Shapiro 
130240266059SGregory Neil Shapiro 		  case 'a':
130340266059SGregory Neil Shapiro 			map->map_app = ++p;
130440266059SGregory Neil Shapiro 			break;
130540266059SGregory Neil Shapiro 
13065b0945b5SGregory Neil Shapiro 		  case 'B':		/* base domain */
13075b0945b5SGregory Neil Shapiro 			{
13085b0945b5SGregory Neil Shapiro 				char *h;
13095b0945b5SGregory Neil Shapiro 
13105b0945b5SGregory Neil Shapiro 				while (isascii(*++p) && isspace(*p))
13115b0945b5SGregory Neil Shapiro 					continue;
13125b0945b5SGregory Neil Shapiro 				h = strchr(p, ' ');
13135b0945b5SGregory Neil Shapiro 				if (h != NULL)
13145b0945b5SGregory Neil Shapiro 					*h = '\0';
13155b0945b5SGregory Neil Shapiro 
13165b0945b5SGregory Neil Shapiro 				/*
13175b0945b5SGregory Neil Shapiro 				**  slight abuse of map->map_file; it isn't
13185b0945b5SGregory Neil Shapiro 				**	used otherwise in this map type.
13195b0945b5SGregory Neil Shapiro 				*/
13205b0945b5SGregory Neil Shapiro 
13215b0945b5SGregory Neil Shapiro 				map->map_file = newstr(p);
13225b0945b5SGregory Neil Shapiro 				if (h != NULL)
13235b0945b5SGregory Neil Shapiro 					*h = ' ';
13245b0945b5SGregory Neil Shapiro 			}
132540266059SGregory Neil Shapiro 			break;
132640266059SGregory Neil Shapiro 
132740266059SGregory Neil Shapiro 		  case 'd':
132840266059SGregory Neil Shapiro 			{
132940266059SGregory Neil Shapiro 				char *h;
133040266059SGregory Neil Shapiro 
133140266059SGregory Neil Shapiro 				++p;
133240266059SGregory Neil Shapiro 				h = strchr(p, ' ');
133340266059SGregory Neil Shapiro 				if (h != NULL)
133440266059SGregory Neil Shapiro 					*h = '\0';
133540266059SGregory Neil Shapiro 				map->map_timeout = convtime(p, 's');
133640266059SGregory Neil Shapiro 				if (h != NULL)
133740266059SGregory Neil Shapiro 					*h = ' ';
133840266059SGregory Neil Shapiro 			}
133940266059SGregory Neil Shapiro 			break;
134040266059SGregory Neil Shapiro 
13415b0945b5SGregory Neil Shapiro 		  case 'f':
13425b0945b5SGregory Neil Shapiro 			map->map_mflags |= MF_NOFOLDCASE;
13435b0945b5SGregory Neil Shapiro 			break;
13445b0945b5SGregory Neil Shapiro 
13455b0945b5SGregory Neil Shapiro 		  case 'm':
13465b0945b5SGregory Neil Shapiro 			map->map_mflags |= MF_MATCHONLY;
13475b0945b5SGregory Neil Shapiro 			break;
13485b0945b5SGregory Neil Shapiro 
13495b0945b5SGregory Neil Shapiro 		  case 'N':
13505b0945b5SGregory Neil Shapiro 			map->map_mflags |= MF_INCLNULL;
13515b0945b5SGregory Neil Shapiro 			map->map_mflags &= ~MF_TRY0NULL;
13525b0945b5SGregory Neil Shapiro 			break;
13535b0945b5SGregory Neil Shapiro 
13545b0945b5SGregory Neil Shapiro 		  case 'O':
13555b0945b5SGregory Neil Shapiro 			map->map_mflags &= ~MF_TRY1NULL;
13565b0945b5SGregory Neil Shapiro 			break;
13575b0945b5SGregory Neil Shapiro 
13585b0945b5SGregory Neil Shapiro 		  case 'o':
13595b0945b5SGregory Neil Shapiro 			map->map_mflags |= MF_OPTIONAL;
13605b0945b5SGregory Neil Shapiro 			break;
13615b0945b5SGregory Neil Shapiro 
13625b0945b5SGregory Neil Shapiro 		  case 'q':
13635b0945b5SGregory Neil Shapiro 			map->map_mflags |= MF_KEEPQUOTES;
13645b0945b5SGregory Neil Shapiro 			break;
13655b0945b5SGregory Neil Shapiro 
13665b0945b5SGregory Neil Shapiro 		  case 'S':
13675b0945b5SGregory Neil Shapiro #  if defined(RES_USE_EDNS0) && defined(RES_USE_DNSSEC)
13685b0945b5SGregory Neil Shapiro 			map_p->dns_m_options |= SM_RES_DNSSEC;
13695b0945b5SGregory Neil Shapiro #  endif
13705b0945b5SGregory Neil Shapiro 			break;
13715b0945b5SGregory Neil Shapiro 
137240266059SGregory Neil Shapiro 		  case 'r':
137340266059SGregory Neil Shapiro 			while (isascii(*++p) && isspace(*p))
137440266059SGregory Neil Shapiro 				continue;
137540266059SGregory Neil Shapiro 			map->map_retry = atoi(p);
137640266059SGregory Neil Shapiro 			break;
137740266059SGregory Neil Shapiro 
13785b0945b5SGregory Neil Shapiro 		  case 't':
13795b0945b5SGregory Neil Shapiro 			map->map_mflags |= MF_NODEFER;
13805b0945b5SGregory Neil Shapiro 			break;
13815b0945b5SGregory Neil Shapiro 
13825b0945b5SGregory Neil Shapiro 		  case 'T':
13835b0945b5SGregory Neil Shapiro 			map->map_tapp = ++p;
13845b0945b5SGregory Neil Shapiro 			break;
13855b0945b5SGregory Neil Shapiro 
138640266059SGregory Neil Shapiro 		  case 'z':
138740266059SGregory Neil Shapiro 			if (*++p != '\\')
138840266059SGregory Neil Shapiro 				map->map_coldelim = *p;
138940266059SGregory Neil Shapiro 			else
139040266059SGregory Neil Shapiro 			{
139140266059SGregory Neil Shapiro 				switch (*++p)
139240266059SGregory Neil Shapiro 				{
139340266059SGregory Neil Shapiro 				  case 'n':
139440266059SGregory Neil Shapiro 					map->map_coldelim = '\n';
139540266059SGregory Neil Shapiro 					break;
139640266059SGregory Neil Shapiro 
139740266059SGregory Neil Shapiro 				  case 't':
139840266059SGregory Neil Shapiro 					map->map_coldelim = '\t';
139940266059SGregory Neil Shapiro 					break;
140040266059SGregory Neil Shapiro 
140140266059SGregory Neil Shapiro 				  default:
140240266059SGregory Neil Shapiro 					map->map_coldelim = '\\';
140340266059SGregory Neil Shapiro 				}
140440266059SGregory Neil Shapiro 			}
140540266059SGregory Neil Shapiro 			break;
140640266059SGregory Neil Shapiro 
140740266059SGregory Neil Shapiro 		  case 'Z':
140840266059SGregory Neil Shapiro 			while (isascii(*++p) && isspace(*p))
140940266059SGregory Neil Shapiro 				continue;
141040266059SGregory Neil Shapiro 			map->map_sizelimit = atoi(p);
141140266059SGregory Neil Shapiro 			break;
141240266059SGregory Neil Shapiro 
141340266059SGregory Neil Shapiro 			/* Start of dns_map specific args */
141440266059SGregory Neil Shapiro 		  case 'R':		/* search field */
141540266059SGregory Neil Shapiro 			{
141640266059SGregory Neil Shapiro 				char *h;
141740266059SGregory Neil Shapiro 
141840266059SGregory Neil Shapiro 				while (isascii(*++p) && isspace(*p))
141940266059SGregory Neil Shapiro 					continue;
142040266059SGregory Neil Shapiro 				h = strchr(p, ' ');
142140266059SGregory Neil Shapiro 				if (h != NULL)
142240266059SGregory Neil Shapiro 					*h = '\0';
142340266059SGregory Neil Shapiro 				map_p->dns_m_type = dns_string_to_type(p);
142440266059SGregory Neil Shapiro 				if (h != NULL)
142540266059SGregory Neil Shapiro 					*h = ' ';
142640266059SGregory Neil Shapiro 				if (map_p->dns_m_type < 0)
142740266059SGregory Neil Shapiro 					syserr("dns map %s: wrong type %s",
142840266059SGregory Neil Shapiro 						map->map_mname, p);
142940266059SGregory Neil Shapiro 			}
143040266059SGregory Neil Shapiro 			break;
143140266059SGregory Neil Shapiro 
143240266059SGregory Neil Shapiro 		}
14335b0945b5SGregory Neil Shapiro 		while (*p != '\0' && !(SM_ISSPACE(*p)))
143440266059SGregory Neil Shapiro 			p++;
143540266059SGregory Neil Shapiro 		if (*p != '\0')
143640266059SGregory Neil Shapiro 			*p++ = '\0';
143740266059SGregory Neil Shapiro 	}
143840266059SGregory Neil Shapiro 	if (map_p->dns_m_type < 0)
143940266059SGregory Neil Shapiro 		syserr("dns map %s: missing -R type", map->map_mname);
144040266059SGregory Neil Shapiro 	if (map->map_app != NULL)
144140266059SGregory Neil Shapiro 		map->map_app = newstr(map->map_app);
144240266059SGregory Neil Shapiro 	if (map->map_tapp != NULL)
144340266059SGregory Neil Shapiro 		map->map_tapp = newstr(map->map_tapp);
144440266059SGregory Neil Shapiro 
144540266059SGregory Neil Shapiro 	/*
1446d0cef73dSGregory Neil Shapiro 	**  Assumption: assert(sizeof(int) <= sizeof(ARBPTR_T));
144740266059SGregory Neil Shapiro 	**  Even if this assumption is wrong, we use only one byte,
144840266059SGregory Neil Shapiro 	**  so it doesn't really matter.
144940266059SGregory Neil Shapiro 	*/
145040266059SGregory Neil Shapiro 
145140266059SGregory Neil Shapiro 	map->map_db1 = (ARBPTR_T) map_p;
145240266059SGregory Neil Shapiro 	return true;
145340266059SGregory Neil Shapiro }
145440266059SGregory Neil Shapiro 
145540266059SGregory Neil Shapiro /*
145640266059SGregory Neil Shapiro **  DNS_MAP_LOOKUP -- perform dns map lookup.
145740266059SGregory Neil Shapiro **
145840266059SGregory Neil Shapiro **	Parameters:
145940266059SGregory Neil Shapiro **		map -- pointer to MAP
146040266059SGregory Neil Shapiro **		name -- name to look up
146140266059SGregory Neil Shapiro **		av -- arguments to interpolate into buf.
146240266059SGregory Neil Shapiro **		statp -- pointer to status (EX_)
146340266059SGregory Neil Shapiro **
146440266059SGregory Neil Shapiro **	Returns:
146540266059SGregory Neil Shapiro **		result of lookup if succeeded.
146640266059SGregory Neil Shapiro **		NULL -- otherwise.
146740266059SGregory Neil Shapiro */
146840266059SGregory Neil Shapiro 
146940266059SGregory Neil Shapiro char *
dns_map_lookup(map,name,av,statp)147040266059SGregory Neil Shapiro dns_map_lookup(map, name, av, statp)
147140266059SGregory Neil Shapiro 	MAP *map;
147240266059SGregory Neil Shapiro 	char *name;
147340266059SGregory Neil Shapiro 	char **av;
147440266059SGregory Neil Shapiro 	int *statp;
147540266059SGregory Neil Shapiro {
147640266059SGregory Neil Shapiro 	int resnum = 0;
147740266059SGregory Neil Shapiro 	char *vp = NULL, *result = NULL;
147840266059SGregory Neil Shapiro 	size_t vsize;
147940266059SGregory Neil Shapiro 	struct dns_map *map_p;
148040266059SGregory Neil Shapiro 	RESOURCE_RECORD_T *rr = NULL;
148140266059SGregory Neil Shapiro 	DNS_REPLY_T *r = NULL;
14825b0945b5SGregory Neil Shapiro 	unsigned int options;
148340266059SGregory Neil Shapiro #  if NETINET6
148440266059SGregory Neil Shapiro 	static char buf6[INET6_ADDRSTRLEN];
14855b0945b5SGregory Neil Shapiro #  endif
148640266059SGregory Neil Shapiro 
148740266059SGregory Neil Shapiro 	if (tTd(38, 20))
148840266059SGregory Neil Shapiro 		sm_dprintf("dns_map_lookup(%s, %s)\n",
148940266059SGregory Neil Shapiro 			   map->map_mname, name);
149040266059SGregory Neil Shapiro 
149140266059SGregory Neil Shapiro 	map_p = (struct dns_map *)(map->map_db1);
14925b0945b5SGregory Neil Shapiro 	options = map_p->dns_m_options;
149340266059SGregory Neil Shapiro 	if (map->map_file != NULL && *map->map_file != '\0')
149440266059SGregory Neil Shapiro 	{
149540266059SGregory Neil Shapiro 		size_t len;
149640266059SGregory Neil Shapiro 		char *appdomain;
149740266059SGregory Neil Shapiro 
149840266059SGregory Neil Shapiro 		len = strlen(map->map_file) + strlen(name) + 2;
149940266059SGregory Neil Shapiro 		appdomain = (char *) sm_malloc(len);
150040266059SGregory Neil Shapiro 		if (appdomain == NULL)
150140266059SGregory Neil Shapiro 		{
150240266059SGregory Neil Shapiro 			*statp = EX_UNAVAILABLE;
150340266059SGregory Neil Shapiro 			return NULL;
150440266059SGregory Neil Shapiro 		}
150540266059SGregory Neil Shapiro 		(void) sm_strlcpyn(appdomain, len, 3, name, ".", map->map_file);
15065b0945b5SGregory Neil Shapiro 		r = dns_lookup_map(appdomain, C_IN, map_p->dns_m_type,
15075b0945b5SGregory Neil Shapiro 				   map->map_timeout, map->map_retry, options);
150840266059SGregory Neil Shapiro 		sm_free(appdomain);
150940266059SGregory Neil Shapiro 	}
151040266059SGregory Neil Shapiro 	else
151140266059SGregory Neil Shapiro 	{
15125b0945b5SGregory Neil Shapiro 		r = dns_lookup_map(name, C_IN, map_p->dns_m_type,
15135b0945b5SGregory Neil Shapiro 				   map->map_timeout, map->map_retry, options);
151440266059SGregory Neil Shapiro 	}
151540266059SGregory Neil Shapiro 
151640266059SGregory Neil Shapiro 	if (r == NULL)
151740266059SGregory Neil Shapiro 	{
151840266059SGregory Neil Shapiro 		result = NULL;
1519a7ec597cSGregory Neil Shapiro 		if (h_errno == TRY_AGAIN || transienterror(errno))
152040266059SGregory Neil Shapiro 			*statp = EX_TEMPFAIL;
152140266059SGregory Neil Shapiro 		else
152240266059SGregory Neil Shapiro 			*statp = EX_NOTFOUND;
152340266059SGregory Neil Shapiro 		goto cleanup;
152440266059SGregory Neil Shapiro 	}
152540266059SGregory Neil Shapiro 	*statp = EX_OK;
152640266059SGregory Neil Shapiro 	for (rr = r->dns_r_head; rr != NULL; rr = rr->rr_next)
152740266059SGregory Neil Shapiro 	{
152840266059SGregory Neil Shapiro 		char *type = NULL;
152940266059SGregory Neil Shapiro 		char *value = NULL;
153040266059SGregory Neil Shapiro 
153140266059SGregory Neil Shapiro 		switch (rr->rr_type)
153240266059SGregory Neil Shapiro 		{
153340266059SGregory Neil Shapiro 		  case T_NS:
153440266059SGregory Neil Shapiro 			type = "T_NS";
153540266059SGregory Neil Shapiro 			value = rr->rr_u.rr_txt;
153640266059SGregory Neil Shapiro 			break;
153740266059SGregory Neil Shapiro 		  case T_CNAME:
153840266059SGregory Neil Shapiro 			type = "T_CNAME";
153940266059SGregory Neil Shapiro 			value = rr->rr_u.rr_txt;
154040266059SGregory Neil Shapiro 			break;
154140266059SGregory Neil Shapiro 		  case T_AFSDB:
154240266059SGregory Neil Shapiro 			type = "T_AFSDB";
154340266059SGregory Neil Shapiro 			value = rr->rr_u.rr_mx->mx_r_domain;
154440266059SGregory Neil Shapiro 			break;
154540266059SGregory Neil Shapiro 		  case T_SRV:
154640266059SGregory Neil Shapiro 			type = "T_SRV";
154740266059SGregory Neil Shapiro 			value = rr->rr_u.rr_srv->srv_r_target;
154840266059SGregory Neil Shapiro 			break;
154940266059SGregory Neil Shapiro 		  case T_PTR:
155040266059SGregory Neil Shapiro 			type = "T_PTR";
155140266059SGregory Neil Shapiro 			value = rr->rr_u.rr_txt;
155240266059SGregory Neil Shapiro 			break;
155340266059SGregory Neil Shapiro 		  case T_TXT:
155440266059SGregory Neil Shapiro 			type = "T_TXT";
155540266059SGregory Neil Shapiro 			value = rr->rr_u.rr_txt;
155640266059SGregory Neil Shapiro 			break;
155740266059SGregory Neil Shapiro 		  case T_MX:
155840266059SGregory Neil Shapiro 			type = "T_MX";
155940266059SGregory Neil Shapiro 			value = rr->rr_u.rr_mx->mx_r_domain;
156040266059SGregory Neil Shapiro 			break;
156140266059SGregory Neil Shapiro #  if NETINET
156240266059SGregory Neil Shapiro 		  case T_A:
156340266059SGregory Neil Shapiro 			type = "T_A";
156440266059SGregory Neil Shapiro 			value = inet_ntoa(*(rr->rr_u.rr_a));
156540266059SGregory Neil Shapiro 			break;
156640266059SGregory Neil Shapiro #  endif /* NETINET */
156740266059SGregory Neil Shapiro #  if NETINET6
156840266059SGregory Neil Shapiro 		  case T_AAAA:
156940266059SGregory Neil Shapiro 			type = "T_AAAA";
157040266059SGregory Neil Shapiro 			value = anynet_ntop(rr->rr_u.rr_aaaa, buf6,
1571d0cef73dSGregory Neil Shapiro 					    sizeof(buf6));
157240266059SGregory Neil Shapiro 			break;
157340266059SGregory Neil Shapiro #  endif /* NETINET6 */
15745b0945b5SGregory Neil Shapiro #  ifdef T_TLSA
15755b0945b5SGregory Neil Shapiro 		  case T_TLSA:
15765b0945b5SGregory Neil Shapiro 			type = "T_TLSA";
15775b0945b5SGregory Neil Shapiro 			value = rr->rr_u.rr_txt;
15785b0945b5SGregory Neil Shapiro 			break;
15795b0945b5SGregory Neil Shapiro #  endif /* T_TLSA */
158040266059SGregory Neil Shapiro 		}
158140266059SGregory Neil Shapiro 
1582739ac4d4SGregory Neil Shapiro 		(void) strreplnonprt(value, 'X');
158340266059SGregory Neil Shapiro 		if (map_p->dns_m_type != rr->rr_type)
158440266059SGregory Neil Shapiro 		{
158540266059SGregory Neil Shapiro 			if (tTd(38, 40))
158640266059SGregory Neil Shapiro 				sm_dprintf("\tskipping type %s (%d) value %s\n",
158740266059SGregory Neil Shapiro 					   type != NULL ? type : "<UNKNOWN>",
158840266059SGregory Neil Shapiro 					   rr->rr_type,
158940266059SGregory Neil Shapiro 					   value != NULL ? value : "<NO VALUE>");
159040266059SGregory Neil Shapiro 			continue;
159140266059SGregory Neil Shapiro 		}
159240266059SGregory Neil Shapiro 
159340266059SGregory Neil Shapiro #  if NETINET6
159440266059SGregory Neil Shapiro 		if (rr->rr_type == T_AAAA && value == NULL)
159540266059SGregory Neil Shapiro 		{
159640266059SGregory Neil Shapiro 			result = NULL;
159740266059SGregory Neil Shapiro 			*statp = EX_DATAERR;
159840266059SGregory Neil Shapiro 			if (tTd(38, 40))
159940266059SGregory Neil Shapiro 				sm_dprintf("\tbad T_AAAA conversion\n");
160040266059SGregory Neil Shapiro 			goto cleanup;
160140266059SGregory Neil Shapiro 		}
160240266059SGregory Neil Shapiro #  endif /* NETINET6 */
160340266059SGregory Neil Shapiro 		if (tTd(38, 40))
160440266059SGregory Neil Shapiro 			sm_dprintf("\tfound type %s (%d) value %s\n",
160540266059SGregory Neil Shapiro 				   type != NULL ? type : "<UNKNOWN>",
160640266059SGregory Neil Shapiro 				   rr->rr_type,
160740266059SGregory Neil Shapiro 				   value != NULL ? value : "<NO VALUE>");
160840266059SGregory Neil Shapiro 		if (value != NULL &&
160940266059SGregory Neil Shapiro 		    (map->map_coldelim == '\0' ||
161040266059SGregory Neil Shapiro 		     map->map_sizelimit == 1 ||
161140266059SGregory Neil Shapiro 		     bitset(MF_MATCHONLY, map->map_mflags)))
161240266059SGregory Neil Shapiro 		{
161340266059SGregory Neil Shapiro 			/* Only care about the first match */
161440266059SGregory Neil Shapiro 			vp = newstr(value);
161540266059SGregory Neil Shapiro 			break;
161640266059SGregory Neil Shapiro 		}
161740266059SGregory Neil Shapiro 		else if (vp == NULL)
161840266059SGregory Neil Shapiro 		{
161940266059SGregory Neil Shapiro 			/* First result */
162040266059SGregory Neil Shapiro 			vp = newstr(value);
162140266059SGregory Neil Shapiro 		}
162240266059SGregory Neil Shapiro 		else
162340266059SGregory Neil Shapiro 		{
162440266059SGregory Neil Shapiro 			/* concatenate the results */
162540266059SGregory Neil Shapiro 			int sz;
162640266059SGregory Neil Shapiro 			char *new;
162740266059SGregory Neil Shapiro 
162840266059SGregory Neil Shapiro 			sz = strlen(vp) + strlen(value) + 2;
162940266059SGregory Neil Shapiro 			new = xalloc(sz);
163040266059SGregory Neil Shapiro 			(void) sm_snprintf(new, sz, "%s%c%s",
163140266059SGregory Neil Shapiro 					   vp, map->map_coldelim, value);
163240266059SGregory Neil Shapiro 			sm_free(vp);
163340266059SGregory Neil Shapiro 			vp = new;
163440266059SGregory Neil Shapiro 			if (map->map_sizelimit > 0 &&
163540266059SGregory Neil Shapiro 			    ++resnum >= map->map_sizelimit)
163640266059SGregory Neil Shapiro 				break;
163740266059SGregory Neil Shapiro 		}
163840266059SGregory Neil Shapiro 	}
163940266059SGregory Neil Shapiro 	if (vp == NULL)
164040266059SGregory Neil Shapiro 	{
164140266059SGregory Neil Shapiro 		result = NULL;
164240266059SGregory Neil Shapiro 		*statp = EX_NOTFOUND;
164340266059SGregory Neil Shapiro 		if (tTd(38, 40))
164440266059SGregory Neil Shapiro 			sm_dprintf("\tno match found\n");
164540266059SGregory Neil Shapiro 		goto cleanup;
164640266059SGregory Neil Shapiro 	}
164740266059SGregory Neil Shapiro 
164840266059SGregory Neil Shapiro 	/* Cleanly truncate for rulesets */
164940266059SGregory Neil Shapiro 	truncate_at_delim(vp, PSBUFSIZE / 2, map->map_coldelim);
165040266059SGregory Neil Shapiro 
165140266059SGregory Neil Shapiro 	vsize = strlen(vp);
165240266059SGregory Neil Shapiro 
165340266059SGregory Neil Shapiro 	if (LogLevel > 9)
165440266059SGregory Neil Shapiro 		sm_syslog(LOG_INFO, CurEnv->e_id, "dns %.100s => %s",
165540266059SGregory Neil Shapiro 			  name, vp);
165640266059SGregory Neil Shapiro 	if (bitset(MF_MATCHONLY, map->map_mflags))
165740266059SGregory Neil Shapiro 		result = map_rewrite(map, name, strlen(name), NULL);
165840266059SGregory Neil Shapiro 	else
165940266059SGregory Neil Shapiro 		result = map_rewrite(map, vp, vsize, av);
166040266059SGregory Neil Shapiro 
166140266059SGregory Neil Shapiro   cleanup:
16622fb4f839SGregory Neil Shapiro 	SM_FREE(vp);
166340266059SGregory Neil Shapiro 	dns_free_data(r);
166440266059SGregory Neil Shapiro 	return result;
166540266059SGregory Neil Shapiro }
166640266059SGregory Neil Shapiro # endif /* DNSMAP */
166740266059SGregory Neil Shapiro #endif /* NAMED_BIND */
166840266059SGregory Neil Shapiro 
166940266059SGregory Neil Shapiro /*
1670c2aa98e2SPeter Wemm **  NDBM modules
1671c2aa98e2SPeter Wemm */
1672c2aa98e2SPeter Wemm 
167340266059SGregory Neil Shapiro #if NDBM
1674c2aa98e2SPeter Wemm 
1675c2aa98e2SPeter Wemm /*
1676c2aa98e2SPeter Wemm **  NDBM_MAP_OPEN -- DBM-style map open
1677c2aa98e2SPeter Wemm */
1678c2aa98e2SPeter Wemm 
1679c2aa98e2SPeter Wemm bool
ndbm_map_open(map,mode)1680c2aa98e2SPeter Wemm ndbm_map_open(map, mode)
1681c2aa98e2SPeter Wemm 	MAP *map;
1682c2aa98e2SPeter Wemm 	int mode;
1683c2aa98e2SPeter Wemm {
1684c2aa98e2SPeter Wemm 	register DBM *dbm;
168506f25ae9SGregory Neil Shapiro 	int save_errno;
1686c2aa98e2SPeter Wemm 	int dfd;
1687c2aa98e2SPeter Wemm 	int pfd;
168806f25ae9SGregory Neil Shapiro 	long sff;
1689c2aa98e2SPeter Wemm 	int ret;
1690c2aa98e2SPeter Wemm 	int smode = S_IREAD;
169194c01205SGregory Neil Shapiro 	char dirfile[MAXPATHLEN];
169294c01205SGregory Neil Shapiro 	char pagfile[MAXPATHLEN];
169306f25ae9SGregory Neil Shapiro 	struct stat st;
1694c2aa98e2SPeter Wemm 	struct stat std, stp;
1695c2aa98e2SPeter Wemm 
1696c2aa98e2SPeter Wemm 	if (tTd(38, 2))
169740266059SGregory Neil Shapiro 		sm_dprintf("ndbm_map_open(%s, %s, %d)\n",
1698c2aa98e2SPeter Wemm 			map->map_mname, map->map_file, mode);
1699c2aa98e2SPeter Wemm 	map->map_lockfd = -1;
1700c2aa98e2SPeter Wemm 	mode &= O_ACCMODE;
1701c2aa98e2SPeter Wemm 
1702c2aa98e2SPeter Wemm 	/* do initial file and directory checks */
1703d0cef73dSGregory Neil Shapiro 	if (sm_strlcpyn(dirfile, sizeof(dirfile), 2,
1704d0cef73dSGregory Neil Shapiro 			map->map_file, ".dir") >= sizeof(dirfile) ||
1705d0cef73dSGregory Neil Shapiro 	    sm_strlcpyn(pagfile, sizeof(pagfile), 2,
1706d0cef73dSGregory Neil Shapiro 			map->map_file, ".pag") >= sizeof(pagfile))
170794c01205SGregory Neil Shapiro 	{
170894c01205SGregory Neil Shapiro 		errno = 0;
170994c01205SGregory Neil Shapiro 		if (!bitset(MF_OPTIONAL, map->map_mflags))
171094c01205SGregory Neil Shapiro 			syserr("dbm map \"%s\": map file %s name too long",
171194c01205SGregory Neil Shapiro 				map->map_mname, map->map_file);
171294c01205SGregory Neil Shapiro 		return false;
171394c01205SGregory Neil Shapiro 	}
1714c2aa98e2SPeter Wemm 	sff = SFF_ROOTOK|SFF_REGONLY;
1715c2aa98e2SPeter Wemm 	if (mode == O_RDWR)
1716c2aa98e2SPeter Wemm 	{
1717c2aa98e2SPeter Wemm 		sff |= SFF_CREAT;
171806f25ae9SGregory Neil Shapiro 		if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail))
1719c2aa98e2SPeter Wemm 			sff |= SFF_NOSLINK;
172006f25ae9SGregory Neil Shapiro 		if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail))
1721c2aa98e2SPeter Wemm 			sff |= SFF_NOHLINK;
1722c2aa98e2SPeter Wemm 		smode = S_IWRITE;
1723c2aa98e2SPeter Wemm 	}
1724c2aa98e2SPeter Wemm 	else
1725c2aa98e2SPeter Wemm 	{
172606f25ae9SGregory Neil Shapiro 		if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail))
1727c2aa98e2SPeter Wemm 			sff |= SFF_NOWLINK;
1728c2aa98e2SPeter Wemm 	}
172906f25ae9SGregory Neil Shapiro 	if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail))
1730c2aa98e2SPeter Wemm 		sff |= SFF_SAFEDIRPATH;
1731c2aa98e2SPeter Wemm 	ret = safefile(dirfile, RunAsUid, RunAsGid, RunAsUserName,
1732c2aa98e2SPeter Wemm 		       sff, smode, &std);
1733c2aa98e2SPeter Wemm 	if (ret == 0)
1734c2aa98e2SPeter Wemm 		ret = safefile(pagfile, RunAsUid, RunAsGid, RunAsUserName,
1735c2aa98e2SPeter Wemm 			       sff, smode, &stp);
173606f25ae9SGregory Neil Shapiro 
1737c2aa98e2SPeter Wemm 	if (ret != 0)
1738c2aa98e2SPeter Wemm 	{
1739c2aa98e2SPeter Wemm 		char *prob = "unsafe";
1740c2aa98e2SPeter Wemm 
1741c2aa98e2SPeter Wemm 		/* cannot open this map */
1742c2aa98e2SPeter Wemm 		if (ret == ENOENT)
1743c2aa98e2SPeter Wemm 			prob = "missing";
1744c2aa98e2SPeter Wemm 		if (tTd(38, 2))
174540266059SGregory Neil Shapiro 			sm_dprintf("\t%s map file: %d\n", prob, ret);
1746c2aa98e2SPeter Wemm 		if (!bitset(MF_OPTIONAL, map->map_mflags))
1747c2aa98e2SPeter Wemm 			syserr("dbm map \"%s\": %s map file %s",
1748c2aa98e2SPeter Wemm 				map->map_mname, prob, map->map_file);
174940266059SGregory Neil Shapiro 		return false;
1750c2aa98e2SPeter Wemm 	}
1751c2aa98e2SPeter Wemm 	if (std.st_mode == ST_MODE_NOFILE)
1752c2aa98e2SPeter Wemm 		mode |= O_CREAT|O_EXCL;
1753c2aa98e2SPeter Wemm 
1754c2aa98e2SPeter Wemm # if LOCK_ON_OPEN
1755c2aa98e2SPeter Wemm 	if (mode == O_RDONLY)
1756c2aa98e2SPeter Wemm 		mode |= O_SHLOCK;
1757c2aa98e2SPeter Wemm 	else
1758c2aa98e2SPeter Wemm 		mode |= O_TRUNC|O_EXLOCK;
175906f25ae9SGregory Neil Shapiro # else /* LOCK_ON_OPEN */
1760c2aa98e2SPeter Wemm 	if ((mode & O_ACCMODE) == O_RDWR)
1761c2aa98e2SPeter Wemm 	{
1762c2aa98e2SPeter Wemm #  if NOFTRUNCATE
1763c2aa98e2SPeter Wemm 		/*
1764c2aa98e2SPeter Wemm 		**  Warning: race condition.  Try to lock the file as
1765c2aa98e2SPeter Wemm 		**  quickly as possible after opening it.
1766c2aa98e2SPeter Wemm 		**	This may also have security problems on some systems,
1767c2aa98e2SPeter Wemm 		**	but there isn't anything we can do about it.
1768c2aa98e2SPeter Wemm 		*/
1769c2aa98e2SPeter Wemm 
1770c2aa98e2SPeter Wemm 		mode |= O_TRUNC;
177106f25ae9SGregory Neil Shapiro #  else /* NOFTRUNCATE */
1772c2aa98e2SPeter Wemm 		/*
1773c2aa98e2SPeter Wemm 		**  This ugly code opens the map without truncating it,
1774c2aa98e2SPeter Wemm 		**  locks the file, then truncates it.  Necessary to
1775c2aa98e2SPeter Wemm 		**  avoid race conditions.
1776c2aa98e2SPeter Wemm 		*/
1777c2aa98e2SPeter Wemm 
1778c2aa98e2SPeter Wemm 		int dirfd;
1779c2aa98e2SPeter Wemm 		int pagfd;
178006f25ae9SGregory Neil Shapiro 		long sff = SFF_CREAT|SFF_OPENASROOT;
1781c2aa98e2SPeter Wemm 
178206f25ae9SGregory Neil Shapiro 		if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail))
1783c2aa98e2SPeter Wemm 			sff |= SFF_NOSLINK;
178406f25ae9SGregory Neil Shapiro 		if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail))
1785c2aa98e2SPeter Wemm 			sff |= SFF_NOHLINK;
1786c2aa98e2SPeter Wemm 
1787c2aa98e2SPeter Wemm 		dirfd = safeopen(dirfile, mode, DBMMODE, sff);
1788c2aa98e2SPeter Wemm 		pagfd = safeopen(pagfile, mode, DBMMODE, sff);
1789c2aa98e2SPeter Wemm 
1790c2aa98e2SPeter Wemm 		if (dirfd < 0 || pagfd < 0)
1791c2aa98e2SPeter Wemm 		{
179206f25ae9SGregory Neil Shapiro 			save_errno = errno;
1793c2aa98e2SPeter Wemm 			if (dirfd >= 0)
1794c2aa98e2SPeter Wemm 				(void) close(dirfd);
1795c2aa98e2SPeter Wemm 			if (pagfd >= 0)
1796c2aa98e2SPeter Wemm 				(void) close(pagfd);
1797c2aa98e2SPeter Wemm 			errno = save_errno;
1798c2aa98e2SPeter Wemm 			syserr("ndbm_map_open: cannot create database %s",
1799c2aa98e2SPeter Wemm 				map->map_file);
180040266059SGregory Neil Shapiro 			return false;
1801c2aa98e2SPeter Wemm 		}
1802c2aa98e2SPeter Wemm 		if (ftruncate(dirfd, (off_t) 0) < 0 ||
1803c2aa98e2SPeter Wemm 		    ftruncate(pagfd, (off_t) 0) < 0)
1804c2aa98e2SPeter Wemm 		{
180506f25ae9SGregory Neil Shapiro 			save_errno = errno;
1806c2aa98e2SPeter Wemm 			(void) close(dirfd);
1807c2aa98e2SPeter Wemm 			(void) close(pagfd);
1808c2aa98e2SPeter Wemm 			errno = save_errno;
1809c2aa98e2SPeter Wemm 			syserr("ndbm_map_open: cannot truncate %s.{dir,pag}",
1810c2aa98e2SPeter Wemm 				map->map_file);
181140266059SGregory Neil Shapiro 			return false;
1812c2aa98e2SPeter Wemm 		}
1813c2aa98e2SPeter Wemm 
1814c2aa98e2SPeter Wemm 		/* if new file, get "before" bits for later filechanged check */
1815c2aa98e2SPeter Wemm 		if (std.st_mode == ST_MODE_NOFILE &&
1816c2aa98e2SPeter Wemm 		    (fstat(dirfd, &std) < 0 || fstat(pagfd, &stp) < 0))
1817c2aa98e2SPeter Wemm 		{
181806f25ae9SGregory Neil Shapiro 			save_errno = errno;
1819c2aa98e2SPeter Wemm 			(void) close(dirfd);
1820c2aa98e2SPeter Wemm 			(void) close(pagfd);
1821c2aa98e2SPeter Wemm 			errno = save_errno;
1822c2aa98e2SPeter Wemm 			syserr("ndbm_map_open(%s.{dir,pag}): cannot fstat pre-opened file",
1823c2aa98e2SPeter Wemm 				map->map_file);
182440266059SGregory Neil Shapiro 			return false;
1825c2aa98e2SPeter Wemm 		}
1826c2aa98e2SPeter Wemm 
1827c2aa98e2SPeter Wemm 		/* have to save the lock for the duration (bletch) */
1828c2aa98e2SPeter Wemm 		map->map_lockfd = dirfd;
182906f25ae9SGregory Neil Shapiro 		(void) close(pagfd);
1830c2aa98e2SPeter Wemm 
1831c2aa98e2SPeter Wemm 		/* twiddle bits for dbm_open */
1832c2aa98e2SPeter Wemm 		mode &= ~(O_CREAT|O_EXCL);
183306f25ae9SGregory Neil Shapiro #  endif /* NOFTRUNCATE */
1834c2aa98e2SPeter Wemm 	}
183506f25ae9SGregory Neil Shapiro # endif /* LOCK_ON_OPEN */
1836c2aa98e2SPeter Wemm 
1837c2aa98e2SPeter Wemm 	/* open the database */
1838c2aa98e2SPeter Wemm 	dbm = dbm_open(map->map_file, mode, DBMMODE);
1839c2aa98e2SPeter Wemm 	if (dbm == NULL)
1840c2aa98e2SPeter Wemm 	{
184106f25ae9SGregory Neil Shapiro 		save_errno = errno;
1842c2aa98e2SPeter Wemm 		if (bitset(MF_ALIAS, map->map_mflags) &&
184340266059SGregory Neil Shapiro 		    aliaswait(map, ".pag", false))
184440266059SGregory Neil Shapiro 			return true;
1845c2aa98e2SPeter Wemm # if !LOCK_ON_OPEN && !NOFTRUNCATE
1846c2aa98e2SPeter Wemm 		if (map->map_lockfd >= 0)
184706f25ae9SGregory Neil Shapiro 			(void) close(map->map_lockfd);
18485b0945b5SGregory Neil Shapiro # endif
1849c2aa98e2SPeter Wemm 		errno = save_errno;
1850c2aa98e2SPeter Wemm 		if (!bitset(MF_OPTIONAL, map->map_mflags))
1851c2aa98e2SPeter Wemm 			syserr("Cannot open DBM database %s", map->map_file);
185240266059SGregory Neil Shapiro 		return false;
1853c2aa98e2SPeter Wemm 	}
1854c2aa98e2SPeter Wemm 	dfd = dbm_dirfno(dbm);
1855c2aa98e2SPeter Wemm 	pfd = dbm_pagfno(dbm);
1856c2aa98e2SPeter Wemm 	if (dfd == pfd)
1857c2aa98e2SPeter Wemm 	{
1858c2aa98e2SPeter Wemm 		/* heuristic: if files are linked, this is actually gdbm */
1859c2aa98e2SPeter Wemm 		dbm_close(dbm);
1860c2aa98e2SPeter Wemm # if !LOCK_ON_OPEN && !NOFTRUNCATE
1861c2aa98e2SPeter Wemm 		if (map->map_lockfd >= 0)
186206f25ae9SGregory Neil Shapiro 			(void) close(map->map_lockfd);
18635b0945b5SGregory Neil Shapiro # endif
1864c2aa98e2SPeter Wemm 		errno = 0;
1865c2aa98e2SPeter Wemm 		syserr("dbm map \"%s\": cannot support GDBM",
1866c2aa98e2SPeter Wemm 			map->map_mname);
186740266059SGregory Neil Shapiro 		return false;
1868c2aa98e2SPeter Wemm 	}
1869c2aa98e2SPeter Wemm 
1870c2aa98e2SPeter Wemm 	if (filechanged(dirfile, dfd, &std) ||
1871c2aa98e2SPeter Wemm 	    filechanged(pagfile, pfd, &stp))
1872c2aa98e2SPeter Wemm 	{
187306f25ae9SGregory Neil Shapiro 		save_errno = errno;
1874c2aa98e2SPeter Wemm 		dbm_close(dbm);
1875c2aa98e2SPeter Wemm # if !LOCK_ON_OPEN && !NOFTRUNCATE
1876c2aa98e2SPeter Wemm 		if (map->map_lockfd >= 0)
187706f25ae9SGregory Neil Shapiro 			(void) close(map->map_lockfd);
18785b0945b5SGregory Neil Shapiro # endif
1879c2aa98e2SPeter Wemm 		errno = save_errno;
1880c2aa98e2SPeter Wemm 		syserr("ndbm_map_open(%s): file changed after open",
1881c2aa98e2SPeter Wemm 			map->map_file);
188240266059SGregory Neil Shapiro 		return false;
1883c2aa98e2SPeter Wemm 	}
1884c2aa98e2SPeter Wemm 
1885c2aa98e2SPeter Wemm 	map->map_db1 = (ARBPTR_T) dbm;
188606f25ae9SGregory Neil Shapiro 
188706f25ae9SGregory Neil Shapiro 	/*
188806f25ae9SGregory Neil Shapiro 	**  Need to set map_mtime before the call to aliaswait()
188906f25ae9SGregory Neil Shapiro 	**  as aliaswait() will call map_lookup() which requires
189006f25ae9SGregory Neil Shapiro 	**  map_mtime to be set
189106f25ae9SGregory Neil Shapiro 	*/
189206f25ae9SGregory Neil Shapiro 
18938774250cSGregory Neil Shapiro 	if (fstat(pfd, &st) >= 0)
189406f25ae9SGregory Neil Shapiro 		map->map_mtime = st.st_mtime;
189506f25ae9SGregory Neil Shapiro 
1896c2aa98e2SPeter Wemm 	if (mode == O_RDONLY)
1897c2aa98e2SPeter Wemm 	{
1898c2aa98e2SPeter Wemm # if LOCK_ON_OPEN
1899c2aa98e2SPeter Wemm 		if (dfd >= 0)
1900c2aa98e2SPeter Wemm 			(void) lockfile(dfd, map->map_file, ".dir", LOCK_UN);
1901c2aa98e2SPeter Wemm 		if (pfd >= 0)
1902c2aa98e2SPeter Wemm 			(void) lockfile(pfd, map->map_file, ".pag", LOCK_UN);
190306f25ae9SGregory Neil Shapiro # endif /* LOCK_ON_OPEN */
1904c2aa98e2SPeter Wemm 		if (bitset(MF_ALIAS, map->map_mflags) &&
190540266059SGregory Neil Shapiro 		    !aliaswait(map, ".pag", true))
190640266059SGregory Neil Shapiro 			return false;
1907c2aa98e2SPeter Wemm 	}
1908c2aa98e2SPeter Wemm 	else
1909c2aa98e2SPeter Wemm 	{
1910c2aa98e2SPeter Wemm 		map->map_mflags |= MF_LOCKED;
1911*d39bd2c1SGregory Neil Shapiro 		mapchown(map->map_file, dfd, pfd, map->map_file);
1912c2aa98e2SPeter Wemm 	}
191340266059SGregory Neil Shapiro 	return true;
1914c2aa98e2SPeter Wemm }
1915c2aa98e2SPeter Wemm 
1916c2aa98e2SPeter Wemm 
1917c2aa98e2SPeter Wemm /*
1918c2aa98e2SPeter Wemm **  NDBM_MAP_LOOKUP -- look up a datum in a DBM-type map
1919c2aa98e2SPeter Wemm */
1920c2aa98e2SPeter Wemm 
1921c2aa98e2SPeter Wemm char *
ndbm_map_lookup(map,name,av,statp)1922c2aa98e2SPeter Wemm ndbm_map_lookup(map, name, av, statp)
1923c2aa98e2SPeter Wemm 	MAP *map;
1924c2aa98e2SPeter Wemm 	char *name;
1925c2aa98e2SPeter Wemm 	char **av;
1926c2aa98e2SPeter Wemm 	int *statp;
1927c2aa98e2SPeter Wemm {
1928c2aa98e2SPeter Wemm 	datum key, val;
19298774250cSGregory Neil Shapiro 	int dfd, pfd;
19302fb4f839SGregory Neil Shapiro 	char keybuf[MAXNAME + 1];	/* EAI:ok */
1931*d39bd2c1SGregory Neil Shapiro # if _FFR_MAP_CHK_FILE
1932*d39bd2c1SGregory Neil Shapiro 	char buf[MAXPATHLEN];
1933*d39bd2c1SGregory Neil Shapiro # endif
1934*d39bd2c1SGregory Neil Shapiro 	const char *fn = NULL;
1935c2aa98e2SPeter Wemm 
1936c2aa98e2SPeter Wemm 	if (tTd(38, 20))
193740266059SGregory Neil Shapiro 		sm_dprintf("ndbm_map_lookup(%s, %s)\n",
1938c2aa98e2SPeter Wemm 			map->map_mname, name);
1939c2aa98e2SPeter Wemm 
1940c2aa98e2SPeter Wemm 	key.dptr = name;
1941c2aa98e2SPeter Wemm 	key.dsize = strlen(name);
1942c2aa98e2SPeter Wemm 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
1943c2aa98e2SPeter Wemm 	{
1944d0cef73dSGregory Neil Shapiro 		if (key.dsize > sizeof(keybuf) - 1)
1945d0cef73dSGregory Neil Shapiro 			key.dsize = sizeof(keybuf) - 1;
194606f25ae9SGregory Neil Shapiro 		memmove(keybuf, key.dptr, key.dsize);
1947c2aa98e2SPeter Wemm 		keybuf[key.dsize] = '\0';
19482fb4f839SGregory Neil Shapiro 		makelower_buf(keybuf, keybuf, sizeof(keybuf));
1949c2aa98e2SPeter Wemm 		key.dptr = keybuf;
1950c2aa98e2SPeter Wemm 	}
1951*d39bd2c1SGregory Neil Shapiro # if _FFR_MAP_CHK_FILE
1952*d39bd2c1SGregory Neil Shapiro 	if (!smdb_add_extension(buf, sizeof(buf), map->map_file, "pag"))
1953*d39bd2c1SGregory Neil Shapiro 	{
1954*d39bd2c1SGregory Neil Shapiro 		errno = 0;
1955*d39bd2c1SGregory Neil Shapiro 		if (!bitset(MF_OPTIONAL, map->map_mflags))
1956*d39bd2c1SGregory Neil Shapiro 			syserr("ndbm map \"%s\": map file %s name too long",
1957*d39bd2c1SGregory Neil Shapiro 				map->map_mname, map->map_file);
1958*d39bd2c1SGregory Neil Shapiro 		return NULL;
1959*d39bd2c1SGregory Neil Shapiro 	}
1960*d39bd2c1SGregory Neil Shapiro 	fn = buf;
1961*d39bd2c1SGregory Neil Shapiro # endif
1962c2aa98e2SPeter Wemm lockdbm:
19638774250cSGregory Neil Shapiro 	dfd = dbm_dirfno((DBM *) map->map_db1);
19648774250cSGregory Neil Shapiro 	if (dfd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
19658774250cSGregory Neil Shapiro 		(void) lockfile(dfd, map->map_file, ".dir", LOCK_SH);
19668774250cSGregory Neil Shapiro 	pfd = dbm_pagfno((DBM *) map->map_db1);
1967*d39bd2c1SGregory Neil Shapiro 
1968*d39bd2c1SGregory Neil Shapiro 	if (map_has_chged(map, fn, pfd))
1969c2aa98e2SPeter Wemm 	{
1970c2aa98e2SPeter Wemm 		/* Reopen the database to sync the cache */
1971c2aa98e2SPeter Wemm 		int omode = bitset(map->map_mflags, MF_WRITABLE) ? O_RDWR
1972c2aa98e2SPeter Wemm 								 : O_RDONLY;
1973c2aa98e2SPeter Wemm 
19748774250cSGregory Neil Shapiro 		if (dfd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
19758774250cSGregory Neil Shapiro 			(void) lockfile(dfd, map->map_file, ".dir", LOCK_UN);
19768774250cSGregory Neil Shapiro 		map->map_mflags |= MF_CLOSING;
1977c2aa98e2SPeter Wemm 		map->map_class->map_close(map);
19788774250cSGregory Neil Shapiro 		map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING);
1979c2aa98e2SPeter Wemm 		if (map->map_class->map_open(map, omode))
1980c2aa98e2SPeter Wemm 		{
1981c2aa98e2SPeter Wemm 			map->map_mflags |= MF_OPEN;
198240266059SGregory Neil Shapiro 			map->map_pid = CurrentPid;
19839bd497b8SGregory Neil Shapiro 			if ((omode & O_ACCMODE) == O_RDWR)
1984c2aa98e2SPeter Wemm 				map->map_mflags |= MF_WRITABLE;
1985c2aa98e2SPeter Wemm 			goto lockdbm;
1986c2aa98e2SPeter Wemm 		}
1987c2aa98e2SPeter Wemm 		else
1988c2aa98e2SPeter Wemm 		{
1989c2aa98e2SPeter Wemm 			if (!bitset(MF_OPTIONAL, map->map_mflags))
1990c2aa98e2SPeter Wemm 			{
1991c2aa98e2SPeter Wemm 				extern MAPCLASS BogusMapClass;
1992c2aa98e2SPeter Wemm 
1993c2aa98e2SPeter Wemm 				*statp = EX_TEMPFAIL;
199440266059SGregory Neil Shapiro 				map->map_orgclass = map->map_class;
1995c2aa98e2SPeter Wemm 				map->map_class = &BogusMapClass;
1996c2aa98e2SPeter Wemm 				map->map_mflags |= MF_OPEN;
199740266059SGregory Neil Shapiro 				map->map_pid = CurrentPid;
1998c2aa98e2SPeter Wemm 				syserr("Cannot reopen NDBM database %s",
1999c2aa98e2SPeter Wemm 					map->map_file);
2000c2aa98e2SPeter Wemm 			}
2001c2aa98e2SPeter Wemm 			return NULL;
2002c2aa98e2SPeter Wemm 		}
2003c2aa98e2SPeter Wemm 	}
2004c2aa98e2SPeter Wemm 	val.dptr = NULL;
2005c2aa98e2SPeter Wemm 	if (bitset(MF_TRY0NULL, map->map_mflags))
2006c2aa98e2SPeter Wemm 	{
2007c2aa98e2SPeter Wemm 		val = dbm_fetch((DBM *) map->map_db1, key);
2008c2aa98e2SPeter Wemm 		if (val.dptr != NULL)
2009c2aa98e2SPeter Wemm 			map->map_mflags &= ~MF_TRY1NULL;
2010c2aa98e2SPeter Wemm 	}
2011c2aa98e2SPeter Wemm 	if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags))
2012c2aa98e2SPeter Wemm 	{
2013c2aa98e2SPeter Wemm 		key.dsize++;
2014c2aa98e2SPeter Wemm 		val = dbm_fetch((DBM *) map->map_db1, key);
2015c2aa98e2SPeter Wemm 		if (val.dptr != NULL)
2016c2aa98e2SPeter Wemm 			map->map_mflags &= ~MF_TRY0NULL;
2017c2aa98e2SPeter Wemm 	}
20188774250cSGregory Neil Shapiro 	if (dfd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
20198774250cSGregory Neil Shapiro 		(void) lockfile(dfd, map->map_file, ".dir", LOCK_UN);
2020c2aa98e2SPeter Wemm 	if (val.dptr == NULL)
2021c2aa98e2SPeter Wemm 		return NULL;
2022c2aa98e2SPeter Wemm 	if (bitset(MF_MATCHONLY, map->map_mflags))
2023c2aa98e2SPeter Wemm 		return map_rewrite(map, name, strlen(name), NULL);
2024c2aa98e2SPeter Wemm 	else
2025c2aa98e2SPeter Wemm 		return map_rewrite(map, val.dptr, val.dsize, av);
2026c2aa98e2SPeter Wemm }
2027c2aa98e2SPeter Wemm 
2028c2aa98e2SPeter Wemm 
2029c2aa98e2SPeter Wemm /*
2030c2aa98e2SPeter Wemm **  NDBM_MAP_STORE -- store a datum in the database
2031c2aa98e2SPeter Wemm */
2032c2aa98e2SPeter Wemm 
2033c2aa98e2SPeter Wemm void
ndbm_map_store(map,lhs,rhs)2034c2aa98e2SPeter Wemm ndbm_map_store(map, lhs, rhs)
2035c2aa98e2SPeter Wemm 	register MAP *map;
2036c2aa98e2SPeter Wemm 	char *lhs;
2037c2aa98e2SPeter Wemm 	char *rhs;
2038c2aa98e2SPeter Wemm {
2039c2aa98e2SPeter Wemm 	datum key;
2040c2aa98e2SPeter Wemm 	datum data;
204106f25ae9SGregory Neil Shapiro 	int status;
20422fb4f839SGregory Neil Shapiro 	char keybuf[MAXNAME + 1];	/* EAI:ok */
2043c2aa98e2SPeter Wemm 
2044c2aa98e2SPeter Wemm 	if (tTd(38, 12))
204540266059SGregory Neil Shapiro 		sm_dprintf("ndbm_map_store(%s, %s, %s)\n",
2046c2aa98e2SPeter Wemm 			map->map_mname, lhs, rhs);
2047c2aa98e2SPeter Wemm 
2048c2aa98e2SPeter Wemm 	key.dsize = strlen(lhs);
2049c2aa98e2SPeter Wemm 	key.dptr = lhs;
2050c2aa98e2SPeter Wemm 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
2051c2aa98e2SPeter Wemm 	{
2052d0cef73dSGregory Neil Shapiro 		if (key.dsize > sizeof(keybuf) - 1)
2053d0cef73dSGregory Neil Shapiro 			key.dsize = sizeof(keybuf) - 1;
205406f25ae9SGregory Neil Shapiro 		memmove(keybuf, key.dptr, key.dsize);
2055c2aa98e2SPeter Wemm 		keybuf[key.dsize] = '\0';
20562fb4f839SGregory Neil Shapiro 		makelower_buf(keybuf, keybuf, sizeof(keybuf));
2057c2aa98e2SPeter Wemm 		key.dptr = keybuf;
2058c2aa98e2SPeter Wemm 	}
2059c2aa98e2SPeter Wemm 
2060c2aa98e2SPeter Wemm 	data.dsize = strlen(rhs);
2061c2aa98e2SPeter Wemm 	data.dptr = rhs;
2062c2aa98e2SPeter Wemm 
2063c2aa98e2SPeter Wemm 	if (bitset(MF_INCLNULL, map->map_mflags))
2064c2aa98e2SPeter Wemm 	{
2065c2aa98e2SPeter Wemm 		key.dsize++;
2066c2aa98e2SPeter Wemm 		data.dsize++;
2067c2aa98e2SPeter Wemm 	}
2068c2aa98e2SPeter Wemm 
206906f25ae9SGregory Neil Shapiro 	status = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT);
207006f25ae9SGregory Neil Shapiro 	if (status > 0)
2071c2aa98e2SPeter Wemm 	{
2072c2aa98e2SPeter Wemm 		if (!bitset(MF_APPEND, map->map_mflags))
2073c2aa98e2SPeter Wemm 			message("050 Warning: duplicate alias name %s", lhs);
2074c2aa98e2SPeter Wemm 		else
2075c2aa98e2SPeter Wemm 		{
2076c2aa98e2SPeter Wemm 			static char *buf = NULL;
2077c2aa98e2SPeter Wemm 			static int bufsiz = 0;
2078c2aa98e2SPeter Wemm 			auto int xstat;
2079c2aa98e2SPeter Wemm 			datum old;
2080c2aa98e2SPeter Wemm 
2081c2aa98e2SPeter Wemm 			old.dptr = ndbm_map_lookup(map, key.dptr,
2082c2aa98e2SPeter Wemm 						   (char **) NULL, &xstat);
2083c2aa98e2SPeter Wemm 			if (old.dptr != NULL && *(char *) old.dptr != '\0')
2084c2aa98e2SPeter Wemm 			{
2085c2aa98e2SPeter Wemm 				old.dsize = strlen(old.dptr);
2086c2aa98e2SPeter Wemm 				if (data.dsize + old.dsize + 2 > bufsiz)
2087c2aa98e2SPeter Wemm 				{
20882fb4f839SGregory Neil Shapiro 					SM_FREE(buf);
2089c2aa98e2SPeter Wemm 					bufsiz = data.dsize + old.dsize + 2;
209040266059SGregory Neil Shapiro 					buf = sm_pmalloc_x(bufsiz);
2091c2aa98e2SPeter Wemm 				}
209240266059SGregory Neil Shapiro 				(void) sm_strlcpyn(buf, bufsiz, 3,
209340266059SGregory Neil Shapiro 					data.dptr, ",", old.dptr);
2094c2aa98e2SPeter Wemm 				data.dsize = data.dsize + old.dsize + 1;
2095c2aa98e2SPeter Wemm 				data.dptr = buf;
2096c2aa98e2SPeter Wemm 				if (tTd(38, 9))
209740266059SGregory Neil Shapiro 					sm_dprintf("ndbm_map_store append=%s\n",
20985b0945b5SGregory Neil Shapiro 						data.dptr);
2099c2aa98e2SPeter Wemm 			}
2100c2aa98e2SPeter Wemm 		}
210106f25ae9SGregory Neil Shapiro 		status = dbm_store((DBM *) map->map_db1,
210206f25ae9SGregory Neil Shapiro 				   key, data, DBM_REPLACE);
2103c2aa98e2SPeter Wemm 	}
210406f25ae9SGregory Neil Shapiro 	if (status != 0)
210506f25ae9SGregory Neil Shapiro 		syserr("readaliases: dbm put (%s): %d", lhs, status);
2106c2aa98e2SPeter Wemm }
2107c2aa98e2SPeter Wemm 
2108c2aa98e2SPeter Wemm 
2109c2aa98e2SPeter Wemm /*
2110c2aa98e2SPeter Wemm **  NDBM_MAP_CLOSE -- close the database
2111c2aa98e2SPeter Wemm */
2112c2aa98e2SPeter Wemm 
2113c2aa98e2SPeter Wemm void
ndbm_map_close(map)2114c2aa98e2SPeter Wemm ndbm_map_close(map)
2115c2aa98e2SPeter Wemm 	register MAP  *map;
2116c2aa98e2SPeter Wemm {
2117c2aa98e2SPeter Wemm 	if (tTd(38, 9))
211840266059SGregory Neil Shapiro 		sm_dprintf("ndbm_map_close(%s, %s, %lx)\n",
2119c2aa98e2SPeter Wemm 			map->map_mname, map->map_file, map->map_mflags);
2120c2aa98e2SPeter Wemm 
2121c2aa98e2SPeter Wemm 	if (bitset(MF_WRITABLE, map->map_mflags))
2122c2aa98e2SPeter Wemm 	{
2123c2aa98e2SPeter Wemm # ifdef NDBM_YP_COMPAT
2124c2aa98e2SPeter Wemm 		bool inclnull;
2125065a643dSPeter Wemm 		char buf[MAXHOSTNAMELEN];
2126c2aa98e2SPeter Wemm 
2127c2aa98e2SPeter Wemm 		inclnull = bitset(MF_INCLNULL, map->map_mflags);
2128c2aa98e2SPeter Wemm 		map->map_mflags &= ~MF_INCLNULL;
2129c2aa98e2SPeter Wemm 
2130c2aa98e2SPeter Wemm 		if (strstr(map->map_file, "/yp/") != NULL)
2131c2aa98e2SPeter Wemm 		{
2132c2aa98e2SPeter Wemm 			long save_mflags = map->map_mflags;
2133c2aa98e2SPeter Wemm 
2134c2aa98e2SPeter Wemm 			map->map_mflags |= MF_NOFOLDCASE;
2135c2aa98e2SPeter Wemm 
2136d0cef73dSGregory Neil Shapiro 			(void) sm_snprintf(buf, sizeof(buf), "%010ld", curtime());
2137c2aa98e2SPeter Wemm 			ndbm_map_store(map, "YP_LAST_MODIFIED", buf);
2138c2aa98e2SPeter Wemm 
2139d0cef73dSGregory Neil Shapiro 			(void) gethostname(buf, sizeof(buf));
2140c2aa98e2SPeter Wemm 			ndbm_map_store(map, "YP_MASTER_NAME", buf);
2141c2aa98e2SPeter Wemm 
2142c2aa98e2SPeter Wemm 			map->map_mflags = save_mflags;
2143c2aa98e2SPeter Wemm 		}
2144c2aa98e2SPeter Wemm 
2145c2aa98e2SPeter Wemm 		if (inclnull)
2146c2aa98e2SPeter Wemm 			map->map_mflags |= MF_INCLNULL;
214706f25ae9SGregory Neil Shapiro # endif /* NDBM_YP_COMPAT */
2148c2aa98e2SPeter Wemm 
2149c2aa98e2SPeter Wemm 		/* write out the distinguished alias */
2150c2aa98e2SPeter Wemm 		ndbm_map_store(map, "@", "@");
2151c2aa98e2SPeter Wemm 	}
2152c2aa98e2SPeter Wemm 	dbm_close((DBM *) map->map_db1);
2153c2aa98e2SPeter Wemm 
2154c2aa98e2SPeter Wemm 	/* release lock (if needed) */
2155c2aa98e2SPeter Wemm # if !LOCK_ON_OPEN
2156c2aa98e2SPeter Wemm 	if (map->map_lockfd >= 0)
2157c2aa98e2SPeter Wemm 		(void) close(map->map_lockfd);
21585b0945b5SGregory Neil Shapiro # endif
2159c2aa98e2SPeter Wemm }
2160c2aa98e2SPeter Wemm 
216106f25ae9SGregory Neil Shapiro #endif /* NDBM */
216240266059SGregory Neil Shapiro /*
2163c2aa98e2SPeter Wemm **  NEWDB (Hash and BTree) Modules
2164c2aa98e2SPeter Wemm */
2165c2aa98e2SPeter Wemm 
216640266059SGregory Neil Shapiro #if NEWDB
2167c2aa98e2SPeter Wemm 
2168c2aa98e2SPeter Wemm /*
2169c2aa98e2SPeter Wemm **  BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives.
2170c2aa98e2SPeter Wemm **
2171c2aa98e2SPeter Wemm **	These do rather bizarre locking.  If you can lock on open,
2172c2aa98e2SPeter Wemm **	do that to avoid the condition of opening a database that
2173c2aa98e2SPeter Wemm **	is being rebuilt.  If you don't, we'll try to fake it, but
2174c2aa98e2SPeter Wemm **	there will be a race condition.  If opening for read-only,
2175c2aa98e2SPeter Wemm **	we immediately release the lock to avoid freezing things up.
2176c2aa98e2SPeter Wemm **	We really ought to hold the lock, but guarantee that we won't
2177c2aa98e2SPeter Wemm **	be pokey about it.  That's hard to do.
2178c2aa98e2SPeter Wemm */
2179c2aa98e2SPeter Wemm 
2180c2aa98e2SPeter Wemm /* these should be K line arguments */
2181c2aa98e2SPeter Wemm # if DB_VERSION_MAJOR < 2
2182c2aa98e2SPeter Wemm #  define db_cachesize	cachesize
2183c2aa98e2SPeter Wemm #  define h_nelem	nelem
2184c2aa98e2SPeter Wemm #  ifndef DB_CACHE_SIZE
2185c2aa98e2SPeter Wemm #   define DB_CACHE_SIZE	(1024 * 1024)	/* database memory cache size */
21865b0945b5SGregory Neil Shapiro #  endif
2187c2aa98e2SPeter Wemm #  ifndef DB_HASH_NELEM
2188c2aa98e2SPeter Wemm #   define DB_HASH_NELEM	4096		/* (starting) size of hash table */
21895b0945b5SGregory Neil Shapiro #  endif
219006f25ae9SGregory Neil Shapiro # endif /* DB_VERSION_MAJOR < 2 */
2191c2aa98e2SPeter Wemm 
2192c2aa98e2SPeter Wemm bool
bt_map_open(map,mode)2193c2aa98e2SPeter Wemm bt_map_open(map, mode)
2194c2aa98e2SPeter Wemm 	MAP *map;
2195c2aa98e2SPeter Wemm 	int mode;
2196c2aa98e2SPeter Wemm {
2197c2aa98e2SPeter Wemm # if DB_VERSION_MAJOR < 2
2198c2aa98e2SPeter Wemm 	BTREEINFO btinfo;
21995b0945b5SGregory Neil Shapiro # endif
220006f25ae9SGregory Neil Shapiro # if DB_VERSION_MAJOR == 2
2201c2aa98e2SPeter Wemm 	DB_INFO btinfo;
22025b0945b5SGregory Neil Shapiro # endif
220306f25ae9SGregory Neil Shapiro # if DB_VERSION_MAJOR > 2
220406f25ae9SGregory Neil Shapiro 	void *btinfo = NULL;
22055b0945b5SGregory Neil Shapiro # endif
2206c2aa98e2SPeter Wemm 
2207c2aa98e2SPeter Wemm 	if (tTd(38, 2))
220840266059SGregory Neil Shapiro 		sm_dprintf("bt_map_open(%s, %s, %d)\n",
2209c2aa98e2SPeter Wemm 			map->map_mname, map->map_file, mode);
2210c2aa98e2SPeter Wemm 
221106f25ae9SGregory Neil Shapiro # if DB_VERSION_MAJOR < 3
2212d0cef73dSGregory Neil Shapiro 	memset(&btinfo, '\0', sizeof(btinfo));
2213c2aa98e2SPeter Wemm #  ifdef DB_CACHE_SIZE
2214c2aa98e2SPeter Wemm 	btinfo.db_cachesize = DB_CACHE_SIZE;
22155b0945b5SGregory Neil Shapiro #  endif
221606f25ae9SGregory Neil Shapiro # endif /* DB_VERSION_MAJOR < 3 */
221706f25ae9SGregory Neil Shapiro 
2218c2aa98e2SPeter Wemm 	return db_map_open(map, mode, "btree", DB_BTREE, &btinfo);
2219c2aa98e2SPeter Wemm }
2220c2aa98e2SPeter Wemm 
2221c2aa98e2SPeter Wemm bool
hash_map_open(map,mode)2222c2aa98e2SPeter Wemm hash_map_open(map, mode)
2223c2aa98e2SPeter Wemm 	MAP *map;
2224c2aa98e2SPeter Wemm 	int mode;
2225c2aa98e2SPeter Wemm {
2226c2aa98e2SPeter Wemm # if DB_VERSION_MAJOR < 2
2227c2aa98e2SPeter Wemm 	HASHINFO hinfo;
22285b0945b5SGregory Neil Shapiro # endif
222906f25ae9SGregory Neil Shapiro # if DB_VERSION_MAJOR == 2
2230c2aa98e2SPeter Wemm 	DB_INFO hinfo;
22315b0945b5SGregory Neil Shapiro # endif
223206f25ae9SGregory Neil Shapiro # if DB_VERSION_MAJOR > 2
223306f25ae9SGregory Neil Shapiro 	void *hinfo = NULL;
22345b0945b5SGregory Neil Shapiro # endif
2235c2aa98e2SPeter Wemm 
2236c2aa98e2SPeter Wemm 	if (tTd(38, 2))
223740266059SGregory Neil Shapiro 		sm_dprintf("hash_map_open(%s, %s, %d)\n",
2238c2aa98e2SPeter Wemm 			map->map_mname, map->map_file, mode);
2239c2aa98e2SPeter Wemm 
224006f25ae9SGregory Neil Shapiro # if DB_VERSION_MAJOR < 3
2241d0cef73dSGregory Neil Shapiro 	memset(&hinfo, '\0', sizeof(hinfo));
2242c2aa98e2SPeter Wemm #  ifdef DB_HASH_NELEM
2243c2aa98e2SPeter Wemm 	hinfo.h_nelem = DB_HASH_NELEM;
22445b0945b5SGregory Neil Shapiro #  endif
2245c2aa98e2SPeter Wemm #  ifdef DB_CACHE_SIZE
2246c2aa98e2SPeter Wemm 	hinfo.db_cachesize = DB_CACHE_SIZE;
22475b0945b5SGregory Neil Shapiro #  endif
224806f25ae9SGregory Neil Shapiro # endif /* DB_VERSION_MAJOR < 3 */
224906f25ae9SGregory Neil Shapiro 
2250c2aa98e2SPeter Wemm 	return db_map_open(map, mode, "hash", DB_HASH, &hinfo);
2251c2aa98e2SPeter Wemm }
2252c2aa98e2SPeter Wemm 
225306f25ae9SGregory Neil Shapiro static bool
2254c2aa98e2SPeter Wemm db_map_open(map, mode, mapclassname, dbtype, openinfo)
2255c2aa98e2SPeter Wemm 	MAP *map;
2256c2aa98e2SPeter Wemm 	int mode;
2257c2aa98e2SPeter Wemm 	char *mapclassname;
2258c2aa98e2SPeter Wemm 	DBTYPE dbtype;
2259c2aa98e2SPeter Wemm # if DB_VERSION_MAJOR < 2
2260c2aa98e2SPeter Wemm 	const void *openinfo;
22615b0945b5SGregory Neil Shapiro # endif
226206f25ae9SGregory Neil Shapiro # if DB_VERSION_MAJOR == 2
2263c2aa98e2SPeter Wemm 	DB_INFO *openinfo;
22645b0945b5SGregory Neil Shapiro # endif
226506f25ae9SGregory Neil Shapiro # if DB_VERSION_MAJOR > 2
226606f25ae9SGregory Neil Shapiro 	void **openinfo;
22675b0945b5SGregory Neil Shapiro # endif
2268c2aa98e2SPeter Wemm {
2269c2aa98e2SPeter Wemm 	DB *db = NULL;
2270c2aa98e2SPeter Wemm 	int i;
2271c2aa98e2SPeter Wemm 	int omode;
2272c2aa98e2SPeter Wemm 	int smode = S_IREAD;
2273c2aa98e2SPeter Wemm 	int fd;
227406f25ae9SGregory Neil Shapiro 	long sff;
227506f25ae9SGregory Neil Shapiro 	int save_errno;
2276c2aa98e2SPeter Wemm 	struct stat st;
227794c01205SGregory Neil Shapiro 	char buf[MAXPATHLEN];
2278c2aa98e2SPeter Wemm 
2279c2aa98e2SPeter Wemm 	/* do initial file and directory checks */
2280*d39bd2c1SGregory Neil Shapiro 	if (!smdb_add_extension(buf, sizeof(buf), map->map_file, "db"))
228194c01205SGregory Neil Shapiro 	{
228294c01205SGregory Neil Shapiro 		errno = 0;
228394c01205SGregory Neil Shapiro 		if (!bitset(MF_OPTIONAL, map->map_mflags))
2284*d39bd2c1SGregory Neil Shapiro 			syserr("db map \"%s\": map file %s name too long",
228594c01205SGregory Neil Shapiro 				map->map_mname, map->map_file);
228694c01205SGregory Neil Shapiro 		return false;
228794c01205SGregory Neil Shapiro 	}
2288c2aa98e2SPeter Wemm 
2289c2aa98e2SPeter Wemm 	mode &= O_ACCMODE;
2290c2aa98e2SPeter Wemm 	omode = mode;
2291c2aa98e2SPeter Wemm 
2292c2aa98e2SPeter Wemm 	sff = SFF_ROOTOK|SFF_REGONLY;
2293c2aa98e2SPeter Wemm 	if (mode == O_RDWR)
2294c2aa98e2SPeter Wemm 	{
2295c2aa98e2SPeter Wemm 		sff |= SFF_CREAT;
229606f25ae9SGregory Neil Shapiro 		if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail))
2297c2aa98e2SPeter Wemm 			sff |= SFF_NOSLINK;
229806f25ae9SGregory Neil Shapiro 		if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail))
2299c2aa98e2SPeter Wemm 			sff |= SFF_NOHLINK;
2300c2aa98e2SPeter Wemm 		smode = S_IWRITE;
2301c2aa98e2SPeter Wemm 	}
2302c2aa98e2SPeter Wemm 	else
2303c2aa98e2SPeter Wemm 	{
230406f25ae9SGregory Neil Shapiro 		if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail))
2305c2aa98e2SPeter Wemm 			sff |= SFF_NOWLINK;
2306c2aa98e2SPeter Wemm 	}
230706f25ae9SGregory Neil Shapiro 	if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail))
2308c2aa98e2SPeter Wemm 		sff |= SFF_SAFEDIRPATH;
2309c2aa98e2SPeter Wemm 	i = safefile(buf, RunAsUid, RunAsGid, RunAsUserName, sff, smode, &st);
231006f25ae9SGregory Neil Shapiro 
2311c2aa98e2SPeter Wemm 	if (i != 0)
2312c2aa98e2SPeter Wemm 	{
2313c2aa98e2SPeter Wemm 		char *prob = "unsafe";
2314c2aa98e2SPeter Wemm 
2315c2aa98e2SPeter Wemm 		/* cannot open this map */
2316c2aa98e2SPeter Wemm 		if (i == ENOENT)
2317c2aa98e2SPeter Wemm 			prob = "missing";
2318c2aa98e2SPeter Wemm 		if (tTd(38, 2))
2319*d39bd2c1SGregory Neil Shapiro 			sm_dprintf("\t%s map file %s: %s\n", prob, buf, sm_errstring(i));
2320c2aa98e2SPeter Wemm 		errno = i;
2321c2aa98e2SPeter Wemm 		if (!bitset(MF_OPTIONAL, map->map_mflags))
2322c2aa98e2SPeter Wemm 			syserr("%s map \"%s\": %s map file %s",
2323c2aa98e2SPeter Wemm 				mapclassname, map->map_mname, prob, buf);
232440266059SGregory Neil Shapiro 		return false;
2325c2aa98e2SPeter Wemm 	}
2326c2aa98e2SPeter Wemm 	if (st.st_mode == ST_MODE_NOFILE)
2327c2aa98e2SPeter Wemm 		omode |= O_CREAT|O_EXCL;
2328c2aa98e2SPeter Wemm 
2329c2aa98e2SPeter Wemm 	map->map_lockfd = -1;
2330c2aa98e2SPeter Wemm 
2331c2aa98e2SPeter Wemm # if LOCK_ON_OPEN
2332c2aa98e2SPeter Wemm 	if (mode == O_RDWR)
2333c2aa98e2SPeter Wemm 		omode |= O_TRUNC|O_EXLOCK;
2334c2aa98e2SPeter Wemm 	else
2335c2aa98e2SPeter Wemm 		omode |= O_SHLOCK;
233606f25ae9SGregory Neil Shapiro # else /* LOCK_ON_OPEN */
2337c2aa98e2SPeter Wemm 	/*
2338c2aa98e2SPeter Wemm 	**  Pre-lock the file to avoid race conditions.  In particular,
2339c2aa98e2SPeter Wemm 	**  since dbopen returns NULL if the file is zero length, we
2340c2aa98e2SPeter Wemm 	**  must have a locked instance around the dbopen.
2341c2aa98e2SPeter Wemm 	*/
2342c2aa98e2SPeter Wemm 
2343c2aa98e2SPeter Wemm 	fd = open(buf, omode, DBMMODE);
2344c2aa98e2SPeter Wemm 	if (fd < 0)
2345c2aa98e2SPeter Wemm 	{
2346c2aa98e2SPeter Wemm 		if (!bitset(MF_OPTIONAL, map->map_mflags))
2347c2aa98e2SPeter Wemm 			syserr("db_map_open: cannot pre-open database %s", buf);
234840266059SGregory Neil Shapiro 		return false;
2349c2aa98e2SPeter Wemm 	}
2350c2aa98e2SPeter Wemm 
2351c2aa98e2SPeter Wemm 	/* make sure no baddies slipped in just before the open... */
2352c2aa98e2SPeter Wemm 	if (filechanged(buf, fd, &st))
2353c2aa98e2SPeter Wemm 	{
235406f25ae9SGregory Neil Shapiro 		save_errno = errno;
2355c2aa98e2SPeter Wemm 		(void) close(fd);
2356c2aa98e2SPeter Wemm 		errno = save_errno;
2357c2aa98e2SPeter Wemm 		syserr("db_map_open(%s): file changed after pre-open", buf);
235840266059SGregory Neil Shapiro 		return false;
2359c2aa98e2SPeter Wemm 	}
2360c2aa98e2SPeter Wemm 
2361c2aa98e2SPeter Wemm 	/* if new file, get the "before" bits for later filechanged check */
2362c2aa98e2SPeter Wemm 	if (st.st_mode == ST_MODE_NOFILE && fstat(fd, &st) < 0)
2363c2aa98e2SPeter Wemm 	{
236406f25ae9SGregory Neil Shapiro 		save_errno = errno;
2365c2aa98e2SPeter Wemm 		(void) close(fd);
2366c2aa98e2SPeter Wemm 		errno = save_errno;
2367c2aa98e2SPeter Wemm 		syserr("db_map_open(%s): cannot fstat pre-opened file",
2368c2aa98e2SPeter Wemm 			buf);
236940266059SGregory Neil Shapiro 		return false;
2370c2aa98e2SPeter Wemm 	}
2371c2aa98e2SPeter Wemm 
2372c2aa98e2SPeter Wemm 	/* actually lock the pre-opened file */
2373c2aa98e2SPeter Wemm 	if (!lockfile(fd, buf, NULL, mode == O_RDONLY ? LOCK_SH : LOCK_EX))
2374c2aa98e2SPeter Wemm 		syserr("db_map_open: cannot lock %s", buf);
2375c2aa98e2SPeter Wemm 
2376c2aa98e2SPeter Wemm 	/* set up mode bits for dbopen */
2377c2aa98e2SPeter Wemm 	if (mode == O_RDWR)
2378c2aa98e2SPeter Wemm 		omode |= O_TRUNC;
2379c2aa98e2SPeter Wemm 	omode &= ~(O_EXCL|O_CREAT);
238006f25ae9SGregory Neil Shapiro # endif /* LOCK_ON_OPEN */
2381c2aa98e2SPeter Wemm 
2382c2aa98e2SPeter Wemm # if DB_VERSION_MAJOR < 2
2383c2aa98e2SPeter Wemm 	db = dbopen(buf, omode, DBMMODE, dbtype, openinfo);
238406f25ae9SGregory Neil Shapiro # else /* DB_VERSION_MAJOR < 2 */
2385c2aa98e2SPeter Wemm 	{
2386c2aa98e2SPeter Wemm 		int flags = 0;
238706f25ae9SGregory Neil Shapiro #  if DB_VERSION_MAJOR > 2
238806f25ae9SGregory Neil Shapiro 		int ret;
23895b0945b5SGregory Neil Shapiro #  endif
2390c2aa98e2SPeter Wemm 
2391c2aa98e2SPeter Wemm 		if (mode == O_RDONLY)
2392c2aa98e2SPeter Wemm 			flags |= DB_RDONLY;
2393c2aa98e2SPeter Wemm 		if (bitset(O_CREAT, omode))
2394c2aa98e2SPeter Wemm 			flags |= DB_CREATE;
2395c2aa98e2SPeter Wemm 		if (bitset(O_TRUNC, omode))
2396c2aa98e2SPeter Wemm 			flags |= DB_TRUNCATE;
239713bd1963SGregory Neil Shapiro 		SM_DB_FLAG_ADD(flags);
239806f25ae9SGregory Neil Shapiro 
239906f25ae9SGregory Neil Shapiro #  if DB_VERSION_MAJOR > 2
240006f25ae9SGregory Neil Shapiro 		ret = db_create(&db, NULL, 0);
240106f25ae9SGregory Neil Shapiro #   ifdef DB_CACHE_SIZE
240206f25ae9SGregory Neil Shapiro 		if (ret == 0 && db != NULL)
240306f25ae9SGregory Neil Shapiro 		{
240406f25ae9SGregory Neil Shapiro 			ret = db->set_cachesize(db, 0, DB_CACHE_SIZE, 0);
240506f25ae9SGregory Neil Shapiro 			if (ret != 0)
240606f25ae9SGregory Neil Shapiro 			{
240706f25ae9SGregory Neil Shapiro 				(void) db->close(db, 0);
240806f25ae9SGregory Neil Shapiro 				db = NULL;
240906f25ae9SGregory Neil Shapiro 			}
241006f25ae9SGregory Neil Shapiro 		}
241106f25ae9SGregory Neil Shapiro #   endif /* DB_CACHE_SIZE */
241206f25ae9SGregory Neil Shapiro #   ifdef DB_HASH_NELEM
241306f25ae9SGregory Neil Shapiro 		if (dbtype == DB_HASH && ret == 0 && db != NULL)
241406f25ae9SGregory Neil Shapiro 		{
241506f25ae9SGregory Neil Shapiro 			ret = db->set_h_nelem(db, DB_HASH_NELEM);
241606f25ae9SGregory Neil Shapiro 			if (ret != 0)
241706f25ae9SGregory Neil Shapiro 			{
241806f25ae9SGregory Neil Shapiro 				(void) db->close(db, 0);
241906f25ae9SGregory Neil Shapiro 				db = NULL;
242006f25ae9SGregory Neil Shapiro 			}
242106f25ae9SGregory Neil Shapiro 		}
242206f25ae9SGregory Neil Shapiro #   endif /* DB_HASH_NELEM */
242306f25ae9SGregory Neil Shapiro 		if (ret == 0 && db != NULL)
242406f25ae9SGregory Neil Shapiro 		{
242513bd1963SGregory Neil Shapiro 			ret = db->open(db,
242613bd1963SGregory Neil Shapiro 					DBTXN	/* transaction for DB 4.1 */
242713bd1963SGregory Neil Shapiro 					buf, NULL, dbtype, flags, DBMMODE);
242806f25ae9SGregory Neil Shapiro 			if (ret != 0)
242906f25ae9SGregory Neil Shapiro 			{
2430602a2b1bSGregory Neil Shapiro #   ifdef DB_OLD_VERSION
2431602a2b1bSGregory Neil Shapiro 				if (ret == DB_OLD_VERSION)
2432602a2b1bSGregory Neil Shapiro 					ret = EINVAL;
2433602a2b1bSGregory Neil Shapiro #   endif /* DB_OLD_VERSION */
243406f25ae9SGregory Neil Shapiro 				(void) db->close(db, 0);
243506f25ae9SGregory Neil Shapiro 				db = NULL;
243606f25ae9SGregory Neil Shapiro 			}
243706f25ae9SGregory Neil Shapiro 		}
243806f25ae9SGregory Neil Shapiro 		errno = ret;
243906f25ae9SGregory Neil Shapiro #  else /* DB_VERSION_MAJOR > 2 */
2440c2aa98e2SPeter Wemm 		errno = db_open(buf, dbtype, flags, DBMMODE,
2441c2aa98e2SPeter Wemm 				NULL, openinfo, &db);
244206f25ae9SGregory Neil Shapiro #  endif /* DB_VERSION_MAJOR > 2 */
2443c2aa98e2SPeter Wemm 	}
244406f25ae9SGregory Neil Shapiro # endif /* DB_VERSION_MAJOR < 2 */
244506f25ae9SGregory Neil Shapiro 	save_errno = errno;
2446c2aa98e2SPeter Wemm 
2447c2aa98e2SPeter Wemm # if !LOCK_ON_OPEN
2448c2aa98e2SPeter Wemm 	if (mode == O_RDWR)
2449c2aa98e2SPeter Wemm 		map->map_lockfd = fd;
2450c2aa98e2SPeter Wemm 	else
2451c2aa98e2SPeter Wemm 		(void) close(fd);
245206f25ae9SGregory Neil Shapiro # endif /* !LOCK_ON_OPEN */
2453c2aa98e2SPeter Wemm 
2454c2aa98e2SPeter Wemm 	if (db == NULL)
2455c2aa98e2SPeter Wemm 	{
2456c2aa98e2SPeter Wemm 		if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags) &&
245740266059SGregory Neil Shapiro 		    aliaswait(map, ".db", false))
245840266059SGregory Neil Shapiro 			return true;
2459c2aa98e2SPeter Wemm # if !LOCK_ON_OPEN
2460c2aa98e2SPeter Wemm 		if (map->map_lockfd >= 0)
2461c2aa98e2SPeter Wemm 			(void) close(map->map_lockfd);
24625b0945b5SGregory Neil Shapiro # endif
246306f25ae9SGregory Neil Shapiro 		errno = save_errno;
2464c2aa98e2SPeter Wemm 		if (!bitset(MF_OPTIONAL, map->map_mflags))
2465c2aa98e2SPeter Wemm 			syserr("Cannot open %s database %s",
2466c2aa98e2SPeter Wemm 				mapclassname, buf);
246740266059SGregory Neil Shapiro 		return false;
2468c2aa98e2SPeter Wemm 	}
2469c2aa98e2SPeter Wemm 
2470c2aa98e2SPeter Wemm # if DB_VERSION_MAJOR < 2
2471c2aa98e2SPeter Wemm 	fd = db->fd(db);
24725b0945b5SGregory Neil Shapiro # else
2473c2aa98e2SPeter Wemm 	fd = -1;
2474c2aa98e2SPeter Wemm 	errno = db->fd(db, &fd);
247506f25ae9SGregory Neil Shapiro # endif /* DB_VERSION_MAJOR < 2 */
2476c2aa98e2SPeter Wemm 	if (filechanged(buf, fd, &st))
2477c2aa98e2SPeter Wemm 	{
247806f25ae9SGregory Neil Shapiro 		save_errno = errno;
2479c2aa98e2SPeter Wemm # if DB_VERSION_MAJOR < 2
248006f25ae9SGregory Neil Shapiro 		(void) db->close(db);
24815b0945b5SGregory Neil Shapiro # else
2482c2aa98e2SPeter Wemm 		errno = db->close(db, 0);
248306f25ae9SGregory Neil Shapiro # endif /* DB_VERSION_MAJOR < 2 */
2484c2aa98e2SPeter Wemm # if !LOCK_ON_OPEN
2485c2aa98e2SPeter Wemm 		if (map->map_lockfd >= 0)
248606f25ae9SGregory Neil Shapiro 			(void) close(map->map_lockfd);
24875b0945b5SGregory Neil Shapiro # endif
2488c2aa98e2SPeter Wemm 		errno = save_errno;
2489c2aa98e2SPeter Wemm 		syserr("db_map_open(%s): file changed after open", buf);
249040266059SGregory Neil Shapiro 		return false;
2491c2aa98e2SPeter Wemm 	}
2492c2aa98e2SPeter Wemm 
2493c2aa98e2SPeter Wemm 	if (mode == O_RDWR)
2494c2aa98e2SPeter Wemm 		map->map_mflags |= MF_LOCKED;
2495c2aa98e2SPeter Wemm # if LOCK_ON_OPEN
2496c2aa98e2SPeter Wemm 	if (fd >= 0 && mode == O_RDONLY)
2497c2aa98e2SPeter Wemm 		(void) lockfile(fd, buf, NULL, LOCK_UN);
2498*d39bd2c1SGregory Neil Shapiro # endif
2499c2aa98e2SPeter Wemm 
2500c2aa98e2SPeter Wemm 	/* try to make sure that at least the database header is on disk */
2501c2aa98e2SPeter Wemm 	if (mode == O_RDWR)
2502c2aa98e2SPeter Wemm 	{
2503c2aa98e2SPeter Wemm 		(void) db->sync(db, 0);
2504*d39bd2c1SGregory Neil Shapiro 		mapchown(map->map_file, fd, -1, buf);
2505c2aa98e2SPeter Wemm 	}
2506c2aa98e2SPeter Wemm 
250706f25ae9SGregory Neil Shapiro 	map->map_db2 = (ARBPTR_T) db;
250806f25ae9SGregory Neil Shapiro 
250906f25ae9SGregory Neil Shapiro 	/*
251006f25ae9SGregory Neil Shapiro 	**  Need to set map_mtime before the call to aliaswait()
251106f25ae9SGregory Neil Shapiro 	**  as aliaswait() will call map_lookup() which requires
251206f25ae9SGregory Neil Shapiro 	**  map_mtime to be set
251306f25ae9SGregory Neil Shapiro 	*/
251406f25ae9SGregory Neil Shapiro 
2515c2aa98e2SPeter Wemm 	if (fd >= 0 && fstat(fd, &st) >= 0)
2516c2aa98e2SPeter Wemm 		map->map_mtime = st.st_mtime;
2517c2aa98e2SPeter Wemm 
2518*d39bd2c1SGregory Neil Shapiro # if _FFR_TESTS
2519*d39bd2c1SGregory Neil Shapiro 	if (tTd(68, 101) && fd >= 0 && mode == O_RDONLY)
2520*d39bd2c1SGregory Neil Shapiro 	{
2521*d39bd2c1SGregory Neil Shapiro 		int sl;
2522*d39bd2c1SGregory Neil Shapiro 
2523*d39bd2c1SGregory Neil Shapiro 		sl = tTdlevel(68) - 100;
2524*d39bd2c1SGregory Neil Shapiro 		/* XXX test checks for map type!!! */
2525*d39bd2c1SGregory Neil Shapiro 		sm_dprintf("hash_map_open: sleep=%d\n", sl);
2526*d39bd2c1SGregory Neil Shapiro 		sleep(sl);
2527*d39bd2c1SGregory Neil Shapiro 	}
2528*d39bd2c1SGregory Neil Shapiro # endif
2529*d39bd2c1SGregory Neil Shapiro 
2530c2aa98e2SPeter Wemm 	if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags) &&
253140266059SGregory Neil Shapiro 	    !aliaswait(map, ".db", true))
253240266059SGregory Neil Shapiro 		return false;
253340266059SGregory Neil Shapiro 	return true;
2534c2aa98e2SPeter Wemm }
2535c2aa98e2SPeter Wemm 
2536c2aa98e2SPeter Wemm 
2537c2aa98e2SPeter Wemm /*
2538c2aa98e2SPeter Wemm **  DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map
2539c2aa98e2SPeter Wemm */
2540c2aa98e2SPeter Wemm 
2541c2aa98e2SPeter Wemm char *
db_map_lookup(map,name,av,statp)2542c2aa98e2SPeter Wemm db_map_lookup(map, name, av, statp)
2543c2aa98e2SPeter Wemm 	MAP *map;
2544c2aa98e2SPeter Wemm 	char *name;
2545c2aa98e2SPeter Wemm 	char **av;
2546c2aa98e2SPeter Wemm 	int *statp;
2547c2aa98e2SPeter Wemm {
2548c2aa98e2SPeter Wemm 	DBT key, val;
2549c2aa98e2SPeter Wemm 	register DB *db = (DB *) map->map_db2;
2550c2aa98e2SPeter Wemm 	int st;
255106f25ae9SGregory Neil Shapiro 	int save_errno;
2552c2aa98e2SPeter Wemm 	int fd;
25532fb4f839SGregory Neil Shapiro 	char keybuf[MAXNAME + 1];	/* EAI:ok */
255494c01205SGregory Neil Shapiro 	char buf[MAXPATHLEN];
2555c2aa98e2SPeter Wemm 
2556d0cef73dSGregory Neil Shapiro 	memset(&key, '\0', sizeof(key));
2557d0cef73dSGregory Neil Shapiro 	memset(&val, '\0', sizeof(val));
2558c2aa98e2SPeter Wemm 
2559c2aa98e2SPeter Wemm 	if (tTd(38, 20))
256040266059SGregory Neil Shapiro 		sm_dprintf("db_map_lookup(%s, %s)\n",
2561c2aa98e2SPeter Wemm 			map->map_mname, name);
2562*d39bd2c1SGregory Neil Shapiro 	if (!smdb_add_extension(buf, sizeof(buf), map->map_file, "db"))
256394c01205SGregory Neil Shapiro 	{
256494c01205SGregory Neil Shapiro 		errno = 0;
256594c01205SGregory Neil Shapiro 		if (!bitset(MF_OPTIONAL, map->map_mflags))
2566*d39bd2c1SGregory Neil Shapiro 			syserr("db map \"%s\": map file %s name too long",
256794c01205SGregory Neil Shapiro 				map->map_mname, map->map_file);
256894c01205SGregory Neil Shapiro 		return NULL;
256994c01205SGregory Neil Shapiro 	}
2570c2aa98e2SPeter Wemm 
2571c2aa98e2SPeter Wemm 	key.size = strlen(name);
2572d0cef73dSGregory Neil Shapiro 	if (key.size > sizeof(keybuf) - 1)
2573d0cef73dSGregory Neil Shapiro 		key.size = sizeof(keybuf) - 1;
2574c2aa98e2SPeter Wemm 	key.data = keybuf;
257506f25ae9SGregory Neil Shapiro 	memmove(keybuf, name, key.size);
2576c2aa98e2SPeter Wemm 	keybuf[key.size] = '\0';
2577c2aa98e2SPeter Wemm 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
25782fb4f839SGregory Neil Shapiro 		makelower_buf(keybuf, keybuf, sizeof(keybuf));
2579c2aa98e2SPeter Wemm   lockdb:
2580c2aa98e2SPeter Wemm # if DB_VERSION_MAJOR < 2
2581c2aa98e2SPeter Wemm 	fd = db->fd(db);
25825b0945b5SGregory Neil Shapiro # else
2583c2aa98e2SPeter Wemm 	fd = -1;
2584c2aa98e2SPeter Wemm 	errno = db->fd(db, &fd);
258506f25ae9SGregory Neil Shapiro # endif /* DB_VERSION_MAJOR < 2 */
2586c2aa98e2SPeter Wemm 	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
2587*d39bd2c1SGregory Neil Shapiro 		(void) lockfile(fd, buf, NULL, LOCK_SH);
2588*d39bd2c1SGregory Neil Shapiro 	if (map_has_chged(map, buf, fd))
2589c2aa98e2SPeter Wemm 	{
2590c2aa98e2SPeter Wemm 		/* Reopen the database to sync the cache */
2591c2aa98e2SPeter Wemm 		int omode = bitset(map->map_mflags, MF_WRITABLE) ? O_RDWR
2592c2aa98e2SPeter Wemm 								 : O_RDONLY;
2593c2aa98e2SPeter Wemm 
259406f25ae9SGregory Neil Shapiro 		if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
2595*d39bd2c1SGregory Neil Shapiro 			(void) lockfile(fd, buf, NULL, LOCK_UN);
25968774250cSGregory Neil Shapiro 		map->map_mflags |= MF_CLOSING;
2597c2aa98e2SPeter Wemm 		map->map_class->map_close(map);
25988774250cSGregory Neil Shapiro 		map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING);
2599c2aa98e2SPeter Wemm 		if (map->map_class->map_open(map, omode))
2600c2aa98e2SPeter Wemm 		{
2601c2aa98e2SPeter Wemm 			map->map_mflags |= MF_OPEN;
260240266059SGregory Neil Shapiro 			map->map_pid = CurrentPid;
26039bd497b8SGregory Neil Shapiro 			if ((omode & O_ACCMODE) == O_RDWR)
2604c2aa98e2SPeter Wemm 				map->map_mflags |= MF_WRITABLE;
2605c2aa98e2SPeter Wemm 			db = (DB *) map->map_db2;
2606c2aa98e2SPeter Wemm 			goto lockdb;
2607c2aa98e2SPeter Wemm 		}
2608c2aa98e2SPeter Wemm 		else
2609c2aa98e2SPeter Wemm 		{
2610c2aa98e2SPeter Wemm 			if (!bitset(MF_OPTIONAL, map->map_mflags))
2611c2aa98e2SPeter Wemm 			{
2612c2aa98e2SPeter Wemm 				extern MAPCLASS BogusMapClass;
2613c2aa98e2SPeter Wemm 
2614c2aa98e2SPeter Wemm 				*statp = EX_TEMPFAIL;
261540266059SGregory Neil Shapiro 				map->map_orgclass = map->map_class;
2616c2aa98e2SPeter Wemm 				map->map_class = &BogusMapClass;
2617c2aa98e2SPeter Wemm 				map->map_mflags |= MF_OPEN;
261840266059SGregory Neil Shapiro 				map->map_pid = CurrentPid;
2619c2aa98e2SPeter Wemm 				syserr("Cannot reopen DB database %s",
2620c2aa98e2SPeter Wemm 					map->map_file);
2621c2aa98e2SPeter Wemm 			}
2622c2aa98e2SPeter Wemm 			return NULL;
2623c2aa98e2SPeter Wemm 		}
2624c2aa98e2SPeter Wemm 	}
2625c2aa98e2SPeter Wemm 
2626c2aa98e2SPeter Wemm 	st = 1;
2627c2aa98e2SPeter Wemm 	if (bitset(MF_TRY0NULL, map->map_mflags))
2628c2aa98e2SPeter Wemm 	{
2629c2aa98e2SPeter Wemm # if DB_VERSION_MAJOR < 2
2630c2aa98e2SPeter Wemm 		st = db->get(db, &key, &val, 0);
263106f25ae9SGregory Neil Shapiro # else /* DB_VERSION_MAJOR < 2 */
2632c2aa98e2SPeter Wemm 		errno = db->get(db, NULL, &key, &val, 0);
2633c2aa98e2SPeter Wemm 		switch (errno)
2634c2aa98e2SPeter Wemm 		{
2635c2aa98e2SPeter Wemm 		  case DB_NOTFOUND:
2636c2aa98e2SPeter Wemm 		  case DB_KEYEMPTY:
2637c2aa98e2SPeter Wemm 			st = 1;
2638c2aa98e2SPeter Wemm 			break;
2639c2aa98e2SPeter Wemm 
2640c2aa98e2SPeter Wemm 		  case 0:
2641c2aa98e2SPeter Wemm 			st = 0;
2642c2aa98e2SPeter Wemm 			break;
2643c2aa98e2SPeter Wemm 
2644c2aa98e2SPeter Wemm 		  default:
2645c2aa98e2SPeter Wemm 			st = -1;
2646c2aa98e2SPeter Wemm 			break;
2647c2aa98e2SPeter Wemm 		}
264806f25ae9SGregory Neil Shapiro # endif /* DB_VERSION_MAJOR < 2 */
2649c2aa98e2SPeter Wemm 		if (st == 0)
2650c2aa98e2SPeter Wemm 			map->map_mflags &= ~MF_TRY1NULL;
2651c2aa98e2SPeter Wemm 	}
2652c2aa98e2SPeter Wemm 	if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags))
2653c2aa98e2SPeter Wemm 	{
2654c2aa98e2SPeter Wemm 		key.size++;
2655c2aa98e2SPeter Wemm # if DB_VERSION_MAJOR < 2
2656c2aa98e2SPeter Wemm 		st = db->get(db, &key, &val, 0);
265706f25ae9SGregory Neil Shapiro # else /* DB_VERSION_MAJOR < 2 */
2658c2aa98e2SPeter Wemm 		errno = db->get(db, NULL, &key, &val, 0);
2659c2aa98e2SPeter Wemm 		switch (errno)
2660c2aa98e2SPeter Wemm 		{
2661c2aa98e2SPeter Wemm 		  case DB_NOTFOUND:
2662c2aa98e2SPeter Wemm 		  case DB_KEYEMPTY:
2663c2aa98e2SPeter Wemm 			st = 1;
2664c2aa98e2SPeter Wemm 			break;
2665c2aa98e2SPeter Wemm 
2666c2aa98e2SPeter Wemm 		  case 0:
2667c2aa98e2SPeter Wemm 			st = 0;
2668c2aa98e2SPeter Wemm 			break;
2669c2aa98e2SPeter Wemm 
2670c2aa98e2SPeter Wemm 		  default:
2671c2aa98e2SPeter Wemm 			st = -1;
2672c2aa98e2SPeter Wemm 			break;
2673c2aa98e2SPeter Wemm 		}
267406f25ae9SGregory Neil Shapiro # endif /* DB_VERSION_MAJOR < 2 */
2675c2aa98e2SPeter Wemm 		if (st == 0)
2676c2aa98e2SPeter Wemm 			map->map_mflags &= ~MF_TRY0NULL;
2677c2aa98e2SPeter Wemm 	}
267806f25ae9SGregory Neil Shapiro 	save_errno = errno;
2679c2aa98e2SPeter Wemm 	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
2680*d39bd2c1SGregory Neil Shapiro 		(void) lockfile(fd, buf, NULL, LOCK_UN);
2681c2aa98e2SPeter Wemm 	if (st != 0)
2682c2aa98e2SPeter Wemm 	{
268306f25ae9SGregory Neil Shapiro 		errno = save_errno;
2684c2aa98e2SPeter Wemm 		if (st < 0)
2685c2aa98e2SPeter Wemm 			syserr("db_map_lookup: get (%s)", name);
2686c2aa98e2SPeter Wemm 		return NULL;
2687c2aa98e2SPeter Wemm 	}
2688c2aa98e2SPeter Wemm 	if (bitset(MF_MATCHONLY, map->map_mflags))
2689c2aa98e2SPeter Wemm 		return map_rewrite(map, name, strlen(name), NULL);
2690c2aa98e2SPeter Wemm 	else
2691c2aa98e2SPeter Wemm 		return map_rewrite(map, val.data, val.size, av);
2692c2aa98e2SPeter Wemm }
2693c2aa98e2SPeter Wemm 
2694c2aa98e2SPeter Wemm 
2695c2aa98e2SPeter Wemm /*
2696c2aa98e2SPeter Wemm **  DB_MAP_STORE -- store a datum in the NEWDB database
2697c2aa98e2SPeter Wemm */
2698c2aa98e2SPeter Wemm 
2699c2aa98e2SPeter Wemm void
db_map_store(map,lhs,rhs)2700c2aa98e2SPeter Wemm db_map_store(map, lhs, rhs)
2701c2aa98e2SPeter Wemm 	register MAP *map;
2702c2aa98e2SPeter Wemm 	char *lhs;
2703c2aa98e2SPeter Wemm 	char *rhs;
2704c2aa98e2SPeter Wemm {
270506f25ae9SGregory Neil Shapiro 	int status;
2706c2aa98e2SPeter Wemm 	DBT key;
2707c2aa98e2SPeter Wemm 	DBT data;
2708c2aa98e2SPeter Wemm 	register DB *db = map->map_db2;
27092fb4f839SGregory Neil Shapiro 	char keybuf[MAXNAME + 1];	/* EAI:ok */
2710c2aa98e2SPeter Wemm 
2711d0cef73dSGregory Neil Shapiro 	memset(&key, '\0', sizeof(key));
2712d0cef73dSGregory Neil Shapiro 	memset(&data, '\0', sizeof(data));
2713c2aa98e2SPeter Wemm 
2714c2aa98e2SPeter Wemm 	if (tTd(38, 12))
271540266059SGregory Neil Shapiro 		sm_dprintf("db_map_store(%s, %s, %s)\n",
2716c2aa98e2SPeter Wemm 			map->map_mname, lhs, rhs);
2717c2aa98e2SPeter Wemm 
2718c2aa98e2SPeter Wemm 	key.size = strlen(lhs);
2719c2aa98e2SPeter Wemm 	key.data = lhs;
2720c2aa98e2SPeter Wemm 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
2721c2aa98e2SPeter Wemm 	{
2722d0cef73dSGregory Neil Shapiro 		if (key.size > sizeof(keybuf) - 1)
2723d0cef73dSGregory Neil Shapiro 			key.size = sizeof(keybuf) - 1;
272406f25ae9SGregory Neil Shapiro 		memmove(keybuf, key.data, key.size);
2725c2aa98e2SPeter Wemm 		keybuf[key.size] = '\0';
27262fb4f839SGregory Neil Shapiro 		makelower_buf(keybuf, keybuf, sizeof(keybuf));
2727c2aa98e2SPeter Wemm 		key.data = keybuf;
2728c2aa98e2SPeter Wemm 	}
2729c2aa98e2SPeter Wemm 
2730c2aa98e2SPeter Wemm 	data.size = strlen(rhs);
2731c2aa98e2SPeter Wemm 	data.data = rhs;
2732c2aa98e2SPeter Wemm 
2733c2aa98e2SPeter Wemm 	if (bitset(MF_INCLNULL, map->map_mflags))
2734c2aa98e2SPeter Wemm 	{
2735c2aa98e2SPeter Wemm 		key.size++;
2736c2aa98e2SPeter Wemm 		data.size++;
2737c2aa98e2SPeter Wemm 	}
2738c2aa98e2SPeter Wemm 
2739c2aa98e2SPeter Wemm # if DB_VERSION_MAJOR < 2
274006f25ae9SGregory Neil Shapiro 	status = db->put(db, &key, &data, R_NOOVERWRITE);
274106f25ae9SGregory Neil Shapiro # else /* DB_VERSION_MAJOR < 2 */
2742c2aa98e2SPeter Wemm 	errno = db->put(db, NULL, &key, &data, DB_NOOVERWRITE);
2743c2aa98e2SPeter Wemm 	switch (errno)
2744c2aa98e2SPeter Wemm 	{
2745c2aa98e2SPeter Wemm 	  case DB_KEYEXIST:
274606f25ae9SGregory Neil Shapiro 		status = 1;
2747c2aa98e2SPeter Wemm 		break;
2748c2aa98e2SPeter Wemm 
2749c2aa98e2SPeter Wemm 	  case 0:
275006f25ae9SGregory Neil Shapiro 		status = 0;
2751c2aa98e2SPeter Wemm 		break;
2752c2aa98e2SPeter Wemm 
2753c2aa98e2SPeter Wemm 	  default:
275406f25ae9SGregory Neil Shapiro 		status = -1;
2755c2aa98e2SPeter Wemm 		break;
2756c2aa98e2SPeter Wemm 	}
275706f25ae9SGregory Neil Shapiro # endif /* DB_VERSION_MAJOR < 2 */
275806f25ae9SGregory Neil Shapiro 	if (status > 0)
2759c2aa98e2SPeter Wemm 	{
2760c2aa98e2SPeter Wemm 		if (!bitset(MF_APPEND, map->map_mflags))
2761c2aa98e2SPeter Wemm 			message("050 Warning: duplicate alias name %s", lhs);
2762c2aa98e2SPeter Wemm 		else
2763c2aa98e2SPeter Wemm 		{
2764c2aa98e2SPeter Wemm 			static char *buf = NULL;
2765c2aa98e2SPeter Wemm 			static int bufsiz = 0;
2766c2aa98e2SPeter Wemm 			DBT old;
2767c2aa98e2SPeter Wemm 
2768d0cef73dSGregory Neil Shapiro 			memset(&old, '\0', sizeof(old));
2769c2aa98e2SPeter Wemm 
2770c2aa98e2SPeter Wemm 			old.data = db_map_lookup(map, key.data,
277106f25ae9SGregory Neil Shapiro 						 (char **) NULL, &status);
2772c2aa98e2SPeter Wemm 			if (old.data != NULL)
2773c2aa98e2SPeter Wemm 			{
2774c2aa98e2SPeter Wemm 				old.size = strlen(old.data);
277506f25ae9SGregory Neil Shapiro 				if (data.size + old.size + 2 > (size_t) bufsiz)
2776c2aa98e2SPeter Wemm 				{
27772fb4f839SGregory Neil Shapiro 					SM_FREE(buf);
2778c2aa98e2SPeter Wemm 					bufsiz = data.size + old.size + 2;
277940266059SGregory Neil Shapiro 					buf = sm_pmalloc_x(bufsiz);
2780c2aa98e2SPeter Wemm 				}
278140266059SGregory Neil Shapiro 				(void) sm_strlcpyn(buf, bufsiz, 3,
278240266059SGregory Neil Shapiro 					(char *) data.data, ",",
278340266059SGregory Neil Shapiro 					(char *) old.data);
2784c2aa98e2SPeter Wemm 				data.size = data.size + old.size + 1;
2785c2aa98e2SPeter Wemm 				data.data = buf;
2786c2aa98e2SPeter Wemm 				if (tTd(38, 9))
278740266059SGregory Neil Shapiro 					sm_dprintf("db_map_store append=%s\n",
2788c2aa98e2SPeter Wemm 						(char *) data.data);
2789c2aa98e2SPeter Wemm 			}
2790c2aa98e2SPeter Wemm 		}
2791c2aa98e2SPeter Wemm # if DB_VERSION_MAJOR < 2
279206f25ae9SGregory Neil Shapiro 		status = db->put(db, &key, &data, 0);
27935b0945b5SGregory Neil Shapiro # else
279406f25ae9SGregory Neil Shapiro 		status = errno = db->put(db, NULL, &key, &data, 0);
279506f25ae9SGregory Neil Shapiro # endif /* DB_VERSION_MAJOR < 2 */
2796c2aa98e2SPeter Wemm 	}
279706f25ae9SGregory Neil Shapiro 	if (status != 0)
2798c2aa98e2SPeter Wemm 		syserr("readaliases: db put (%s)", lhs);
2799c2aa98e2SPeter Wemm }
2800c2aa98e2SPeter Wemm 
2801c2aa98e2SPeter Wemm 
2802c2aa98e2SPeter Wemm /*
2803c2aa98e2SPeter Wemm **  DB_MAP_CLOSE -- add distinguished entries and close the database
2804c2aa98e2SPeter Wemm */
2805c2aa98e2SPeter Wemm 
2806c2aa98e2SPeter Wemm void
db_map_close(map)2807c2aa98e2SPeter Wemm db_map_close(map)
2808c2aa98e2SPeter Wemm 	MAP *map;
2809c2aa98e2SPeter Wemm {
2810c2aa98e2SPeter Wemm 	register DB *db = map->map_db2;
2811c2aa98e2SPeter Wemm 
2812c2aa98e2SPeter Wemm 	if (tTd(38, 9))
281340266059SGregory Neil Shapiro 		sm_dprintf("db_map_close(%s, %s, %lx)\n",
2814c2aa98e2SPeter Wemm 			map->map_mname, map->map_file, map->map_mflags);
2815c2aa98e2SPeter Wemm 
2816c2aa98e2SPeter Wemm 	if (bitset(MF_WRITABLE, map->map_mflags))
2817c2aa98e2SPeter Wemm 	{
2818c2aa98e2SPeter Wemm 		/* write out the distinguished alias */
2819c2aa98e2SPeter Wemm 		db_map_store(map, "@", "@");
2820c2aa98e2SPeter Wemm 	}
2821c2aa98e2SPeter Wemm 
2822c2aa98e2SPeter Wemm 	(void) db->sync(db, 0);
2823c2aa98e2SPeter Wemm 
2824c2aa98e2SPeter Wemm # if !LOCK_ON_OPEN
2825c2aa98e2SPeter Wemm 	if (map->map_lockfd >= 0)
2826c2aa98e2SPeter Wemm 		(void) close(map->map_lockfd);
282706f25ae9SGregory Neil Shapiro # endif /* !LOCK_ON_OPEN */
2828c2aa98e2SPeter Wemm 
2829c2aa98e2SPeter Wemm # if DB_VERSION_MAJOR < 2
2830c2aa98e2SPeter Wemm 	if (db->close(db) != 0)
283106f25ae9SGregory Neil Shapiro # else /* DB_VERSION_MAJOR < 2 */
2832065a643dSPeter Wemm 	/*
2833065a643dSPeter Wemm 	**  Berkeley DB can use internal shared memory
2834065a643dSPeter Wemm 	**  locking for its memory pool.  Closing a map
2835065a643dSPeter Wemm 	**  opened by another process will interfere
2836065a643dSPeter Wemm 	**  with the shared memory and locks of the parent
2837065a643dSPeter Wemm 	**  process leaving things in a bad state.
28382e43090eSPeter Wemm 	*/
28392e43090eSPeter Wemm 
28402e43090eSPeter Wemm 	/*
2841065a643dSPeter Wemm 	**  If this map was not opened by the current
28422e43090eSPeter Wemm 	**  process, do not close the map but recover
2843065a643dSPeter Wemm 	**  the file descriptor.
2844065a643dSPeter Wemm 	*/
284540266059SGregory Neil Shapiro 
284640266059SGregory Neil Shapiro 	if (map->map_pid != CurrentPid)
2847065a643dSPeter Wemm 	{
2848065a643dSPeter Wemm 		int fd = -1;
2849065a643dSPeter Wemm 
2850065a643dSPeter Wemm 		errno = db->fd(db, &fd);
2851065a643dSPeter Wemm 		if (fd >= 0)
2852065a643dSPeter Wemm 			(void) close(fd);
2853065a643dSPeter Wemm 		return;
2854065a643dSPeter Wemm 	}
2855065a643dSPeter Wemm 
2856c2aa98e2SPeter Wemm 	if ((errno = db->close(db, 0)) != 0)
285706f25ae9SGregory Neil Shapiro # endif /* DB_VERSION_MAJOR < 2 */
2858065a643dSPeter Wemm 		syserr("db_map_close(%s, %s, %lx): db close failure",
2859065a643dSPeter Wemm 			map->map_mname, map->map_file, map->map_mflags);
2860c2aa98e2SPeter Wemm }
286106f25ae9SGregory Neil Shapiro #endif /* NEWDB */
28625b0945b5SGregory Neil Shapiro 
28635b0945b5SGregory Neil Shapiro #if CDB
28645b0945b5SGregory Neil Shapiro /*
28655b0945b5SGregory Neil Shapiro **  CDB Modules
28665b0945b5SGregory Neil Shapiro */
28675b0945b5SGregory Neil Shapiro 
28685b0945b5SGregory Neil Shapiro bool
cdb_map_open(map,mode)28695b0945b5SGregory Neil Shapiro cdb_map_open(map, mode)
28705b0945b5SGregory Neil Shapiro 	MAP *map;
28715b0945b5SGregory Neil Shapiro 	int mode;
28725b0945b5SGregory Neil Shapiro {
28735b0945b5SGregory Neil Shapiro 	int fd, status, omode, smode;
28745b0945b5SGregory Neil Shapiro 	long sff;
28755b0945b5SGregory Neil Shapiro 	struct stat st;
28762fb4f839SGregory Neil Shapiro 	struct cdb *cdbp;
28775b0945b5SGregory Neil Shapiro 	char buf[MAXPATHLEN];
28785b0945b5SGregory Neil Shapiro 
28795b0945b5SGregory Neil Shapiro 	if (tTd(38, 2))
2880*d39bd2c1SGregory Neil Shapiro 		sm_dprintf("cdb_map_open(%s, %s, %s)\n",
2881*d39bd2c1SGregory Neil Shapiro 			map->map_mname, map->map_file,
2882*d39bd2c1SGregory Neil Shapiro 			O_RDWR == (mode & O_ACCMODE) ? "rdwr" : "rdonly");
28835b0945b5SGregory Neil Shapiro 	map->map_db1 = (ARBPTR_T)NULL;
28845b0945b5SGregory Neil Shapiro 	map->map_db2 = (ARBPTR_T)NULL;
28855b0945b5SGregory Neil Shapiro 
28865b0945b5SGregory Neil Shapiro 	mode &= O_ACCMODE;
28875b0945b5SGregory Neil Shapiro 	omode = mode;
28885b0945b5SGregory Neil Shapiro 
28895b0945b5SGregory Neil Shapiro 	/*
28902fb4f839SGregory Neil Shapiro 	**  Note:
28915b0945b5SGregory Neil Shapiro 	**  The code to add the extension and to set up safefile()
28925b0945b5SGregory Neil Shapiro 	**  and open() should be in a common function
28935b0945b5SGregory Neil Shapiro 	**  (it would be nice to re-use libsmdb?)
28945b0945b5SGregory Neil Shapiro 	*/
28955b0945b5SGregory Neil Shapiro 
28965b0945b5SGregory Neil Shapiro 	if (!smdb_add_extension(buf, sizeof(buf), map->map_file, CDBext))
28975b0945b5SGregory Neil Shapiro 	{
28985b0945b5SGregory Neil Shapiro 		errno = 0;
28995b0945b5SGregory Neil Shapiro 		if (!bitset(MF_OPTIONAL, map->map_mflags))
29005b0945b5SGregory Neil Shapiro 			syserr("cdb map \"%s\": map file %s name too long",
29015b0945b5SGregory Neil Shapiro 				map->map_mname, map->map_file);
29025b0945b5SGregory Neil Shapiro 		return false;
29035b0945b5SGregory Neil Shapiro 	}
29045b0945b5SGregory Neil Shapiro 
29055b0945b5SGregory Neil Shapiro 	sff = SFF_ROOTOK|SFF_REGONLY;
29065b0945b5SGregory Neil Shapiro 	if (mode == O_RDWR)
29075b0945b5SGregory Neil Shapiro 	{
29085b0945b5SGregory Neil Shapiro 		sff |= SFF_CREAT;
29095b0945b5SGregory Neil Shapiro 		if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail))
29105b0945b5SGregory Neil Shapiro 			sff |= SFF_NOSLINK;
29115b0945b5SGregory Neil Shapiro 		if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail))
29125b0945b5SGregory Neil Shapiro 			sff |= SFF_NOHLINK;
29135b0945b5SGregory Neil Shapiro 		smode = S_IWRITE;
29142fb4f839SGregory Neil Shapiro 		map->map_mflags |= MF_LOCKED;
29155b0945b5SGregory Neil Shapiro 	}
29165b0945b5SGregory Neil Shapiro 	else
29175b0945b5SGregory Neil Shapiro 	{
29185b0945b5SGregory Neil Shapiro 		smode = S_IREAD;
29195b0945b5SGregory Neil Shapiro 		if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail))
29205b0945b5SGregory Neil Shapiro 			sff |= SFF_NOWLINK;
29215b0945b5SGregory Neil Shapiro 	}
29225b0945b5SGregory Neil Shapiro 	if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail))
29235b0945b5SGregory Neil Shapiro 		sff |= SFF_SAFEDIRPATH;
29245b0945b5SGregory Neil Shapiro 	status = safefile(buf, RunAsUid, RunAsGid, RunAsUserName, sff, smode, &st);
29255b0945b5SGregory Neil Shapiro 	if (status != 0)
29265b0945b5SGregory Neil Shapiro 	{
29275b0945b5SGregory Neil Shapiro 		char *prob = "unsafe";
29285b0945b5SGregory Neil Shapiro 
29295b0945b5SGregory Neil Shapiro 		/* cannot open this map */
29305b0945b5SGregory Neil Shapiro 		if (status == ENOENT)
29315b0945b5SGregory Neil Shapiro 			prob = "missing";
29325b0945b5SGregory Neil Shapiro 		errno = status;
29335b0945b5SGregory Neil Shapiro 		if (tTd(38, 2))
29345b0945b5SGregory Neil Shapiro 			sm_dprintf("\t%s map file: %s\n", prob, sm_errstring(status));
29355b0945b5SGregory Neil Shapiro 		if (!bitset(MF_OPTIONAL, map->map_mflags))
29365b0945b5SGregory Neil Shapiro 			syserr("%s map \"%s\": %s map file %s",
29375b0945b5SGregory Neil Shapiro 				map->map_mname, prob, buf, sm_errstring(status));
29385b0945b5SGregory Neil Shapiro 		return false;
29395b0945b5SGregory Neil Shapiro 	}
29405b0945b5SGregory Neil Shapiro 
29415b0945b5SGregory Neil Shapiro 	if (st.st_mode == ST_MODE_NOFILE)
29425b0945b5SGregory Neil Shapiro 		omode |= O_CREAT|O_EXCL;
29435b0945b5SGregory Neil Shapiro # if LOCK_ON_OPEN
29445b0945b5SGregory Neil Shapiro 	if (mode == O_RDWR)
29455b0945b5SGregory Neil Shapiro 		omode |= O_TRUNC|O_EXLOCK;
29465b0945b5SGregory Neil Shapiro 	else
29475b0945b5SGregory Neil Shapiro 		omode |= O_SHLOCK;
29485b0945b5SGregory Neil Shapiro # else
29495b0945b5SGregory Neil Shapiro 	if (mode == O_RDWR)
29505b0945b5SGregory Neil Shapiro 		omode |= O_TRUNC;
29515b0945b5SGregory Neil Shapiro # endif /* LOCK_ON_OPEN */
29525b0945b5SGregory Neil Shapiro 
29535b0945b5SGregory Neil Shapiro 	fd = open(buf, omode, DBMMODE);
29545b0945b5SGregory Neil Shapiro 	if (fd < 0)
29555b0945b5SGregory Neil Shapiro 	{
29565b0945b5SGregory Neil Shapiro 		if (!bitset(MF_OPTIONAL, map->map_mflags))
29575b0945b5SGregory Neil Shapiro 			syserr("cdb_map_open: cannot open database %s", buf);
29585b0945b5SGregory Neil Shapiro 		return false;
29595b0945b5SGregory Neil Shapiro 	}
29605b0945b5SGregory Neil Shapiro 
29615b0945b5SGregory Neil Shapiro # if !LOCK_ON_OPEN
29625b0945b5SGregory Neil Shapiro 	/* make sure no baddies slipped in just before the open... */
29635b0945b5SGregory Neil Shapiro 	if (filechanged(buf, fd, &st))
29645b0945b5SGregory Neil Shapiro 	{
29655b0945b5SGregory Neil Shapiro 		int save_errno;
29665b0945b5SGregory Neil Shapiro 
29675b0945b5SGregory Neil Shapiro 		save_errno = errno;
29685b0945b5SGregory Neil Shapiro 		(void) close(fd);
29695b0945b5SGregory Neil Shapiro 		errno = save_errno;
29705b0945b5SGregory Neil Shapiro 		syserr("cdb_map_open(%s): file changed after open", buf);
29715b0945b5SGregory Neil Shapiro 		return false;
29725b0945b5SGregory Neil Shapiro 	}
29735b0945b5SGregory Neil Shapiro 
29745b0945b5SGregory Neil Shapiro 	/* actually lock the opened file */
29755b0945b5SGregory Neil Shapiro 	if (!lockfile(fd, buf, NULL, mode == O_RDONLY ? LOCK_SH : LOCK_EX))
29765b0945b5SGregory Neil Shapiro 		syserr("cdb_map_open: cannot lock %s", buf);
2977*d39bd2c1SGregory Neil Shapiro # else /* !LOCK_ON_OPEN */
2978*d39bd2c1SGregory Neil Shapiro 	if (tTd(55, 60))
2979*d39bd2c1SGregory Neil Shapiro 		sm_dprintf("lockopen(%s, fd=%d, action=nb, type=%s): SUCCESS\n",
2980*d39bd2c1SGregory Neil Shapiro 			buf, fd, mode == O_RDONLY ? "rd" : "wr");
29815b0945b5SGregory Neil Shapiro # endif /* !LOCK_ON_OPEN */
29825b0945b5SGregory Neil Shapiro 
29832fb4f839SGregory Neil Shapiro 	map->map_lockfd = fd;
29842fb4f839SGregory Neil Shapiro 
29852fb4f839SGregory Neil Shapiro 	if (fd >= 0 && fstat(fd, &st) >= 0)
29862fb4f839SGregory Neil Shapiro 		map->map_mtime = st.st_mtime;
29872fb4f839SGregory Neil Shapiro 
29885b0945b5SGregory Neil Shapiro 	/* only for aliases! */
29895b0945b5SGregory Neil Shapiro 	if (mode == O_RDWR)
29905b0945b5SGregory Neil Shapiro 	{
29915b0945b5SGregory Neil Shapiro 		struct cdb_make *cdbmp;
29925b0945b5SGregory Neil Shapiro 
29935b0945b5SGregory Neil Shapiro 		cdbmp = (struct cdb_make *) xalloc(sizeof(*cdbmp));
29945b0945b5SGregory Neil Shapiro 		status = cdb_make_start(cdbmp, fd);
29955b0945b5SGregory Neil Shapiro 		if (status != 0)
29965b0945b5SGregory Neil Shapiro 		{
29975b0945b5SGregory Neil Shapiro 			close(fd);
29985b0945b5SGregory Neil Shapiro 			if (!bitset(MF_OPTIONAL, map->map_mflags))
29995b0945b5SGregory Neil Shapiro 				syserr("initialization of cdb map (make) failed");
30005b0945b5SGregory Neil Shapiro 			return false;
30015b0945b5SGregory Neil Shapiro 		}
30025b0945b5SGregory Neil Shapiro 
30035b0945b5SGregory Neil Shapiro 		map->map_db2 = (ARBPTR_T)cdbmp;
3004*d39bd2c1SGregory Neil Shapiro 		mapchown(map->map_file, fd, -1, buf);
30055b0945b5SGregory Neil Shapiro 		return true;
30065b0945b5SGregory Neil Shapiro 	}
3007*d39bd2c1SGregory Neil Shapiro 	(void) lockfile(fd, buf, NULL, LOCK_UN);
3008*d39bd2c1SGregory Neil Shapiro # if _FFR_TESTS
3009*d39bd2c1SGregory Neil Shapiro 	if (tTd(68, 101))
3010*d39bd2c1SGregory Neil Shapiro 	{
3011*d39bd2c1SGregory Neil Shapiro 		int sl;
3012*d39bd2c1SGregory Neil Shapiro 
3013*d39bd2c1SGregory Neil Shapiro 		sl = tTdlevel(68) - 100;
3014*d39bd2c1SGregory Neil Shapiro 		sm_dprintf("cdb_map_open: sleep=%d\n", sl);
3015*d39bd2c1SGregory Neil Shapiro 		sleep(sl);
3016*d39bd2c1SGregory Neil Shapiro 	}
3017*d39bd2c1SGregory Neil Shapiro # endif
30185b0945b5SGregory Neil Shapiro 
30195b0945b5SGregory Neil Shapiro 	cdbp = (struct cdb *) xalloc(sizeof(*cdbp));
30205b0945b5SGregory Neil Shapiro 	status = cdb_init(cdbp, fd);
30215b0945b5SGregory Neil Shapiro 	if (status != 0)
30225b0945b5SGregory Neil Shapiro 	{
30235b0945b5SGregory Neil Shapiro 		close(fd);
30245b0945b5SGregory Neil Shapiro 		if (!bitset(MF_OPTIONAL, map->map_mflags))
30255b0945b5SGregory Neil Shapiro 			syserr("initialization of cdb map failed");
30265b0945b5SGregory Neil Shapiro 		return false;
30275b0945b5SGregory Neil Shapiro 	}
3028*d39bd2c1SGregory Neil Shapiro 
30295b0945b5SGregory Neil Shapiro 	map->map_db1 = (ARBPTR_T)cdbp;
3030*d39bd2c1SGregory Neil Shapiro 	if (bitset(MF_ALIAS, map->map_mflags) && !aliaswait(map, CDBEXT, true))
3031*d39bd2c1SGregory Neil Shapiro 	{
3032*d39bd2c1SGregory Neil Shapiro 		close(fd);	/* XXX more error handling needed? */
3033*d39bd2c1SGregory Neil Shapiro 		return false;
3034*d39bd2c1SGregory Neil Shapiro 	}
30355b0945b5SGregory Neil Shapiro 	return true;
30365b0945b5SGregory Neil Shapiro }
30375b0945b5SGregory Neil Shapiro 
30385b0945b5SGregory Neil Shapiro char *
cdb_map_lookup(map,name,av,statp)30395b0945b5SGregory Neil Shapiro cdb_map_lookup(map, name, av, statp)
30405b0945b5SGregory Neil Shapiro 	MAP *map;
30415b0945b5SGregory Neil Shapiro 	char *name;
30425b0945b5SGregory Neil Shapiro 	char **av;
30435b0945b5SGregory Neil Shapiro 	int *statp;
30445b0945b5SGregory Neil Shapiro {
30455b0945b5SGregory Neil Shapiro 	char *data;
30465b0945b5SGregory Neil Shapiro 	struct cdb *cdbmap;
30475b0945b5SGregory Neil Shapiro 	unsigned int klen, dlen;
30482fb4f839SGregory Neil Shapiro 	int st, fd;
30492fb4f839SGregory Neil Shapiro 	char key[MAXNAME + 1];	/* EAI:ok */
30502fb4f839SGregory Neil Shapiro 	char buf[MAXPATHLEN];
30515b0945b5SGregory Neil Shapiro 
30525b0945b5SGregory Neil Shapiro 	data = NULL;
30535b0945b5SGregory Neil Shapiro 	cdbmap = map->map_db1;
30545b0945b5SGregory Neil Shapiro 	if (tTd(38, 20))
30555b0945b5SGregory Neil Shapiro 		sm_dprintf("cdb_map_lookup(%s, %s)\n", map->map_mname, name);
30565b0945b5SGregory Neil Shapiro 
30572fb4f839SGregory Neil Shapiro 	if (!smdb_add_extension(buf, sizeof(buf), map->map_file, CDBext))
30582fb4f839SGregory Neil Shapiro 	{
30592fb4f839SGregory Neil Shapiro 		errno = 0;
30602fb4f839SGregory Neil Shapiro 		if (!bitset(MF_OPTIONAL, map->map_mflags))
30612fb4f839SGregory Neil Shapiro 			syserr("cdb map \"%s\": map file %s name too long",
30622fb4f839SGregory Neil Shapiro 				map->map_mname, map->map_file);
3063*d39bd2c1SGregory Neil Shapiro 		return NULL;
30642fb4f839SGregory Neil Shapiro 	}
30652fb4f839SGregory Neil Shapiro 
30665b0945b5SGregory Neil Shapiro 	klen = strlen(name);
30675b0945b5SGregory Neil Shapiro 	if (klen > sizeof(key) - 1)
30685b0945b5SGregory Neil Shapiro 		klen = sizeof(key) - 1;
30695b0945b5SGregory Neil Shapiro 	memmove(key, name, klen);
30705b0945b5SGregory Neil Shapiro 	key[klen] = '\0';
30715b0945b5SGregory Neil Shapiro 
30725b0945b5SGregory Neil Shapiro 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
30732fb4f839SGregory Neil Shapiro 		makelower_buf(key, key, sizeof(key));
30742fb4f839SGregory Neil Shapiro 
30752fb4f839SGregory Neil Shapiro   lockdb:
30762fb4f839SGregory Neil Shapiro 	fd = map->map_lockfd;
30772fb4f839SGregory Neil Shapiro 	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
30782fb4f839SGregory Neil Shapiro 		(void) lockfile(fd, buf, NULL, LOCK_SH);
3079*d39bd2c1SGregory Neil Shapiro 	if (map_has_chged(map, buf, fd))
30802fb4f839SGregory Neil Shapiro 	{
30812fb4f839SGregory Neil Shapiro 		/* Reopen the database to sync the cache */
30822fb4f839SGregory Neil Shapiro 		int omode = bitset(map->map_mflags, MF_WRITABLE) ? O_RDWR
30832fb4f839SGregory Neil Shapiro 								 : O_RDONLY;
30842fb4f839SGregory Neil Shapiro 
30852fb4f839SGregory Neil Shapiro 		if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
30862fb4f839SGregory Neil Shapiro 			(void) lockfile(fd, buf, NULL, LOCK_UN);
30872fb4f839SGregory Neil Shapiro 		map->map_mflags |= MF_CLOSING;
30882fb4f839SGregory Neil Shapiro 		map->map_class->map_close(map);
30892fb4f839SGregory Neil Shapiro 		map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING);
30902fb4f839SGregory Neil Shapiro 		if (map->map_class->map_open(map, omode))
30912fb4f839SGregory Neil Shapiro 		{
30922fb4f839SGregory Neil Shapiro 			map->map_mflags |= MF_OPEN;
30932fb4f839SGregory Neil Shapiro 			if ((omode & O_ACCMODE) == O_RDWR)
30942fb4f839SGregory Neil Shapiro 				map->map_mflags |= MF_WRITABLE;
30952fb4f839SGregory Neil Shapiro 			cdbmap = map->map_db1;
30962fb4f839SGregory Neil Shapiro 			goto lockdb;
30972fb4f839SGregory Neil Shapiro 		}
30982fb4f839SGregory Neil Shapiro 		else
30992fb4f839SGregory Neil Shapiro 		{
31002fb4f839SGregory Neil Shapiro 			if (!bitset(MF_OPTIONAL, map->map_mflags))
31012fb4f839SGregory Neil Shapiro 			{
31022fb4f839SGregory Neil Shapiro 				extern MAPCLASS BogusMapClass;
31032fb4f839SGregory Neil Shapiro 
31042fb4f839SGregory Neil Shapiro 				*statp = EX_TEMPFAIL;
31052fb4f839SGregory Neil Shapiro 				map->map_orgclass = map->map_class;
31062fb4f839SGregory Neil Shapiro 				map->map_class = &BogusMapClass;
31072fb4f839SGregory Neil Shapiro 				map->map_mflags |= MF_OPEN;
31082fb4f839SGregory Neil Shapiro 				syserr("Cannot reopen CDB database %s",
31092fb4f839SGregory Neil Shapiro 					map->map_file);
31102fb4f839SGregory Neil Shapiro 			}
31112fb4f839SGregory Neil Shapiro 			return NULL;
31122fb4f839SGregory Neil Shapiro 		}
31132fb4f839SGregory Neil Shapiro 	}
31145b0945b5SGregory Neil Shapiro 
31155b0945b5SGregory Neil Shapiro 	st = 0;
31165b0945b5SGregory Neil Shapiro 	if (bitset(MF_TRY0NULL, map->map_mflags))
31175b0945b5SGregory Neil Shapiro 	{
31185b0945b5SGregory Neil Shapiro 		st = cdb_find(cdbmap, key, klen);
31195b0945b5SGregory Neil Shapiro 		if (st == 1)
31205b0945b5SGregory Neil Shapiro 			 map->map_mflags &= ~MF_TRY1NULL;
31215b0945b5SGregory Neil Shapiro 	}
31225b0945b5SGregory Neil Shapiro 	if (st != 1 && bitset(MF_TRY1NULL, map->map_mflags))
31235b0945b5SGregory Neil Shapiro 	{
31245b0945b5SGregory Neil Shapiro 		st = cdb_find(cdbmap, key, klen + 1);
31255b0945b5SGregory Neil Shapiro 		if (st == 1)
31265b0945b5SGregory Neil Shapiro 			 map->map_mflags &= ~MF_TRY0NULL;
31275b0945b5SGregory Neil Shapiro 	}
31282fb4f839SGregory Neil Shapiro 	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
31292fb4f839SGregory Neil Shapiro 		(void) lockfile(fd, buf, NULL, LOCK_UN);
31305b0945b5SGregory Neil Shapiro 	if (st != 1)
31315b0945b5SGregory Neil Shapiro 	{
31325b0945b5SGregory Neil Shapiro 		if (st < 0)
31335b0945b5SGregory Neil Shapiro 			syserr("cdb_map_lookup: get (%s)", name);
31345b0945b5SGregory Neil Shapiro 		return NULL;
31355b0945b5SGregory Neil Shapiro 	}
31365b0945b5SGregory Neil Shapiro 	else
31375b0945b5SGregory Neil Shapiro 	{
31385b0945b5SGregory Neil Shapiro 		dlen = cdb_datalen(cdbmap);
31395b0945b5SGregory Neil Shapiro 		data = malloc(dlen + 1);
31405b0945b5SGregory Neil Shapiro 		cdb_read(cdbmap, data, dlen, cdb_datapos(cdbmap));
31415b0945b5SGregory Neil Shapiro 		data[dlen] = '\0';
31425b0945b5SGregory Neil Shapiro 	}
31435b0945b5SGregory Neil Shapiro 	if (bitset(MF_MATCHONLY, map->map_mflags))
31445b0945b5SGregory Neil Shapiro 		return map_rewrite(map, name, strlen(name), NULL);
31455b0945b5SGregory Neil Shapiro 	else
31465b0945b5SGregory Neil Shapiro 		return map_rewrite(map, data, dlen, av);
31475b0945b5SGregory Neil Shapiro }
31485b0945b5SGregory Neil Shapiro 
31495b0945b5SGregory Neil Shapiro /*
31505b0945b5SGregory Neil Shapiro **  CDB_MAP_STORE -- store a datum in the CDB database
31515b0945b5SGregory Neil Shapiro */
31525b0945b5SGregory Neil Shapiro 
31535b0945b5SGregory Neil Shapiro void
cdb_map_store(map,lhs,rhs)31545b0945b5SGregory Neil Shapiro cdb_map_store(map, lhs, rhs)
31555b0945b5SGregory Neil Shapiro 	MAP *map;
31565b0945b5SGregory Neil Shapiro 	char *lhs;
31575b0945b5SGregory Neil Shapiro 	char *rhs;
31585b0945b5SGregory Neil Shapiro {
31595b0945b5SGregory Neil Shapiro 	struct cdb_make *cdbmp;
31605b0945b5SGregory Neil Shapiro 	size_t klen;
31615b0945b5SGregory Neil Shapiro 	size_t vlen;
31625b0945b5SGregory Neil Shapiro 	int status;
31632fb4f839SGregory Neil Shapiro 	char keybuf[MAXNAME + 1];	/* EAI:ok */
31645b0945b5SGregory Neil Shapiro 
31655b0945b5SGregory Neil Shapiro 	cdbmp = map->map_db2;
31665b0945b5SGregory Neil Shapiro 	if (cdbmp == NULL)
31675b0945b5SGregory Neil Shapiro 		return;	/* XXX */
31685b0945b5SGregory Neil Shapiro 
31695b0945b5SGregory Neil Shapiro 	klen = strlen(lhs);
31705b0945b5SGregory Neil Shapiro 	vlen = strlen(rhs);
31715b0945b5SGregory Neil Shapiro 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
31725b0945b5SGregory Neil Shapiro 	{
31735b0945b5SGregory Neil Shapiro 		if (klen > sizeof(keybuf) - 1)
31745b0945b5SGregory Neil Shapiro 			klen = sizeof(keybuf) - 1;
31755b0945b5SGregory Neil Shapiro 		memmove(keybuf, lhs, klen);
31765b0945b5SGregory Neil Shapiro 		keybuf[klen] = '\0';
31772fb4f839SGregory Neil Shapiro 		makelower_buf(keybuf, keybuf, sizeof(keybuf));
31785b0945b5SGregory Neil Shapiro 		lhs = keybuf;
31795b0945b5SGregory Neil Shapiro 	}
31805b0945b5SGregory Neil Shapiro 
31815b0945b5SGregory Neil Shapiro 	if (bitset(MF_INCLNULL, map->map_mflags))
31825b0945b5SGregory Neil Shapiro 	{
31835b0945b5SGregory Neil Shapiro 		klen++;
31845b0945b5SGregory Neil Shapiro 		vlen++;
31855b0945b5SGregory Neil Shapiro 	}
31865b0945b5SGregory Neil Shapiro 
31875b0945b5SGregory Neil Shapiro 	/* flags? */
31885b0945b5SGregory Neil Shapiro 	status = cdb_make_put(cdbmp, lhs, klen, rhs, vlen, 0);
31895b0945b5SGregory Neil Shapiro 	/* and now? */
31905b0945b5SGregory Neil Shapiro }
31915b0945b5SGregory Neil Shapiro 
31925b0945b5SGregory Neil Shapiro void
cdb_map_close(map)31935b0945b5SGregory Neil Shapiro cdb_map_close(map)
31945b0945b5SGregory Neil Shapiro 	MAP * map;
31955b0945b5SGregory Neil Shapiro {
31965b0945b5SGregory Neil Shapiro 	struct cdb *cdbp;
31975b0945b5SGregory Neil Shapiro 	struct cdb_make *cdbmp;
31985b0945b5SGregory Neil Shapiro 	int fd;
31995b0945b5SGregory Neil Shapiro 
32005b0945b5SGregory Neil Shapiro 	fd = -1;
32015b0945b5SGregory Neil Shapiro 	cdbp = map->map_db1;
32025b0945b5SGregory Neil Shapiro 	if (cdbp != NULL)
32035b0945b5SGregory Neil Shapiro 	{
32045b0945b5SGregory Neil Shapiro 		if (tTd(38, 20))
32052fb4f839SGregory Neil Shapiro 			sm_dprintf("cdb_map_close(%p): cdbp\n", (void *)cdbp);
32065b0945b5SGregory Neil Shapiro 		fd = cdb_fileno(cdbp);
32075b0945b5SGregory Neil Shapiro 		cdb_free(cdbp);
32082fb4f839SGregory Neil Shapiro 		SM_FREE(cdbp);
32095b0945b5SGregory Neil Shapiro 	}
32105b0945b5SGregory Neil Shapiro 	cdbmp = map->map_db2;
32115b0945b5SGregory Neil Shapiro 	if (cdbmp != NULL)
32125b0945b5SGregory Neil Shapiro 	{
32135b0945b5SGregory Neil Shapiro 		if (tTd(38, 20))
32142fb4f839SGregory Neil Shapiro 			sm_dprintf("cdb_map_close(%p): cdmbp\n", (void *)cdbmp);
32155b0945b5SGregory Neil Shapiro 		fd = cdb_fileno(cdbmp);
32165b0945b5SGregory Neil Shapiro 
32175b0945b5SGregory Neil Shapiro 		/* write out the distinguished alias */
32185b0945b5SGregory Neil Shapiro 		/* XXX Why isn't this in a common place? */
32195b0945b5SGregory Neil Shapiro 		cdb_map_store(map, "@", "@");
32205b0945b5SGregory Neil Shapiro 
32215b0945b5SGregory Neil Shapiro 		if (cdb_make_finish(cdbmp) != 0)
32222fb4f839SGregory Neil Shapiro 			syserr("cdb: cdb_make_finish(%s) failed",
32232fb4f839SGregory Neil Shapiro 				map->map_file);
32245b0945b5SGregory Neil Shapiro 		if (fd >= 0)
32255b0945b5SGregory Neil Shapiro 		{
32265b0945b5SGregory Neil Shapiro 			if (fsync(fd) == -1)
32275b0945b5SGregory Neil Shapiro 				syserr("cdb: fsync(%s) failed", map->map_file);
32285b0945b5SGregory Neil Shapiro 			if (close(fd) == -1)
32295b0945b5SGregory Neil Shapiro 				syserr("cdb: close(%s) failed", map->map_file);
32302fb4f839SGregory Neil Shapiro 			fd = -1;
32315b0945b5SGregory Neil Shapiro 		}
32322fb4f839SGregory Neil Shapiro 		SM_FREE(cdbmp);
32335b0945b5SGregory Neil Shapiro 	}
32345b0945b5SGregory Neil Shapiro 	if (fd >=0)
32355b0945b5SGregory Neil Shapiro 		close(fd);
32365b0945b5SGregory Neil Shapiro }
32375b0945b5SGregory Neil Shapiro #endif /* CDB */
32385b0945b5SGregory Neil Shapiro 
323940266059SGregory Neil Shapiro /*
3240c2aa98e2SPeter Wemm **  NIS Modules
3241c2aa98e2SPeter Wemm */
3242c2aa98e2SPeter Wemm 
324340266059SGregory Neil Shapiro #if NIS
3244c2aa98e2SPeter Wemm 
3245c2aa98e2SPeter Wemm # ifndef YPERR_BUSY
3246c2aa98e2SPeter Wemm #  define YPERR_BUSY	16
32475b0945b5SGregory Neil Shapiro # endif
3248c2aa98e2SPeter Wemm 
3249c2aa98e2SPeter Wemm /*
3250*d39bd2c1SGregory Neil Shapiro **  NIS_MAP_OPEN -- open NIS map
3251c2aa98e2SPeter Wemm */
3252c2aa98e2SPeter Wemm 
3253c2aa98e2SPeter Wemm bool
nis_map_open(map,mode)3254c2aa98e2SPeter Wemm nis_map_open(map, mode)
3255c2aa98e2SPeter Wemm 	MAP *map;
3256c2aa98e2SPeter Wemm 	int mode;
3257c2aa98e2SPeter Wemm {
3258c2aa98e2SPeter Wemm 	int yperr;
3259c2aa98e2SPeter Wemm 	register char *p;
3260c2aa98e2SPeter Wemm 	auto char *vp;
3261c2aa98e2SPeter Wemm 	auto int vsize;
3262c2aa98e2SPeter Wemm 
3263c2aa98e2SPeter Wemm 	if (tTd(38, 2))
326440266059SGregory Neil Shapiro 		sm_dprintf("nis_map_open(%s, %s, %d)\n",
3265c2aa98e2SPeter Wemm 			map->map_mname, map->map_file, mode);
3266c2aa98e2SPeter Wemm 
3267c2aa98e2SPeter Wemm 	mode &= O_ACCMODE;
3268c2aa98e2SPeter Wemm 	if (mode != O_RDONLY)
3269c2aa98e2SPeter Wemm 	{
3270c2aa98e2SPeter Wemm 		/* issue a pseudo-error message */
327140266059SGregory Neil Shapiro 		errno = SM_EMAPCANTWRITE;
327240266059SGregory Neil Shapiro 		return false;
3273c2aa98e2SPeter Wemm 	}
3274c2aa98e2SPeter Wemm 
3275c2aa98e2SPeter Wemm 	p = strchr(map->map_file, '@');
3276c2aa98e2SPeter Wemm 	if (p != NULL)
3277c2aa98e2SPeter Wemm 	{
3278c2aa98e2SPeter Wemm 		*p++ = '\0';
3279c2aa98e2SPeter Wemm 		if (*p != '\0')
3280c2aa98e2SPeter Wemm 			map->map_domain = p;
3281c2aa98e2SPeter Wemm 	}
3282c2aa98e2SPeter Wemm 
3283c2aa98e2SPeter Wemm 	if (*map->map_file == '\0')
3284c2aa98e2SPeter Wemm 		map->map_file = "mail.aliases";
3285c2aa98e2SPeter Wemm 
3286c2aa98e2SPeter Wemm 	if (map->map_domain == NULL)
3287c2aa98e2SPeter Wemm 	{
3288c2aa98e2SPeter Wemm 		yperr = yp_get_default_domain(&map->map_domain);
3289c2aa98e2SPeter Wemm 		if (yperr != 0)
3290c2aa98e2SPeter Wemm 		{
3291c2aa98e2SPeter Wemm 			if (!bitset(MF_OPTIONAL, map->map_mflags))
3292605302a5SGregory Neil Shapiro 				syserr("451 4.3.5 NIS map %s specified, but NIS not running",
3293c2aa98e2SPeter Wemm 				       map->map_file);
329440266059SGregory Neil Shapiro 			return false;
3295c2aa98e2SPeter Wemm 		}
3296c2aa98e2SPeter Wemm 	}
3297c2aa98e2SPeter Wemm 
3298c2aa98e2SPeter Wemm 	/* check to see if this map actually exists */
329906f25ae9SGregory Neil Shapiro 	vp = NULL;
3300c2aa98e2SPeter Wemm 	yperr = yp_match(map->map_domain, map->map_file, "@", 1,
3301c2aa98e2SPeter Wemm 			&vp, &vsize);
3302c2aa98e2SPeter Wemm 	if (tTd(38, 10))
330340266059SGregory Neil Shapiro 		sm_dprintf("nis_map_open: yp_match(@, %s, %s) => %s\n",
3304c2aa98e2SPeter Wemm 			map->map_domain, map->map_file, yperr_string(yperr));
33052fb4f839SGregory Neil Shapiro 	SM_FREE(vp);
330606f25ae9SGregory Neil Shapiro 
3307c2aa98e2SPeter Wemm 	if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY)
3308c2aa98e2SPeter Wemm 	{
3309c2aa98e2SPeter Wemm 		/*
3310c2aa98e2SPeter Wemm 		**  We ought to be calling aliaswait() here if this is an
3311c2aa98e2SPeter Wemm 		**  alias file, but powerful HP-UX NIS servers apparently
3312c2aa98e2SPeter Wemm 		**  don't insert the @:@ token into the alias map when it
3313c2aa98e2SPeter Wemm 		**  is rebuilt, so aliaswait() just hangs.  I hate HP-UX.
3314c2aa98e2SPeter Wemm 		*/
3315c2aa98e2SPeter Wemm 
3316c2aa98e2SPeter Wemm # if 0
3317c2aa98e2SPeter Wemm 		if (!bitset(MF_ALIAS, map->map_mflags) ||
331840266059SGregory Neil Shapiro 		    aliaswait(map, NULL, true))
33195b0945b5SGregory Neil Shapiro # endif
332040266059SGregory Neil Shapiro 			return true;
3321c2aa98e2SPeter Wemm 	}
3322c2aa98e2SPeter Wemm 
3323c2aa98e2SPeter Wemm 	if (!bitset(MF_OPTIONAL, map->map_mflags))
3324c2aa98e2SPeter Wemm 	{
3325605302a5SGregory Neil Shapiro 		syserr("451 4.3.5 Cannot bind to map %s in domain %s: %s",
3326c2aa98e2SPeter Wemm 			map->map_file, map->map_domain, yperr_string(yperr));
3327c2aa98e2SPeter Wemm 	}
3328c2aa98e2SPeter Wemm 
332940266059SGregory Neil Shapiro 	return false;
3330c2aa98e2SPeter Wemm }
3331c2aa98e2SPeter Wemm 
3332c2aa98e2SPeter Wemm 
3333c2aa98e2SPeter Wemm /*
3334c2aa98e2SPeter Wemm **  NIS_MAP_LOOKUP -- look up a datum in a NIS map
3335c2aa98e2SPeter Wemm */
3336c2aa98e2SPeter Wemm 
3337c2aa98e2SPeter Wemm /* ARGSUSED3 */
3338c2aa98e2SPeter Wemm char *
nis_map_lookup(map,name,av,statp)3339c2aa98e2SPeter Wemm nis_map_lookup(map, name, av, statp)
3340c2aa98e2SPeter Wemm 	MAP *map;
3341c2aa98e2SPeter Wemm 	char *name;
3342c2aa98e2SPeter Wemm 	char **av;
3343c2aa98e2SPeter Wemm 	int *statp;
3344c2aa98e2SPeter Wemm {
3345c2aa98e2SPeter Wemm 	char *vp;
3346c2aa98e2SPeter Wemm 	auto int vsize;
3347c2aa98e2SPeter Wemm 	int buflen;
3348c2aa98e2SPeter Wemm 	int yperr;
33492fb4f839SGregory Neil Shapiro 	char keybuf[MAXNAME + 1];	/* EAI:ok */
335040266059SGregory Neil Shapiro 	char *SM_NONVOLATILE result = NULL;
3351c2aa98e2SPeter Wemm 
3352c2aa98e2SPeter Wemm 	if (tTd(38, 20))
335340266059SGregory Neil Shapiro 		sm_dprintf("nis_map_lookup(%s, %s)\n",
3354c2aa98e2SPeter Wemm 			map->map_mname, name);
3355c2aa98e2SPeter Wemm 
3356c2aa98e2SPeter Wemm 	buflen = strlen(name);
3357d0cef73dSGregory Neil Shapiro 	if (buflen > sizeof(keybuf) - 1)
3358d0cef73dSGregory Neil Shapiro 		buflen = sizeof(keybuf) - 1;
335906f25ae9SGregory Neil Shapiro 	memmove(keybuf, name, buflen);
3360c2aa98e2SPeter Wemm 	keybuf[buflen] = '\0';
3361c2aa98e2SPeter Wemm 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
33622fb4f839SGregory Neil Shapiro 		makelower_buf(keybuf, keybuf, sizeof(keybuf));
3363c2aa98e2SPeter Wemm 	yperr = YPERR_KEY;
336406f25ae9SGregory Neil Shapiro 	vp = NULL;
3365c2aa98e2SPeter Wemm 	if (bitset(MF_TRY0NULL, map->map_mflags))
3366c2aa98e2SPeter Wemm 	{
3367c2aa98e2SPeter Wemm 		yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
3368c2aa98e2SPeter Wemm 			     &vp, &vsize);
3369c2aa98e2SPeter Wemm 		if (yperr == 0)
3370c2aa98e2SPeter Wemm 			map->map_mflags &= ~MF_TRY1NULL;
3371c2aa98e2SPeter Wemm 	}
3372c2aa98e2SPeter Wemm 	if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags))
3373c2aa98e2SPeter Wemm 	{
33745b0945b5SGregory Neil Shapiro 		SM_FREE(vp);
3375c2aa98e2SPeter Wemm 		buflen++;
3376c2aa98e2SPeter Wemm 		yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
3377c2aa98e2SPeter Wemm 			     &vp, &vsize);
3378c2aa98e2SPeter Wemm 		if (yperr == 0)
3379c2aa98e2SPeter Wemm 			map->map_mflags &= ~MF_TRY0NULL;
3380c2aa98e2SPeter Wemm 	}
3381c2aa98e2SPeter Wemm 	if (yperr != 0)
3382c2aa98e2SPeter Wemm 	{
3383c2aa98e2SPeter Wemm 		if (yperr != YPERR_KEY && yperr != YPERR_BUSY)
3384c2aa98e2SPeter Wemm 			map->map_mflags &= ~(MF_VALID|MF_OPEN);
33852fb4f839SGregory Neil Shapiro 		SM_FREE(vp);
3386c2aa98e2SPeter Wemm 		return NULL;
3387c2aa98e2SPeter Wemm 	}
338840266059SGregory Neil Shapiro 	SM_TRY
3389c2aa98e2SPeter Wemm 		if (bitset(MF_MATCHONLY, map->map_mflags))
339040266059SGregory Neil Shapiro 			result = map_rewrite(map, name, strlen(name), NULL);
3391c2aa98e2SPeter Wemm 		else
339240266059SGregory Neil Shapiro 			result = map_rewrite(map, vp, vsize, av);
339340266059SGregory Neil Shapiro 	SM_FINALLY
33942fb4f839SGregory Neil Shapiro 		SM_FREE(vp);
339540266059SGregory Neil Shapiro 	SM_END_TRY
339640266059SGregory Neil Shapiro 	return result;
3397c2aa98e2SPeter Wemm }
3398c2aa98e2SPeter Wemm 
3399c2aa98e2SPeter Wemm 
3400c2aa98e2SPeter Wemm /*
3401c2aa98e2SPeter Wemm **  NIS_GETCANONNAME -- look up canonical name in NIS
3402c2aa98e2SPeter Wemm */
3403c2aa98e2SPeter Wemm 
340406f25ae9SGregory Neil Shapiro static bool
nis_getcanonname(name,hbsize,statp)3405c2aa98e2SPeter Wemm nis_getcanonname(name, hbsize, statp)
3406c2aa98e2SPeter Wemm 	char *name;
3407c2aa98e2SPeter Wemm 	int hbsize;
3408c2aa98e2SPeter Wemm 	int *statp;
3409c2aa98e2SPeter Wemm {
3410c2aa98e2SPeter Wemm 	char *vp;
3411c2aa98e2SPeter Wemm 	auto int vsize;
3412c2aa98e2SPeter Wemm 	int keylen;
3413c2aa98e2SPeter Wemm 	int yperr;
341440266059SGregory Neil Shapiro 	static bool try0null = true;
341540266059SGregory Neil Shapiro 	static bool try1null = true;
3416c2aa98e2SPeter Wemm 	static char *yp_domain = NULL;
3417c2aa98e2SPeter Wemm 	char host_record[MAXLINE];
34182fb4f839SGregory Neil Shapiro 	char cbuf[MAXNAME];	/* EAI:hostname */
34192fb4f839SGregory Neil Shapiro 	char nbuf[MAXNAME + 1];	/* EAI:hostname */
3420c2aa98e2SPeter Wemm 
3421c2aa98e2SPeter Wemm 	if (tTd(38, 20))
342240266059SGregory Neil Shapiro 		sm_dprintf("nis_getcanonname(%s)\n", name);
3423c2aa98e2SPeter Wemm 
3424d0cef73dSGregory Neil Shapiro 	if (sm_strlcpy(nbuf, name, sizeof(nbuf)) >= sizeof(nbuf))
3425c2aa98e2SPeter Wemm 	{
3426c2aa98e2SPeter Wemm 		*statp = EX_UNAVAILABLE;
342740266059SGregory Neil Shapiro 		return false;
3428c2aa98e2SPeter Wemm 	}
3429602a2b1bSGregory Neil Shapiro 	(void) shorten_hostname(nbuf);
3430c2aa98e2SPeter Wemm 	keylen = strlen(nbuf);
3431c2aa98e2SPeter Wemm 
3432c2aa98e2SPeter Wemm 	if (yp_domain == NULL)
343306f25ae9SGregory Neil Shapiro 		(void) yp_get_default_domain(&yp_domain);
34342fb4f839SGregory Neil Shapiro 	makelower_buf(nbuf, nbuf, sizeof(nbuf));
3435c2aa98e2SPeter Wemm 	yperr = YPERR_KEY;
343606f25ae9SGregory Neil Shapiro 	vp = NULL;
3437c2aa98e2SPeter Wemm 	if (try0null)
3438c2aa98e2SPeter Wemm 	{
3439c2aa98e2SPeter Wemm 		yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen,
3440c2aa98e2SPeter Wemm 			     &vp, &vsize);
3441c2aa98e2SPeter Wemm 		if (yperr == 0)
344240266059SGregory Neil Shapiro 			try1null = false;
3443c2aa98e2SPeter Wemm 	}
3444c2aa98e2SPeter Wemm 	if (yperr == YPERR_KEY && try1null)
3445c2aa98e2SPeter Wemm 	{
34465b0945b5SGregory Neil Shapiro 		SM_FREE(vp);
3447c2aa98e2SPeter Wemm 		keylen++;
3448c2aa98e2SPeter Wemm 		yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen,
3449c2aa98e2SPeter Wemm 			     &vp, &vsize);
3450c2aa98e2SPeter Wemm 		if (yperr == 0)
345140266059SGregory Neil Shapiro 			try0null = false;
3452c2aa98e2SPeter Wemm 	}
3453c2aa98e2SPeter Wemm 	if (yperr != 0)
3454c2aa98e2SPeter Wemm 	{
3455c2aa98e2SPeter Wemm 		if (yperr == YPERR_KEY)
3456c2aa98e2SPeter Wemm 			*statp = EX_NOHOST;
3457c2aa98e2SPeter Wemm 		else if (yperr == YPERR_BUSY)
3458c2aa98e2SPeter Wemm 			*statp = EX_TEMPFAIL;
3459c2aa98e2SPeter Wemm 		else
3460c2aa98e2SPeter Wemm 			*statp = EX_UNAVAILABLE;
34612fb4f839SGregory Neil Shapiro 		SM_FREE(vp);
346240266059SGregory Neil Shapiro 		return false;
3463c2aa98e2SPeter Wemm 	}
3464d0cef73dSGregory Neil Shapiro 	(void) sm_strlcpy(host_record, vp, sizeof(host_record));
34658774250cSGregory Neil Shapiro 	sm_free(vp);
3466c2aa98e2SPeter Wemm 	if (tTd(38, 44))
346740266059SGregory Neil Shapiro 		sm_dprintf("got record `%s'\n", host_record);
346840266059SGregory Neil Shapiro 	vp = strpbrk(host_record, "#\n");
346940266059SGregory Neil Shapiro 	if (vp != NULL)
347040266059SGregory Neil Shapiro 		*vp = '\0';
3471d0cef73dSGregory Neil Shapiro 	if (!extract_canonname(nbuf, NULL, host_record, cbuf, sizeof(cbuf)))
3472c2aa98e2SPeter Wemm 	{
3473c2aa98e2SPeter Wemm 		/* this should not happen, but.... */
3474c2aa98e2SPeter Wemm 		*statp = EX_NOHOST;
347540266059SGregory Neil Shapiro 		return false;
3476c2aa98e2SPeter Wemm 	}
347740266059SGregory Neil Shapiro 	if (sm_strlcpy(name, cbuf, hbsize) >= hbsize)
3478c2aa98e2SPeter Wemm 	{
3479c2aa98e2SPeter Wemm 		*statp = EX_UNAVAILABLE;
348040266059SGregory Neil Shapiro 		return false;
3481c2aa98e2SPeter Wemm 	}
3482c2aa98e2SPeter Wemm 	*statp = EX_OK;
348340266059SGregory Neil Shapiro 	return true;
3484c2aa98e2SPeter Wemm }
3485c2aa98e2SPeter Wemm 
348606f25ae9SGregory Neil Shapiro #endif /* NIS */
348740266059SGregory Neil Shapiro /*
3488c2aa98e2SPeter Wemm **  NISPLUS Modules
3489c2aa98e2SPeter Wemm **
3490c2aa98e2SPeter Wemm **	This code donated by Sun Microsystems.
3491c2aa98e2SPeter Wemm */
3492c2aa98e2SPeter Wemm 
349340266059SGregory Neil Shapiro #if NISPLUS
3494c2aa98e2SPeter Wemm 
3495c2aa98e2SPeter Wemm # undef NIS		/* symbol conflict in nis.h */
3496c2aa98e2SPeter Wemm # undef T_UNSPEC	/* symbol conflict in nis.h -> ... -> sys/tiuser.h */
3497c2aa98e2SPeter Wemm # include <rpcsvc/nis.h>
3498c2aa98e2SPeter Wemm # include <rpcsvc/nislib.h>
3499552d4955SGregory Neil Shapiro # ifndef NIS_TABLE_OBJ
3500552d4955SGregory Neil Shapiro #  define NIS_TABLE_OBJ TABLE_OBJ
35015b0945b5SGregory Neil Shapiro # endif
3502c2aa98e2SPeter Wemm 
3503c2aa98e2SPeter Wemm # define EN_col(col)	zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val
3504c2aa98e2SPeter Wemm # define COL_NAME(res,i)	((res->objects.objects_val)->TA_data.ta_cols.ta_cols_val)[i].tc_name
3505c2aa98e2SPeter Wemm # define COL_MAX(res)	((res->objects.objects_val)->TA_data.ta_cols.ta_cols_len)
3506c2aa98e2SPeter Wemm # define PARTIAL_NAME(x)	((x)[strlen(x) - 1] != '.')
3507c2aa98e2SPeter Wemm 
3508c2aa98e2SPeter Wemm /*
3509c2aa98e2SPeter Wemm **  NISPLUS_MAP_OPEN -- open nisplus table
3510c2aa98e2SPeter Wemm */
3511c2aa98e2SPeter Wemm 
3512c2aa98e2SPeter Wemm bool
nisplus_map_open(map,mode)3513c2aa98e2SPeter Wemm nisplus_map_open(map, mode)
3514c2aa98e2SPeter Wemm 	MAP *map;
3515c2aa98e2SPeter Wemm 	int mode;
3516c2aa98e2SPeter Wemm {
3517c2aa98e2SPeter Wemm 	nis_result *res = NULL;
3518c2aa98e2SPeter Wemm 	int retry_cnt, max_col, i;
3519c2aa98e2SPeter Wemm 	char qbuf[MAXLINE + NIS_MAXNAMELEN];
3520c2aa98e2SPeter Wemm 
3521c2aa98e2SPeter Wemm 	if (tTd(38, 2))
352240266059SGregory Neil Shapiro 		sm_dprintf("nisplus_map_open(%s, %s, %d)\n",
3523c2aa98e2SPeter Wemm 			map->map_mname, map->map_file, mode);
3524c2aa98e2SPeter Wemm 
3525c2aa98e2SPeter Wemm 	mode &= O_ACCMODE;
3526c2aa98e2SPeter Wemm 	if (mode != O_RDONLY)
3527c2aa98e2SPeter Wemm 	{
3528c2aa98e2SPeter Wemm 		errno = EPERM;
352940266059SGregory Neil Shapiro 		return false;
3530c2aa98e2SPeter Wemm 	}
3531c2aa98e2SPeter Wemm 
3532c2aa98e2SPeter Wemm 	if (*map->map_file == '\0')
3533c2aa98e2SPeter Wemm 		map->map_file = "mail_aliases.org_dir";
3534c2aa98e2SPeter Wemm 
3535c2aa98e2SPeter Wemm 	if (PARTIAL_NAME(map->map_file) && map->map_domain == NULL)
3536c2aa98e2SPeter Wemm 	{
3537c2aa98e2SPeter Wemm 		/* set default NISPLUS Domain to $m */
3538c2aa98e2SPeter Wemm 		map->map_domain = newstr(nisplus_default_domain());
3539c2aa98e2SPeter Wemm 		if (tTd(38, 2))
354040266059SGregory Neil Shapiro 			sm_dprintf("nisplus_map_open(%s): using domain %s\n",
3541c2aa98e2SPeter Wemm 				map->map_file, map->map_domain);
3542c2aa98e2SPeter Wemm 	}
3543c2aa98e2SPeter Wemm 	if (!PARTIAL_NAME(map->map_file))
3544c2aa98e2SPeter Wemm 	{
3545c2aa98e2SPeter Wemm 		map->map_domain = newstr("");
3546d0cef73dSGregory Neil Shapiro 		(void) sm_strlcpy(qbuf, map->map_file, sizeof(qbuf));
3547c2aa98e2SPeter Wemm 	}
3548c2aa98e2SPeter Wemm 	else
3549c2aa98e2SPeter Wemm 	{
3550c2aa98e2SPeter Wemm 		/* check to see if this map actually exists */
3551d0cef73dSGregory Neil Shapiro 		(void) sm_strlcpyn(qbuf, sizeof(qbuf), 3,
355240266059SGregory Neil Shapiro 				   map->map_file, ".", map->map_domain);
3553c2aa98e2SPeter Wemm 	}
3554c2aa98e2SPeter Wemm 
3555c2aa98e2SPeter Wemm 	retry_cnt = 0;
3556c2aa98e2SPeter Wemm 	while (res == NULL || res->status != NIS_SUCCESS)
3557c2aa98e2SPeter Wemm 	{
3558c2aa98e2SPeter Wemm 		res = nis_lookup(qbuf, FOLLOW_LINKS);
3559c2aa98e2SPeter Wemm 		switch (res->status)
3560c2aa98e2SPeter Wemm 		{
3561c2aa98e2SPeter Wemm 		  case NIS_SUCCESS:
3562c2aa98e2SPeter Wemm 			break;
3563c2aa98e2SPeter Wemm 
3564c2aa98e2SPeter Wemm 		  case NIS_TRYAGAIN:
3565c2aa98e2SPeter Wemm 		  case NIS_RPCERROR:
3566c2aa98e2SPeter Wemm 		  case NIS_NAMEUNREACHABLE:
3567c2aa98e2SPeter Wemm 			if (retry_cnt++ > 4)
3568c2aa98e2SPeter Wemm 			{
3569c2aa98e2SPeter Wemm 				errno = EAGAIN;
357040266059SGregory Neil Shapiro 				return false;
3571c2aa98e2SPeter Wemm 			}
3572c2aa98e2SPeter Wemm 			/* try not to overwhelm hosed server */
3573c2aa98e2SPeter Wemm 			sleep(2);
3574c2aa98e2SPeter Wemm 			break;
3575c2aa98e2SPeter Wemm 
3576c2aa98e2SPeter Wemm 		  default:		/* all other nisplus errors */
3577c2aa98e2SPeter Wemm # if 0
3578c2aa98e2SPeter Wemm 			if (!bitset(MF_OPTIONAL, map->map_mflags))
3579605302a5SGregory Neil Shapiro 				syserr("451 4.3.5 Cannot find table %s.%s: %s",
3580c2aa98e2SPeter Wemm 					map->map_file, map->map_domain,
3581c2aa98e2SPeter Wemm 					nis_sperrno(res->status));
358206f25ae9SGregory Neil Shapiro # endif /* 0 */
3583c2aa98e2SPeter Wemm 			errno = EAGAIN;
358440266059SGregory Neil Shapiro 			return false;
3585c2aa98e2SPeter Wemm 		}
3586c2aa98e2SPeter Wemm 	}
3587c2aa98e2SPeter Wemm 
3588c2aa98e2SPeter Wemm 	if (NIS_RES_NUMOBJ(res) != 1 ||
3589552d4955SGregory Neil Shapiro 	    (NIS_RES_OBJECT(res)->zo_data.zo_type != NIS_TABLE_OBJ))
3590c2aa98e2SPeter Wemm 	{
3591c2aa98e2SPeter Wemm 		if (tTd(38, 10))
359240266059SGregory Neil Shapiro 			sm_dprintf("nisplus_map_open: %s is not a table\n", qbuf);
3593c2aa98e2SPeter Wemm # if 0
3594c2aa98e2SPeter Wemm 		if (!bitset(MF_OPTIONAL, map->map_mflags))
3595605302a5SGregory Neil Shapiro 			syserr("451 4.3.5 %s.%s: %s is not a table",
3596c2aa98e2SPeter Wemm 				map->map_file, map->map_domain,
3597c2aa98e2SPeter Wemm 				nis_sperrno(res->status));
359806f25ae9SGregory Neil Shapiro # endif /* 0 */
3599c2aa98e2SPeter Wemm 		errno = EBADF;
360040266059SGregory Neil Shapiro 		return false;
3601c2aa98e2SPeter Wemm 	}
3602c2aa98e2SPeter Wemm 	/* default key column is column 0 */
3603c2aa98e2SPeter Wemm 	if (map->map_keycolnm == NULL)
3604c2aa98e2SPeter Wemm 		map->map_keycolnm = newstr(COL_NAME(res,0));
3605c2aa98e2SPeter Wemm 
3606c2aa98e2SPeter Wemm 	max_col = COL_MAX(res);
3607c2aa98e2SPeter Wemm 
3608c2aa98e2SPeter Wemm 	/* verify the key column exist */
3609c2aa98e2SPeter Wemm 	for (i = 0; i < max_col; i++)
3610c2aa98e2SPeter Wemm 	{
361106f25ae9SGregory Neil Shapiro 		if (strcmp(map->map_keycolnm, COL_NAME(res,i)) == 0)
3612c2aa98e2SPeter Wemm 			break;
3613c2aa98e2SPeter Wemm 	}
3614c2aa98e2SPeter Wemm 	if (i == max_col)
3615c2aa98e2SPeter Wemm 	{
3616c2aa98e2SPeter Wemm 		if (tTd(38, 2))
361740266059SGregory Neil Shapiro 			sm_dprintf("nisplus_map_open(%s): can not find key column %s\n",
3618c2aa98e2SPeter Wemm 				map->map_file, map->map_keycolnm);
3619c2aa98e2SPeter Wemm 		errno = ENOENT;
362040266059SGregory Neil Shapiro 		return false;
3621c2aa98e2SPeter Wemm 	}
3622c2aa98e2SPeter Wemm 
3623c2aa98e2SPeter Wemm 	/* default value column is the last column */
3624c2aa98e2SPeter Wemm 	if (map->map_valcolnm == NULL)
3625c2aa98e2SPeter Wemm 	{
3626c2aa98e2SPeter Wemm 		map->map_valcolno = max_col - 1;
362740266059SGregory Neil Shapiro 		return true;
3628c2aa98e2SPeter Wemm 	}
3629c2aa98e2SPeter Wemm 
3630c2aa98e2SPeter Wemm 	for (i = 0; i< max_col; i++)
3631c2aa98e2SPeter Wemm 	{
3632c2aa98e2SPeter Wemm 		if (strcmp(map->map_valcolnm, COL_NAME(res,i)) == 0)
3633c2aa98e2SPeter Wemm 		{
3634c2aa98e2SPeter Wemm 			map->map_valcolno = i;
363540266059SGregory Neil Shapiro 			return true;
3636c2aa98e2SPeter Wemm 		}
3637c2aa98e2SPeter Wemm 	}
3638c2aa98e2SPeter Wemm 
3639c2aa98e2SPeter Wemm 	if (tTd(38, 2))
364040266059SGregory Neil Shapiro 		sm_dprintf("nisplus_map_open(%s): can not find column %s\n",
3641c2aa98e2SPeter Wemm 			map->map_file, map->map_keycolnm);
3642c2aa98e2SPeter Wemm 	errno = ENOENT;
364340266059SGregory Neil Shapiro 	return false;
3644c2aa98e2SPeter Wemm }
3645c2aa98e2SPeter Wemm 
3646c2aa98e2SPeter Wemm 
3647c2aa98e2SPeter Wemm /*
3648c2aa98e2SPeter Wemm **  NISPLUS_MAP_LOOKUP -- look up a datum in a NISPLUS table
3649c2aa98e2SPeter Wemm */
3650c2aa98e2SPeter Wemm 
3651c2aa98e2SPeter Wemm char *
nisplus_map_lookup(map,name,av,statp)3652c2aa98e2SPeter Wemm nisplus_map_lookup(map, name, av, statp)
3653c2aa98e2SPeter Wemm 	MAP *map;
3654c2aa98e2SPeter Wemm 	char *name;
3655c2aa98e2SPeter Wemm 	char **av;
3656c2aa98e2SPeter Wemm 	int *statp;
3657c2aa98e2SPeter Wemm {
3658c2aa98e2SPeter Wemm 	char *p;
3659c2aa98e2SPeter Wemm 	auto int vsize;
3660c2aa98e2SPeter Wemm 	char *skp;
3661c2aa98e2SPeter Wemm 	int skleft;
36622fb4f839SGregory Neil Shapiro 	char search_key[MAXNAME + 4];	/* EAI:ok */
3663c2aa98e2SPeter Wemm 	char qbuf[MAXLINE + NIS_MAXNAMELEN];
3664c2aa98e2SPeter Wemm 	nis_result *result;
3665c2aa98e2SPeter Wemm 
3666c2aa98e2SPeter Wemm 	if (tTd(38, 20))
366740266059SGregory Neil Shapiro 		sm_dprintf("nisplus_map_lookup(%s, %s)\n",
3668c2aa98e2SPeter Wemm 			map->map_mname, name);
3669c2aa98e2SPeter Wemm 
3670c2aa98e2SPeter Wemm 	if (!bitset(MF_OPEN, map->map_mflags))
3671c2aa98e2SPeter Wemm 	{
3672c2aa98e2SPeter Wemm 		if (nisplus_map_open(map, O_RDONLY))
3673065a643dSPeter Wemm 		{
3674c2aa98e2SPeter Wemm 			map->map_mflags |= MF_OPEN;
367540266059SGregory Neil Shapiro 			map->map_pid = CurrentPid;
3676065a643dSPeter Wemm 		}
3677c2aa98e2SPeter Wemm 		else
3678c2aa98e2SPeter Wemm 		{
3679c2aa98e2SPeter Wemm 			*statp = EX_UNAVAILABLE;
3680c2aa98e2SPeter Wemm 			return NULL;
3681c2aa98e2SPeter Wemm 		}
3682c2aa98e2SPeter Wemm 	}
3683c2aa98e2SPeter Wemm 
3684c2aa98e2SPeter Wemm 	/*
3685c2aa98e2SPeter Wemm 	**  Copy the name to the key buffer, escaping double quote characters
3686c2aa98e2SPeter Wemm 	**  by doubling them and quoting "]" and "," to avoid having the
3687c2aa98e2SPeter Wemm 	**  NIS+ parser choke on them.
3688c2aa98e2SPeter Wemm 	*/
3689c2aa98e2SPeter Wemm 
3690d0cef73dSGregory Neil Shapiro 	skleft = sizeof(search_key) - 4;
3691c2aa98e2SPeter Wemm 	skp = search_key;
3692c2aa98e2SPeter Wemm 	for (p = name; *p != '\0' && skleft > 0; p++)
3693c2aa98e2SPeter Wemm 	{
3694c2aa98e2SPeter Wemm 		switch (*p)
3695c2aa98e2SPeter Wemm 		{
3696c2aa98e2SPeter Wemm 		  case ']':
3697c2aa98e2SPeter Wemm 		  case ',':
3698c2aa98e2SPeter Wemm 			/* quote the character */
3699c2aa98e2SPeter Wemm 			*skp++ = '"';
3700c2aa98e2SPeter Wemm 			*skp++ = *p;
3701c2aa98e2SPeter Wemm 			*skp++ = '"';
3702c2aa98e2SPeter Wemm 			skleft -= 3;
3703c2aa98e2SPeter Wemm 			break;
3704c2aa98e2SPeter Wemm 
3705c2aa98e2SPeter Wemm 		  case '"':
3706c2aa98e2SPeter Wemm 			/* double the quote */
3707c2aa98e2SPeter Wemm 			*skp++ = '"';
3708c2aa98e2SPeter Wemm 			skleft--;
370906f25ae9SGregory Neil Shapiro 			/* FALLTHROUGH */
3710c2aa98e2SPeter Wemm 
3711c2aa98e2SPeter Wemm 		  default:
3712c2aa98e2SPeter Wemm 			*skp++ = *p;
3713c2aa98e2SPeter Wemm 			skleft--;
3714c2aa98e2SPeter Wemm 			break;
3715c2aa98e2SPeter Wemm 		}
3716c2aa98e2SPeter Wemm 	}
3717c2aa98e2SPeter Wemm 	*skp = '\0';
3718c2aa98e2SPeter Wemm 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
37192fb4f839SGregory Neil Shapiro 		makelower_buf(search_key, search_key, sizeof(search_key));
3720c2aa98e2SPeter Wemm 
3721c2aa98e2SPeter Wemm 	/* construct the query */
3722c2aa98e2SPeter Wemm 	if (PARTIAL_NAME(map->map_file))
3723d0cef73dSGregory Neil Shapiro 		(void) sm_snprintf(qbuf, sizeof(qbuf), "[%s=%s],%s.%s",
3724c2aa98e2SPeter Wemm 			map->map_keycolnm, search_key, map->map_file,
3725c2aa98e2SPeter Wemm 			map->map_domain);
3726c2aa98e2SPeter Wemm 	else
3727d0cef73dSGregory Neil Shapiro 		(void) sm_snprintf(qbuf, sizeof(qbuf), "[%s=%s],%s",
3728c2aa98e2SPeter Wemm 			map->map_keycolnm, search_key, map->map_file);
3729c2aa98e2SPeter Wemm 
3730c2aa98e2SPeter Wemm 	if (tTd(38, 20))
373140266059SGregory Neil Shapiro 		sm_dprintf("qbuf=%s\n", qbuf);
3732c2aa98e2SPeter Wemm 	result = nis_list(qbuf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL);
3733c2aa98e2SPeter Wemm 	if (result->status == NIS_SUCCESS)
3734c2aa98e2SPeter Wemm 	{
3735c2aa98e2SPeter Wemm 		int count;
3736c2aa98e2SPeter Wemm 		char *str;
3737c2aa98e2SPeter Wemm 
3738c2aa98e2SPeter Wemm 		if ((count = NIS_RES_NUMOBJ(result)) != 1)
3739c2aa98e2SPeter Wemm 		{
3740c2aa98e2SPeter Wemm 			if (LogLevel > 10)
3741c2aa98e2SPeter Wemm 				sm_syslog(LOG_WARNING, CurEnv->e_id,
3742c2aa98e2SPeter Wemm 					  "%s: lookup error, expected 1 entry, got %d",
3743c2aa98e2SPeter Wemm 					  map->map_file, count);
3744c2aa98e2SPeter Wemm 
3745c2aa98e2SPeter Wemm 			/* ignore second entry */
3746c2aa98e2SPeter Wemm 			if (tTd(38, 20))
374740266059SGregory Neil Shapiro 				sm_dprintf("nisplus_map_lookup(%s), got %d entries, additional entries ignored\n",
3748c2aa98e2SPeter Wemm 					name, count);
3749c2aa98e2SPeter Wemm 		}
3750c2aa98e2SPeter Wemm 
3751c2aa98e2SPeter Wemm 		p = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno));
3752c2aa98e2SPeter Wemm 		/* set the length of the result */
3753c2aa98e2SPeter Wemm 		if (p == NULL)
3754c2aa98e2SPeter Wemm 			p = "";
3755c2aa98e2SPeter Wemm 		vsize = strlen(p);
3756c2aa98e2SPeter Wemm 		if (tTd(38, 20))
375740266059SGregory Neil Shapiro 			sm_dprintf("nisplus_map_lookup(%s), found %s\n",
3758c2aa98e2SPeter Wemm 				name, p);
3759c2aa98e2SPeter Wemm 		if (bitset(MF_MATCHONLY, map->map_mflags))
3760c2aa98e2SPeter Wemm 			str = map_rewrite(map, name, strlen(name), NULL);
3761c2aa98e2SPeter Wemm 		else
3762c2aa98e2SPeter Wemm 			str = map_rewrite(map, p, vsize, av);
3763c2aa98e2SPeter Wemm 		nis_freeresult(result);
3764c2aa98e2SPeter Wemm 		*statp = EX_OK;
3765c2aa98e2SPeter Wemm 		return str;
3766c2aa98e2SPeter Wemm 	}
3767c2aa98e2SPeter Wemm 	else
3768c2aa98e2SPeter Wemm 	{
3769c2aa98e2SPeter Wemm 		if (result->status == NIS_NOTFOUND)
3770c2aa98e2SPeter Wemm 			*statp = EX_NOTFOUND;
3771c2aa98e2SPeter Wemm 		else if (result->status == NIS_TRYAGAIN)
3772c2aa98e2SPeter Wemm 			*statp = EX_TEMPFAIL;
3773c2aa98e2SPeter Wemm 		else
3774c2aa98e2SPeter Wemm 		{
3775c2aa98e2SPeter Wemm 			*statp = EX_UNAVAILABLE;
3776c2aa98e2SPeter Wemm 			map->map_mflags &= ~(MF_VALID|MF_OPEN);
3777c2aa98e2SPeter Wemm 		}
3778c2aa98e2SPeter Wemm 	}
3779c2aa98e2SPeter Wemm 	if (tTd(38, 20))
378040266059SGregory Neil Shapiro 		sm_dprintf("nisplus_map_lookup(%s), failed\n", name);
3781c2aa98e2SPeter Wemm 	nis_freeresult(result);
3782c2aa98e2SPeter Wemm 	return NULL;
3783c2aa98e2SPeter Wemm }
3784c2aa98e2SPeter Wemm 
3785c2aa98e2SPeter Wemm 
3786c2aa98e2SPeter Wemm 
3787c2aa98e2SPeter Wemm /*
3788c2aa98e2SPeter Wemm **  NISPLUS_GETCANONNAME -- look up canonical name in NIS+
3789c2aa98e2SPeter Wemm */
3790c2aa98e2SPeter Wemm 
379106f25ae9SGregory Neil Shapiro static bool
nisplus_getcanonname(name,hbsize,statp)3792c2aa98e2SPeter Wemm nisplus_getcanonname(name, hbsize, statp)
3793c2aa98e2SPeter Wemm 	char *name;
3794c2aa98e2SPeter Wemm 	int hbsize;
3795c2aa98e2SPeter Wemm 	int *statp;
3796c2aa98e2SPeter Wemm {
3797c2aa98e2SPeter Wemm 	char *vp;
3798c2aa98e2SPeter Wemm 	auto int vsize;
3799c2aa98e2SPeter Wemm 	nis_result *result;
3800c2aa98e2SPeter Wemm 	char *p;
38012fb4f839SGregory Neil Shapiro 	char nbuf[MAXNAME + 1];	/* EAI:hostname */
38022fb4f839SGregory Neil Shapiro 	char qbuf[MAXLINE + NIS_MAXNAMELEN];	/* EAI:hostname */
3803c2aa98e2SPeter Wemm 
3804d0cef73dSGregory Neil Shapiro 	if (sm_strlcpy(nbuf, name, sizeof(nbuf)) >= sizeof(nbuf))
3805c2aa98e2SPeter Wemm 	{
3806c2aa98e2SPeter Wemm 		*statp = EX_UNAVAILABLE;
380740266059SGregory Neil Shapiro 		return false;
3808c2aa98e2SPeter Wemm 	}
3809602a2b1bSGregory Neil Shapiro 	(void) shorten_hostname(nbuf);
3810c2aa98e2SPeter Wemm 
3811c2aa98e2SPeter Wemm 	p = strchr(nbuf, '.');
3812c2aa98e2SPeter Wemm 	if (p == NULL)
3813c2aa98e2SPeter Wemm 	{
3814c2aa98e2SPeter Wemm 		/* single token */
3815d0cef73dSGregory Neil Shapiro 		(void) sm_snprintf(qbuf, sizeof(qbuf),
381640266059SGregory Neil Shapiro 			"[name=%s],hosts.org_dir", nbuf);
3817c2aa98e2SPeter Wemm 	}
3818c2aa98e2SPeter Wemm 	else if (p[1] != '\0')
3819c2aa98e2SPeter Wemm 	{
3820c2aa98e2SPeter Wemm 		/* multi token -- take only first token in nbuf */
3821c2aa98e2SPeter Wemm 		*p = '\0';
3822d0cef73dSGregory Neil Shapiro 		(void) sm_snprintf(qbuf, sizeof(qbuf),
382340266059SGregory Neil Shapiro 				   "[name=%s],hosts.org_dir.%s", nbuf, &p[1]);
3824c2aa98e2SPeter Wemm 	}
3825c2aa98e2SPeter Wemm 	else
3826c2aa98e2SPeter Wemm 	{
3827c2aa98e2SPeter Wemm 		*statp = EX_NOHOST;
382840266059SGregory Neil Shapiro 		return false;
3829c2aa98e2SPeter Wemm 	}
3830c2aa98e2SPeter Wemm 
3831c2aa98e2SPeter Wemm 	if (tTd(38, 20))
3832605302a5SGregory Neil Shapiro 		sm_dprintf("\nnisplus_getcanonname(%s), qbuf=%s\n",
3833c2aa98e2SPeter Wemm 			   name, qbuf);
3834c2aa98e2SPeter Wemm 
3835c2aa98e2SPeter Wemm 	result = nis_list(qbuf, EXPAND_NAME|FOLLOW_LINKS|FOLLOW_PATH,
3836c2aa98e2SPeter Wemm 			  NULL, NULL);
3837c2aa98e2SPeter Wemm 
3838c2aa98e2SPeter Wemm 	if (result->status == NIS_SUCCESS)
3839c2aa98e2SPeter Wemm 	{
3840c2aa98e2SPeter Wemm 		int count;
3841c2aa98e2SPeter Wemm 		char *domain;
3842c2aa98e2SPeter Wemm 
3843c2aa98e2SPeter Wemm 		if ((count = NIS_RES_NUMOBJ(result)) != 1)
3844c2aa98e2SPeter Wemm 		{
3845c2aa98e2SPeter Wemm 			if (LogLevel > 10)
3846c2aa98e2SPeter Wemm 				sm_syslog(LOG_WARNING, CurEnv->e_id,
3847c2aa98e2SPeter Wemm 					  "nisplus_getcanonname: lookup error, expected 1 entry, got %d",
3848c2aa98e2SPeter Wemm 					  count);
3849c2aa98e2SPeter Wemm 
3850c2aa98e2SPeter Wemm 			/* ignore second entry */
3851c2aa98e2SPeter Wemm 			if (tTd(38, 20))
3852605302a5SGregory Neil Shapiro 				sm_dprintf("nisplus_getcanonname(%s), got %d entries, all but first ignored\n",
3853c2aa98e2SPeter Wemm 					   name, count);
3854c2aa98e2SPeter Wemm 		}
3855c2aa98e2SPeter Wemm 
3856c2aa98e2SPeter Wemm 		if (tTd(38, 20))
3857605302a5SGregory Neil Shapiro 			sm_dprintf("nisplus_getcanonname(%s), found in directory \"%s\"\n",
3858c2aa98e2SPeter Wemm 				   name, (NIS_RES_OBJECT(result))->zo_domain);
3859c2aa98e2SPeter Wemm 
3860c2aa98e2SPeter Wemm 
3861c2aa98e2SPeter Wemm 		vp = ((NIS_RES_OBJECT(result))->EN_col(0));
3862c2aa98e2SPeter Wemm 		vsize = strlen(vp);
3863c2aa98e2SPeter Wemm 		if (tTd(38, 20))
386440266059SGregory Neil Shapiro 			sm_dprintf("nisplus_getcanonname(%s), found %s\n",
3865c2aa98e2SPeter Wemm 				   name, vp);
3866c2aa98e2SPeter Wemm 		if (strchr(vp, '.') != NULL)
3867c2aa98e2SPeter Wemm 		{
3868c2aa98e2SPeter Wemm 			domain = "";
3869c2aa98e2SPeter Wemm 		}
3870c2aa98e2SPeter Wemm 		else
3871c2aa98e2SPeter Wemm 		{
3872c2aa98e2SPeter Wemm 			domain = macvalue('m', CurEnv);
3873c2aa98e2SPeter Wemm 			if (domain == NULL)
3874c2aa98e2SPeter Wemm 				domain = "";
3875c2aa98e2SPeter Wemm 		}
3876c2aa98e2SPeter Wemm 		if (hbsize > vsize + (int) strlen(domain) + 1)
3877c2aa98e2SPeter Wemm 		{
3878c2aa98e2SPeter Wemm 			if (domain[0] == '\0')
387940266059SGregory Neil Shapiro 				(void) sm_strlcpy(name, vp, hbsize);
3880c2aa98e2SPeter Wemm 			else
388140266059SGregory Neil Shapiro 				(void) sm_snprintf(name, hbsize,
388240266059SGregory Neil Shapiro 						   "%s.%s", vp, domain);
3883c2aa98e2SPeter Wemm 			*statp = EX_OK;
3884c2aa98e2SPeter Wemm 		}
3885c2aa98e2SPeter Wemm 		else
3886c2aa98e2SPeter Wemm 			*statp = EX_NOHOST;
3887c2aa98e2SPeter Wemm 		nis_freeresult(result);
388840266059SGregory Neil Shapiro 		return true;
3889c2aa98e2SPeter Wemm 	}
3890c2aa98e2SPeter Wemm 	else
3891c2aa98e2SPeter Wemm 	{
3892c2aa98e2SPeter Wemm 		if (result->status == NIS_NOTFOUND)
3893c2aa98e2SPeter Wemm 			*statp = EX_NOHOST;
3894c2aa98e2SPeter Wemm 		else if (result->status == NIS_TRYAGAIN)
3895c2aa98e2SPeter Wemm 			*statp = EX_TEMPFAIL;
3896c2aa98e2SPeter Wemm 		else
3897c2aa98e2SPeter Wemm 			*statp = EX_UNAVAILABLE;
3898c2aa98e2SPeter Wemm 	}
3899c2aa98e2SPeter Wemm 	if (tTd(38, 20))
390040266059SGregory Neil Shapiro 		sm_dprintf("nisplus_getcanonname(%s), failed, status=%d, nsw_stat=%d\n",
3901c2aa98e2SPeter Wemm 			   name, result->status, *statp);
3902c2aa98e2SPeter Wemm 	nis_freeresult(result);
390340266059SGregory Neil Shapiro 	return false;
3904c2aa98e2SPeter Wemm }
3905c2aa98e2SPeter Wemm 
3906c2aa98e2SPeter Wemm char *
nisplus_default_domain()3907c2aa98e2SPeter Wemm nisplus_default_domain()
3908c2aa98e2SPeter Wemm {
39092fb4f839SGregory Neil Shapiro 	static char default_domain[MAXNAME + 1] = "";	/* EAI:hostname */
3910c2aa98e2SPeter Wemm 	char *p;
3911c2aa98e2SPeter Wemm 
3912c2aa98e2SPeter Wemm 	if (default_domain[0] != '\0')
391306f25ae9SGregory Neil Shapiro 		return default_domain;
3914c2aa98e2SPeter Wemm 
3915c2aa98e2SPeter Wemm 	p = nis_local_directory();
3916d0cef73dSGregory Neil Shapiro 	(void) sm_strlcpy(default_domain, p, sizeof(default_domain));
3917c2aa98e2SPeter Wemm 	return default_domain;
3918c2aa98e2SPeter Wemm }
3919c2aa98e2SPeter Wemm 
3920c2aa98e2SPeter Wemm #endif /* NISPLUS */
392140266059SGregory Neil Shapiro /*
3922c2aa98e2SPeter Wemm **  LDAP Modules
3923c2aa98e2SPeter Wemm */
3924c2aa98e2SPeter Wemm 
392506f25ae9SGregory Neil Shapiro /*
392606f25ae9SGregory Neil Shapiro **  LDAPMAP_DEQUOTE - helper routine for ldapmap_parseargs
392706f25ae9SGregory Neil Shapiro */
392806f25ae9SGregory Neil Shapiro 
392906f25ae9SGregory Neil Shapiro #if defined(LDAPMAP) || defined(PH_MAP)
393006f25ae9SGregory Neil Shapiro 
393140266059SGregory Neil Shapiro # if PH_MAP
393206f25ae9SGregory Neil Shapiro #  define ph_map_dequote ldapmap_dequote
39335b0945b5SGregory Neil Shapiro # endif
393406f25ae9SGregory Neil Shapiro 
393540266059SGregory Neil Shapiro static char *ldapmap_dequote __P((char *));
393640266059SGregory Neil Shapiro 
393740266059SGregory Neil Shapiro static char *
ldapmap_dequote(str)393806f25ae9SGregory Neil Shapiro ldapmap_dequote(str)
393906f25ae9SGregory Neil Shapiro 	char *str;
394006f25ae9SGregory Neil Shapiro {
394106f25ae9SGregory Neil Shapiro 	char *p;
394206f25ae9SGregory Neil Shapiro 	char *start;
394306f25ae9SGregory Neil Shapiro 
394406f25ae9SGregory Neil Shapiro 	if (str == NULL)
394506f25ae9SGregory Neil Shapiro 		return NULL;
394606f25ae9SGregory Neil Shapiro 
394706f25ae9SGregory Neil Shapiro 	p = str;
394806f25ae9SGregory Neil Shapiro 	if (*p == '"')
394906f25ae9SGregory Neil Shapiro 	{
395006f25ae9SGregory Neil Shapiro 		/* Should probably swallow initial whitespace here */
395106f25ae9SGregory Neil Shapiro 		start = ++p;
395206f25ae9SGregory Neil Shapiro 	}
395306f25ae9SGregory Neil Shapiro 	else
395406f25ae9SGregory Neil Shapiro 		return str;
395506f25ae9SGregory Neil Shapiro 	while (*p != '"' && *p != '\0')
395606f25ae9SGregory Neil Shapiro 		p++;
395706f25ae9SGregory Neil Shapiro 	if (*p != '\0')
395806f25ae9SGregory Neil Shapiro 		*p = '\0';
395906f25ae9SGregory Neil Shapiro 	return start;
396006f25ae9SGregory Neil Shapiro }
396106f25ae9SGregory Neil Shapiro #endif /* defined(LDAPMAP) || defined(PH_MAP) */
396206f25ae9SGregory Neil Shapiro 
396340266059SGregory Neil Shapiro #if LDAPMAP
3964c2aa98e2SPeter Wemm 
396540266059SGregory Neil Shapiro static SM_LDAP_STRUCT *LDAPDefaults = NULL;
3966c2aa98e2SPeter Wemm 
3967c2aa98e2SPeter Wemm /*
396806f25ae9SGregory Neil Shapiro **  LDAPMAP_OPEN -- open LDAP map
3969c2aa98e2SPeter Wemm **
397006f25ae9SGregory Neil Shapiro **	Connect to the LDAP server.  Re-use existing connections since a
397106f25ae9SGregory Neil Shapiro **	single server connection to a host (with the same host, port,
397206f25ae9SGregory Neil Shapiro **	bind DN, and secret) can answer queries for multiple maps.
3973c2aa98e2SPeter Wemm */
3974c2aa98e2SPeter Wemm 
3975c2aa98e2SPeter Wemm bool
ldapmap_open(map,mode)397606f25ae9SGregory Neil Shapiro ldapmap_open(map, mode)
3977c2aa98e2SPeter Wemm 	MAP *map;
3978c2aa98e2SPeter Wemm 	int mode;
3979c2aa98e2SPeter Wemm {
398040266059SGregory Neil Shapiro 	SM_LDAP_STRUCT *lmap;
398106f25ae9SGregory Neil Shapiro 	STAB *s;
3982e92d3f3fSGregory Neil Shapiro 	char *id;
398306f25ae9SGregory Neil Shapiro 
3984c2aa98e2SPeter Wemm 	if (tTd(38, 2))
398540266059SGregory Neil Shapiro 		sm_dprintf("ldapmap_open(%s, %d): ", map->map_mname, mode);
3986c2aa98e2SPeter Wemm 
3987d0cef73dSGregory Neil Shapiro # if defined(SUN_EXTENSIONS) && defined(SUN_SIMPLIFIED_LDAP) && \
3988d0cef73dSGregory Neil Shapiro     HASLDAPGETALIASBYNAME
3989d0cef73dSGregory Neil Shapiro 	if (VendorCode == VENDOR_SUN &&
3990d0cef73dSGregory Neil Shapiro 	    strcmp(map->map_mname, "aliases.ldap") == 0)
3991d0cef73dSGregory Neil Shapiro 	{
3992d0cef73dSGregory Neil Shapiro 		return true;
3993d0cef73dSGregory Neil Shapiro 	}
3994d0cef73dSGregory Neil Shapiro # endif /* defined(SUN_EXTENSIONS) && defined(SUN_SIMPLIFIED_LDAP) && ... */
3995d0cef73dSGregory Neil Shapiro 
3996c2aa98e2SPeter Wemm 	mode &= O_ACCMODE;
399706f25ae9SGregory Neil Shapiro 
399806f25ae9SGregory Neil Shapiro 	/* sendmail doesn't have the ability to write to LDAP (yet) */
3999c2aa98e2SPeter Wemm 	if (mode != O_RDONLY)
4000c2aa98e2SPeter Wemm 	{
4001c2aa98e2SPeter Wemm 		/* issue a pseudo-error message */
400240266059SGregory Neil Shapiro 		errno = SM_EMAPCANTWRITE;
400340266059SGregory Neil Shapiro 		return false;
4004c2aa98e2SPeter Wemm 	}
400506f25ae9SGregory Neil Shapiro 
400640266059SGregory Neil Shapiro 	lmap = (SM_LDAP_STRUCT *) map->map_db1;
400706f25ae9SGregory Neil Shapiro 
400806f25ae9SGregory Neil Shapiro 	s = ldapmap_findconn(lmap);
40098774250cSGregory Neil Shapiro 	if (s->s_lmap != NULL)
401006f25ae9SGregory Neil Shapiro 	{
401106f25ae9SGregory Neil Shapiro 		/* Already have a connection open to this LDAP server */
401240266059SGregory Neil Shapiro 		lmap->ldap_ld = ((SM_LDAP_STRUCT *)s->s_lmap->map_db1)->ldap_ld;
401340266059SGregory Neil Shapiro 		lmap->ldap_pid = ((SM_LDAP_STRUCT *)s->s_lmap->map_db1)->ldap_pid;
40148774250cSGregory Neil Shapiro 
40158774250cSGregory Neil Shapiro 		/* Add this map as head of linked list */
40168774250cSGregory Neil Shapiro 		lmap->ldap_next = s->s_lmap;
40178774250cSGregory Neil Shapiro 		s->s_lmap = map;
40188774250cSGregory Neil Shapiro 
401942e5d165SGregory Neil Shapiro 		if (tTd(38, 2))
402040266059SGregory Neil Shapiro 			sm_dprintf("using cached connection\n");
402140266059SGregory Neil Shapiro 		return true;
4022c2aa98e2SPeter Wemm 	}
4023c2aa98e2SPeter Wemm 
402442e5d165SGregory Neil Shapiro 	if (tTd(38, 2))
402540266059SGregory Neil Shapiro 		sm_dprintf("opening new connection\n");
402642e5d165SGregory Neil Shapiro 
4027e92d3f3fSGregory Neil Shapiro 	if (lmap->ldap_host != NULL)
4028e92d3f3fSGregory Neil Shapiro 		id = lmap->ldap_host;
4029e92d3f3fSGregory Neil Shapiro 	else if (lmap->ldap_uri != NULL)
4030e92d3f3fSGregory Neil Shapiro 		id = lmap->ldap_uri;
4031e92d3f3fSGregory Neil Shapiro 	else
4032e92d3f3fSGregory Neil Shapiro 		id = "localhost";
4033e92d3f3fSGregory Neil Shapiro 
40349bd497b8SGregory Neil Shapiro 	if (tTd(74, 104))
40359bd497b8SGregory Neil Shapiro 	{
40369bd497b8SGregory Neil Shapiro 		extern MAPCLASS NullMapClass;
40379bd497b8SGregory Neil Shapiro 
40389bd497b8SGregory Neil Shapiro 		/* debug mode: don't actually open an LDAP connection */
40399bd497b8SGregory Neil Shapiro 		map->map_orgclass = map->map_class;
40409bd497b8SGregory Neil Shapiro 		map->map_class = &NullMapClass;
40419bd497b8SGregory Neil Shapiro 		map->map_mflags |= MF_OPEN;
40429bd497b8SGregory Neil Shapiro 		map->map_pid = CurrentPid;
40439bd497b8SGregory Neil Shapiro 		return true;
40449bd497b8SGregory Neil Shapiro 	}
40459bd497b8SGregory Neil Shapiro 
404606f25ae9SGregory Neil Shapiro 	/* No connection yet, connect */
404740266059SGregory Neil Shapiro 	if (!sm_ldap_start(map->map_mname, lmap))
404806f25ae9SGregory Neil Shapiro 	{
404940266059SGregory Neil Shapiro 		if (errno == ETIMEDOUT)
405006f25ae9SGregory Neil Shapiro 		{
405106f25ae9SGregory Neil Shapiro 			if (LogLevel > 1)
405206f25ae9SGregory Neil Shapiro 				sm_syslog(LOG_NOTICE, CurEnv->e_id,
4053ba00ec3dSGregory Neil Shapiro 					  "timeout connecting to LDAP server %.100s",
4054e92d3f3fSGregory Neil Shapiro 					  id);
405506f25ae9SGregory Neil Shapiro 		}
405606f25ae9SGregory Neil Shapiro 
405706f25ae9SGregory Neil Shapiro 		if (!bitset(MF_OPTIONAL, map->map_mflags))
405806f25ae9SGregory Neil Shapiro 		{
405906f25ae9SGregory Neil Shapiro 			if (bitset(MF_NODEFER, map->map_mflags))
4060e92d3f3fSGregory Neil Shapiro 			{
406106f25ae9SGregory Neil Shapiro 				syserr("%s failed to %s in map %s",
406206f25ae9SGregory Neil Shapiro # if USE_LDAP_INIT
406340266059SGregory Neil Shapiro 				       "ldap_init/ldap_bind",
40645b0945b5SGregory Neil Shapiro # else
406506f25ae9SGregory Neil Shapiro 				       "ldap_open",
40665b0945b5SGregory Neil Shapiro # endif
4067e92d3f3fSGregory Neil Shapiro 				       id, map->map_mname);
4068e92d3f3fSGregory Neil Shapiro 			}
406906f25ae9SGregory Neil Shapiro 			else
4070e92d3f3fSGregory Neil Shapiro 			{
4071605302a5SGregory Neil Shapiro 				syserr("451 4.3.5 %s failed to %s in map %s",
407206f25ae9SGregory Neil Shapiro # if USE_LDAP_INIT
407340266059SGregory Neil Shapiro 				       "ldap_init/ldap_bind",
40745b0945b5SGregory Neil Shapiro # else
407506f25ae9SGregory Neil Shapiro 				       "ldap_open",
40765b0945b5SGregory Neil Shapiro # endif
4077e92d3f3fSGregory Neil Shapiro 				       id, map->map_mname);
4078e92d3f3fSGregory Neil Shapiro 			}
407906f25ae9SGregory Neil Shapiro 		}
408040266059SGregory Neil Shapiro 		return false;
408106f25ae9SGregory Neil Shapiro 	}
408206f25ae9SGregory Neil Shapiro 
408340266059SGregory Neil Shapiro 	/* Save connection for reuse */
408440266059SGregory Neil Shapiro 	s->s_lmap = map;
408540266059SGregory Neil Shapiro 	return true;
4086c2aa98e2SPeter Wemm }
4087c2aa98e2SPeter Wemm 
408806f25ae9SGregory Neil Shapiro /*
408906f25ae9SGregory Neil Shapiro **  LDAPMAP_CLOSE -- close ldap map
409006f25ae9SGregory Neil Shapiro */
409106f25ae9SGregory Neil Shapiro 
409206f25ae9SGregory Neil Shapiro void
ldapmap_close(map)409306f25ae9SGregory Neil Shapiro ldapmap_close(map)
4094c2aa98e2SPeter Wemm 	MAP *map;
4095c2aa98e2SPeter Wemm {
409640266059SGregory Neil Shapiro 	SM_LDAP_STRUCT *lmap;
409706f25ae9SGregory Neil Shapiro 	STAB *s;
4098c2aa98e2SPeter Wemm 
4099c2aa98e2SPeter Wemm 	if (tTd(38, 2))
410040266059SGregory Neil Shapiro 		sm_dprintf("ldapmap_close(%s)\n", map->map_mname);
4101c2aa98e2SPeter Wemm 
410240266059SGregory Neil Shapiro 	lmap = (SM_LDAP_STRUCT *) map->map_db1;
4103c2aa98e2SPeter Wemm 
410406f25ae9SGregory Neil Shapiro 	/* Check if already closed */
410506f25ae9SGregory Neil Shapiro 	if (lmap->ldap_ld == NULL)
410606f25ae9SGregory Neil Shapiro 		return;
4107c2aa98e2SPeter Wemm 
41088774250cSGregory Neil Shapiro 	/* Close the LDAP connection */
410940266059SGregory Neil Shapiro 	sm_ldap_close(lmap);
41108774250cSGregory Neil Shapiro 
41118774250cSGregory Neil Shapiro 	/* Mark all the maps that share the connection as closed */
411206f25ae9SGregory Neil Shapiro 	s = ldapmap_findconn(lmap);
4113c2aa98e2SPeter Wemm 
41148774250cSGregory Neil Shapiro 	while (s->s_lmap != NULL)
4115c2aa98e2SPeter Wemm 	{
41168774250cSGregory Neil Shapiro 		MAP *smap = s->s_lmap;
41178774250cSGregory Neil Shapiro 
41188774250cSGregory Neil Shapiro 		if (tTd(38, 2) && smap != map)
411940266059SGregory Neil Shapiro 			sm_dprintf("ldapmap_close(%s): closed %s (shared LDAP connection)\n",
41208774250cSGregory Neil Shapiro 				   map->map_mname, smap->map_mname);
41218774250cSGregory Neil Shapiro 		smap->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
412240266059SGregory Neil Shapiro 		lmap = (SM_LDAP_STRUCT *) smap->map_db1;
412306f25ae9SGregory Neil Shapiro 		lmap->ldap_ld = NULL;
41248774250cSGregory Neil Shapiro 		s->s_lmap = lmap->ldap_next;
41258774250cSGregory Neil Shapiro 		lmap->ldap_next = NULL;
4126c2aa98e2SPeter Wemm 	}
4127c2aa98e2SPeter Wemm }
4128c2aa98e2SPeter Wemm 
4129c2aa98e2SPeter Wemm # ifdef SUNET_ID
4130c2aa98e2SPeter Wemm /*
413140266059SGregory Neil Shapiro **  SUNET_ID_HASH -- Convert a string to its Sunet_id canonical form
4132c2aa98e2SPeter Wemm **  This only makes sense at Stanford University.
4133c2aa98e2SPeter Wemm */
4134c2aa98e2SPeter Wemm 
413540266059SGregory Neil Shapiro static char *
sunet_id_hash(str)4136c2aa98e2SPeter Wemm sunet_id_hash(str)
4137c2aa98e2SPeter Wemm 	char *str;
4138c2aa98e2SPeter Wemm {
4139c2aa98e2SPeter Wemm 	char *p, *p_last;
4140c2aa98e2SPeter Wemm 
4141c2aa98e2SPeter Wemm 	p = str;
4142c2aa98e2SPeter Wemm 	p_last = p;
4143c2aa98e2SPeter Wemm 	while (*p != '\0')
4144c2aa98e2SPeter Wemm 	{
41459bd497b8SGregory Neil Shapiro 		if (isascii(*p) && (islower(*p) || isdigit(*p)))
4146c2aa98e2SPeter Wemm 		{
4147c2aa98e2SPeter Wemm 			*p_last = *p;
4148c2aa98e2SPeter Wemm 			p_last++;
4149c2aa98e2SPeter Wemm 		}
41509bd497b8SGregory Neil Shapiro 		else if (isascii(*p) && isupper(*p))
4151c2aa98e2SPeter Wemm 		{
4152c2aa98e2SPeter Wemm 			*p_last = tolower(*p);
4153c2aa98e2SPeter Wemm 			p_last++;
4154c2aa98e2SPeter Wemm 		}
4155c2aa98e2SPeter Wemm 		++p;
4156c2aa98e2SPeter Wemm 	}
4157c2aa98e2SPeter Wemm 	if (*p_last != '\0')
4158c2aa98e2SPeter Wemm 		*p_last = '\0';
415906f25ae9SGregory Neil Shapiro 	return str;
4160c2aa98e2SPeter Wemm }
4161d0cef73dSGregory Neil Shapiro #  define SM_CONVERT_ID(str)	sunet_id_hash(str)
4162d0cef73dSGregory Neil Shapiro # else /* SUNET_ID */
4163d0cef73dSGregory Neil Shapiro #  define SM_CONVERT_ID(str)	makelower(str)
4164c2aa98e2SPeter Wemm # endif /* SUNET_ID */
416506f25ae9SGregory Neil Shapiro 
4166c2aa98e2SPeter Wemm /*
416706f25ae9SGregory Neil Shapiro **  LDAPMAP_LOOKUP -- look up a datum in a LDAP map
4168c2aa98e2SPeter Wemm */
4169c2aa98e2SPeter Wemm 
4170c2aa98e2SPeter Wemm char *
ldapmap_lookup(map,name,av,statp)417106f25ae9SGregory Neil Shapiro ldapmap_lookup(map, name, av, statp)
4172c2aa98e2SPeter Wemm 	MAP *map;
4173c2aa98e2SPeter Wemm 	char *name;
4174c2aa98e2SPeter Wemm 	char **av;
4175c2aa98e2SPeter Wemm 	int *statp;
4176c2aa98e2SPeter Wemm {
4177e92d3f3fSGregory Neil Shapiro 	int flags;
4178d0cef73dSGregory Neil Shapiro 	int i;
4179605302a5SGregory Neil Shapiro 	int plen = 0;
4180605302a5SGregory Neil Shapiro 	int psize = 0;
4181605302a5SGregory Neil Shapiro 	int msgid;
4182605302a5SGregory Neil Shapiro 	int save_errno;
418340266059SGregory Neil Shapiro 	char *vp, *p;
418406f25ae9SGregory Neil Shapiro 	char *result = NULL;
4185e92d3f3fSGregory Neil Shapiro 	SM_RPOOL_T *rpool;
418640266059SGregory Neil Shapiro 	SM_LDAP_STRUCT *lmap = NULL;
4187d0cef73dSGregory Neil Shapiro 	char *argv[SM_LDAP_ARGS];
41884e4196cbSGregory Neil Shapiro 	char keybuf[MAXKEY];
4189d0cef73dSGregory Neil Shapiro # if SM_LDAP_ARGS != MAX_MAP_ARGS
4190*d39bd2c1SGregory Neil Shapiro #  error "SM_LDAP_ARGS must be the same as MAX_MAP_ARGS"
41912fb4f839SGregory Neil Shapiro # endif
41922fb4f839SGregory Neil Shapiro 
41932fb4f839SGregory Neil Shapiro # define AV_FREE(av)	\
41942fb4f839SGregory Neil Shapiro 	do		\
41952fb4f839SGregory Neil Shapiro 	{		\
41962fb4f839SGregory Neil Shapiro 		int ai;	\
41972fb4f839SGregory Neil Shapiro 		for (ai = 0; ai < SM_LDAP_ARGS && av[ai] != NULL; ai++) \
41982fb4f839SGregory Neil Shapiro 			SM_FREE(av[ai]);	\
41992fb4f839SGregory Neil Shapiro 	} while (0)
42002fb4f839SGregory Neil Shapiro 
42012fb4f839SGregory Neil Shapiro # if USE_EAI
42022fb4f839SGregory Neil Shapiro 	bool allascii;
42032fb4f839SGregory Neil Shapiro 	char *largv[SM_LDAP_ARGS];
42042fb4f839SGregory Neil Shapiro 	char **largs;
42052fb4f839SGregory Neil Shapiro 
42062fb4f839SGregory Neil Shapiro #  define LARGV_FREE	AV_FREE(largv)
42072fb4f839SGregory Neil Shapiro # else
42082fb4f839SGregory Neil Shapiro #  define largs av
42092fb4f839SGregory Neil Shapiro #  define LARGV_FREE
42105b0945b5SGregory Neil Shapiro # endif
4211c2aa98e2SPeter Wemm 
4212d0cef73dSGregory Neil Shapiro # if defined(SUN_EXTENSIONS) && defined(SUN_SIMPLIFIED_LDAP) && \
4213d0cef73dSGregory Neil Shapiro     HASLDAPGETALIASBYNAME
4214d0cef73dSGregory Neil Shapiro 	if (VendorCode == VENDOR_SUN &&
4215d0cef73dSGregory Neil Shapiro 	    strcmp(map->map_mname, "aliases.ldap") == 0)
4216d0cef73dSGregory Neil Shapiro 	{
4217d0cef73dSGregory Neil Shapiro 		int rc;
4218ffb83623SGregory Neil Shapiro #  if defined(GETLDAPALIASBYNAME_VERSION) && (GETLDAPALIASBYNAME_VERSION >= 2)
4219ffb83623SGregory Neil Shapiro 		extern char *__getldapaliasbyname();
4220ffb83623SGregory Neil Shapiro 		char *answer;
4221ffb83623SGregory Neil Shapiro 
4222ffb83623SGregory Neil Shapiro 		answer = __getldapaliasbyname(name, &rc);
4223ffb83623SGregory Neil Shapiro #  else
42242fb4f839SGregory Neil Shapiro 		char answer[MAXNAME + 1];	/* EAI:Sun only, ignore */
4225d0cef73dSGregory Neil Shapiro 
4226d0cef73dSGregory Neil Shapiro 		rc = __getldapaliasbyname(name, answer, sizeof(answer));
4227ffb83623SGregory Neil Shapiro #  endif
4228d0cef73dSGregory Neil Shapiro 		if (rc != 0)
4229d0cef73dSGregory Neil Shapiro 		{
4230c2aa98e2SPeter Wemm 			if (tTd(38, 20))
4231d0cef73dSGregory Neil Shapiro 				sm_dprintf("getldapaliasbyname(%.100s) failed, errno=%d\n",
4232d0cef73dSGregory Neil Shapiro 					   name, errno);
4233d0cef73dSGregory Neil Shapiro 			*statp = EX_NOTFOUND;
4234d0cef73dSGregory Neil Shapiro 			return NULL;
4235d0cef73dSGregory Neil Shapiro 		}
4236d0cef73dSGregory Neil Shapiro 		*statp = EX_OK;
4237d0cef73dSGregory Neil Shapiro 		if (tTd(38, 20))
4238d0cef73dSGregory Neil Shapiro 			sm_dprintf("getldapaliasbyname(%.100s) => %s\n", name,
4239d0cef73dSGregory Neil Shapiro 				   answer);
4240d0cef73dSGregory Neil Shapiro 		if (bitset(MF_MATCHONLY, map->map_mflags))
4241d0cef73dSGregory Neil Shapiro 			result = map_rewrite(map, name, strlen(name), NULL);
4242d0cef73dSGregory Neil Shapiro 		else
4243d0cef73dSGregory Neil Shapiro 			result = map_rewrite(map, answer, strlen(answer), av);
4244ffb83623SGregory Neil Shapiro #  if defined(GETLDAPALIASBYNAME_VERSION) && (GETLDAPALIASBYNAME_VERSION >= 2)
4245ffb83623SGregory Neil Shapiro 		free(answer);
4246ffb83623SGregory Neil Shapiro #  endif
4247d0cef73dSGregory Neil Shapiro 		return result;
4248d0cef73dSGregory Neil Shapiro 	}
4249d0cef73dSGregory Neil Shapiro # endif /* defined(SUN_EXTENSIONS) && defined(SUN_SIMPLIFIED_LDAP) && ... */
4250c2aa98e2SPeter Wemm 
4251c2aa98e2SPeter Wemm 	/* Get ldap struct pointer from map */
425240266059SGregory Neil Shapiro 	lmap = (SM_LDAP_STRUCT *) map->map_db1;
425340266059SGregory Neil Shapiro 	sm_ldap_setopts(lmap->ldap_ld, lmap);
4254c2aa98e2SPeter Wemm 
42552fb4f839SGregory Neil Shapiro 	/* initialize first element so AV_FREE can work */
42562fb4f839SGregory Neil Shapiro 	argv[0] = NULL;
42572fb4f839SGregory Neil Shapiro # if USE_EAI
42582fb4f839SGregory Neil Shapiro 	largv[0] = NULL;
42592fb4f839SGregory Neil Shapiro # endif
42602fb4f839SGregory Neil Shapiro 
4261d0cef73dSGregory Neil Shapiro 	if (lmap->ldap_multi_args)
426206f25ae9SGregory Neil Shapiro 	{
4263d0cef73dSGregory Neil Shapiro 		SM_REQUIRE(av != NULL);
4264d0cef73dSGregory Neil Shapiro 		memset(argv, '\0', sizeof(argv));
42652fb4f839SGregory Neil Shapiro # if USE_EAI
42662fb4f839SGregory Neil Shapiro 		largs = av;
42672fb4f839SGregory Neil Shapiro 		memset(largv, '\0', sizeof(largv));
42682fb4f839SGregory Neil Shapiro 
42692fb4f839SGregory Neil Shapiro 		/* this is ugly - can we merge it with the next loop? */
42702fb4f839SGregory Neil Shapiro 		allascii = true;
42712fb4f839SGregory Neil Shapiro 		if (!bitset(MF_MATCHONLY, map->map_mflags))
42722fb4f839SGregory Neil Shapiro 		{
42732fb4f839SGregory Neil Shapiro 			for (i = 0, allascii = true;
42742fb4f839SGregory Neil Shapiro 			     i < SM_LDAP_ARGS && av[i] != NULL;
42752fb4f839SGregory Neil Shapiro 			     i++)
42762fb4f839SGregory Neil Shapiro 			{
42772fb4f839SGregory Neil Shapiro 				if (!addr_is_ascii(av[i]))
42782fb4f839SGregory Neil Shapiro 				{
42792fb4f839SGregory Neil Shapiro 					allascii = false;
42802fb4f839SGregory Neil Shapiro 					largs = largv;
42812fb4f839SGregory Neil Shapiro 					break;
42822fb4f839SGregory Neil Shapiro 				}
42832fb4f839SGregory Neil Shapiro 			}
42842fb4f839SGregory Neil Shapiro 		}
42852fb4f839SGregory Neil Shapiro # endif /* USE_EAI */
4286d0cef73dSGregory Neil Shapiro 		for (i = 0; i < SM_LDAP_ARGS && av[i] != NULL; i++)
4287d0cef73dSGregory Neil Shapiro 		{
4288d0cef73dSGregory Neil Shapiro 			argv[i] = sm_strdup(av[i]);
4289d0cef73dSGregory Neil Shapiro 			if (argv[i] == NULL)
4290d0cef73dSGregory Neil Shapiro 			{
4291d0cef73dSGregory Neil Shapiro 				*statp = EX_TEMPFAIL;
42922fb4f839SGregory Neil Shapiro 				goto none;
429306f25ae9SGregory Neil Shapiro 			}
4294c2aa98e2SPeter Wemm 
4295d0cef73dSGregory Neil Shapiro 			if (!bitset(MF_NOFOLDCASE, map->map_mflags))
42962fb4f839SGregory Neil Shapiro /*			    && !bitset(MF_MATCHONLY, map->map_mflags))	*/
42972fb4f839SGregory Neil Shapiro /* see below: av[]/largs onluy used if !MF_MATCHONLY !? */
42982fb4f839SGregory Neil Shapiro 			{
42992fb4f839SGregory Neil Shapiro # if USE_EAI
43002fb4f839SGregory Neil Shapiro 				if (!allascii)
43012fb4f839SGregory Neil Shapiro 				{
43022fb4f839SGregory Neil Shapiro 					char *lower;
43032fb4f839SGregory Neil Shapiro 
43042fb4f839SGregory Neil Shapiro 					lower = makelower(av[i]);
43052fb4f839SGregory Neil Shapiro 					largv[i] = sm_strdup(lower);
43062fb4f839SGregory Neil Shapiro 					if (largv[i] == NULL)
43072fb4f839SGregory Neil Shapiro 					{
43082fb4f839SGregory Neil Shapiro 						*statp = EX_TEMPFAIL;
43092fb4f839SGregory Neil Shapiro 						goto none;
43102fb4f839SGregory Neil Shapiro 					}
43112fb4f839SGregory Neil Shapiro 				}
43122fb4f839SGregory Neil Shapiro 				else
43132fb4f839SGregory Neil Shapiro # endif /* USE_EAI */
43142fb4f839SGregory Neil Shapiro 				/* NOTE: see else above! */
4315d0cef73dSGregory Neil Shapiro 				SM_CONVERT_ID(av[i]);
4316d0cef73dSGregory Neil Shapiro 			}
4317d0cef73dSGregory Neil Shapiro 		}
43182fb4f839SGregory Neil Shapiro 	}
4319d0cef73dSGregory Neil Shapiro 	else
4320d0cef73dSGregory Neil Shapiro 	{
4321d0cef73dSGregory Neil Shapiro 		(void) sm_strlcpy(keybuf, name, sizeof(keybuf));
4322d0cef73dSGregory Neil Shapiro 
4323d0cef73dSGregory Neil Shapiro 		if (!bitset(MF_NOFOLDCASE, map->map_mflags))
4324d0cef73dSGregory Neil Shapiro 			SM_CONVERT_ID(keybuf);
4325d0cef73dSGregory Neil Shapiro 	}
4326d0cef73dSGregory Neil Shapiro 
4327d0cef73dSGregory Neil Shapiro 	if (tTd(38, 20))
4328d0cef73dSGregory Neil Shapiro 	{
4329d0cef73dSGregory Neil Shapiro 		if (lmap->ldap_multi_args)
4330d0cef73dSGregory Neil Shapiro 		{
4331d0cef73dSGregory Neil Shapiro 			sm_dprintf("ldapmap_lookup(%s, argv)\n",
4332d0cef73dSGregory Neil Shapiro 				map->map_mname);
4333d0cef73dSGregory Neil Shapiro 			for (i = 0; i < SM_LDAP_ARGS; i++)
4334d0cef73dSGregory Neil Shapiro 			{
4335d0cef73dSGregory Neil Shapiro 				sm_dprintf("   argv[%d] = %s\n", i,
4336d0cef73dSGregory Neil Shapiro 					   argv[i] == NULL ? "NULL" : argv[i]);
4337d0cef73dSGregory Neil Shapiro 			}
4338d0cef73dSGregory Neil Shapiro 		}
4339d0cef73dSGregory Neil Shapiro 		else
4340d0cef73dSGregory Neil Shapiro 		{
4341d0cef73dSGregory Neil Shapiro 			sm_dprintf("ldapmap_lookup(%s, %s)\n",
4342d0cef73dSGregory Neil Shapiro 				   map->map_mname, name);
4343d0cef73dSGregory Neil Shapiro 		}
4344d0cef73dSGregory Neil Shapiro 	}
4345d0cef73dSGregory Neil Shapiro 
4346d0cef73dSGregory Neil Shapiro 	if (lmap->ldap_multi_args)
4347d0cef73dSGregory Neil Shapiro 	{
4348d0cef73dSGregory Neil Shapiro 		msgid = sm_ldap_search_m(lmap, argv);
4349d0cef73dSGregory Neil Shapiro 
4350d0cef73dSGregory Neil Shapiro 		/* free the argv array and its content, no longer needed */
43512fb4f839SGregory Neil Shapiro 		AV_FREE(argv);
4352d0cef73dSGregory Neil Shapiro 	}
4353d0cef73dSGregory Neil Shapiro 	else
435440266059SGregory Neil Shapiro 		msgid = sm_ldap_search(lmap, keybuf);
4355d0cef73dSGregory Neil Shapiro 	if (msgid == SM_LDAP_ERR)
4356c2aa98e2SPeter Wemm 	{
435740266059SGregory Neil Shapiro 		errno = sm_ldap_geterrno(lmap->ldap_ld) + E_LDAPBASE;
43588774250cSGregory Neil Shapiro 		save_errno = errno;
4359c2aa98e2SPeter Wemm 		if (!bitset(MF_OPTIONAL, map->map_mflags))
4360c2aa98e2SPeter Wemm 		{
4361d0cef73dSGregory Neil Shapiro 			/*
4362d0cef73dSGregory Neil Shapiro 			**  Do not include keybuf as this error may be shown
4363d0cef73dSGregory Neil Shapiro 			**  to outsiders.
4364d0cef73dSGregory Neil Shapiro 			*/
4365d0cef73dSGregory Neil Shapiro 
436606f25ae9SGregory Neil Shapiro 			if (bitset(MF_NODEFER, map->map_mflags))
4367d0cef73dSGregory Neil Shapiro 				syserr("Error in ldap_search in map %s",
4368d0cef73dSGregory Neil Shapiro 				       map->map_mname);
436906f25ae9SGregory Neil Shapiro 			else
4370d0cef73dSGregory Neil Shapiro 				syserr("451 4.3.5 Error in ldap_search in map %s",
4371d0cef73dSGregory Neil Shapiro 				       map->map_mname);
4372c2aa98e2SPeter Wemm 		}
4373c2aa98e2SPeter Wemm 		*statp = EX_TEMPFAIL;
437440266059SGregory Neil Shapiro 		switch (save_errno - E_LDAPBASE)
43758774250cSGregory Neil Shapiro 		{
437640266059SGregory Neil Shapiro # ifdef LDAP_SERVER_DOWN
437740266059SGregory Neil Shapiro 		  case LDAP_SERVER_DOWN:
43785b0945b5SGregory Neil Shapiro # endif
437940266059SGregory Neil Shapiro 		  case LDAP_TIMEOUT:
438040266059SGregory Neil Shapiro 		  case LDAP_UNAVAILABLE:
43818774250cSGregory Neil Shapiro 			/* server disappeared, try reopen on next search */
43828774250cSGregory Neil Shapiro 			ldapmap_close(map);
438340266059SGregory Neil Shapiro 			break;
438442e5d165SGregory Neil Shapiro 		}
43858774250cSGregory Neil Shapiro 		errno = save_errno;
43862fb4f839SGregory Neil Shapiro 		goto none;
438706f25ae9SGregory Neil Shapiro 	}
4388d0cef73dSGregory Neil Shapiro # if SM_LDAP_ERROR_ON_MISSING_ARGS
4389d0cef73dSGregory Neil Shapiro 	else if (msgid == SM_LDAP_ERR_ARG_MISS)
4390d0cef73dSGregory Neil Shapiro 	{
4391d0cef73dSGregory Neil Shapiro 		if (bitset(MF_NODEFER, map->map_mflags))
4392d0cef73dSGregory Neil Shapiro 			syserr("Error in ldap_search in map %s, too few arguments",
4393d0cef73dSGregory Neil Shapiro 			       map->map_mname);
4394d0cef73dSGregory Neil Shapiro 		else
4395d0cef73dSGregory Neil Shapiro 			syserr("554 5.3.5 Error in ldap_search in map %s, too few arguments",
4396d0cef73dSGregory Neil Shapiro 			       map->map_mname);
4397d0cef73dSGregory Neil Shapiro 		*statp = EX_CONFIG;
43982fb4f839SGregory Neil Shapiro 		goto none;
4399d0cef73dSGregory Neil Shapiro 	}
4400d0cef73dSGregory Neil Shapiro # endif /* SM_LDAP_ERROR_ON_MISSING_ARGS */
440106f25ae9SGregory Neil Shapiro 
440206f25ae9SGregory Neil Shapiro 	*statp = EX_NOTFOUND;
440306f25ae9SGregory Neil Shapiro 	vp = NULL;
440406f25ae9SGregory Neil Shapiro 
440540266059SGregory Neil Shapiro 	flags = 0;
440640266059SGregory Neil Shapiro 	if (bitset(MF_SINGLEMATCH, map->map_mflags))
440740266059SGregory Neil Shapiro 		flags |= SM_LDAP_SINGLEMATCH;
440840266059SGregory Neil Shapiro 	if (bitset(MF_MATCHONLY, map->map_mflags))
440940266059SGregory Neil Shapiro 		flags |= SM_LDAP_MATCHONLY;
44104e4196cbSGregory Neil Shapiro # if _FFR_LDAP_SINGLEDN
44114e4196cbSGregory Neil Shapiro 	if (bitset(MF_SINGLEDN, map->map_mflags))
44124e4196cbSGregory Neil Shapiro 		flags |= SM_LDAP_SINGLEDN;
44135b0945b5SGregory Neil Shapiro # endif
441440266059SGregory Neil Shapiro 
441540266059SGregory Neil Shapiro 	/* Create an rpool for search related memory usage */
441640266059SGregory Neil Shapiro 	rpool = sm_rpool_new_x(NULL);
441740266059SGregory Neil Shapiro 
441840266059SGregory Neil Shapiro 	p = NULL;
441940266059SGregory Neil Shapiro 	*statp = sm_ldap_results(lmap, msgid, flags, map->map_coldelim,
4420605302a5SGregory Neil Shapiro 				 rpool, &p, &plen, &psize, NULL);
442140266059SGregory Neil Shapiro 	save_errno = errno;
442240266059SGregory Neil Shapiro 
442340266059SGregory Neil Shapiro 	/* Copy result so rpool can be freed */
442440266059SGregory Neil Shapiro 	if (*statp == EX_OK && p != NULL)
442540266059SGregory Neil Shapiro 		vp = newstr(p);
442640266059SGregory Neil Shapiro 	sm_rpool_free(rpool);
442740266059SGregory Neil Shapiro 
442840266059SGregory Neil Shapiro 	/* need to restart LDAP connection? */
442940266059SGregory Neil Shapiro 	if (*statp == EX_RESTART)
443040266059SGregory Neil Shapiro 	{
443140266059SGregory Neil Shapiro 		*statp = EX_TEMPFAIL;
443240266059SGregory Neil Shapiro 		ldapmap_close(map);
443340266059SGregory Neil Shapiro 	}
443440266059SGregory Neil Shapiro 
443540266059SGregory Neil Shapiro 	errno = save_errno;
443640266059SGregory Neil Shapiro 	if (*statp != EX_OK && *statp != EX_NOTFOUND)
443740266059SGregory Neil Shapiro 	{
443840266059SGregory Neil Shapiro 		if (!bitset(MF_OPTIONAL, map->map_mflags))
443940266059SGregory Neil Shapiro 		{
444040266059SGregory Neil Shapiro 			if (bitset(MF_NODEFER, map->map_mflags))
4441ba00ec3dSGregory Neil Shapiro 				syserr("Error getting LDAP results, map=%s, name=%s",
4442ba00ec3dSGregory Neil Shapiro 				       map->map_mname, name);
444340266059SGregory Neil Shapiro 			else
4444ba00ec3dSGregory Neil Shapiro 				syserr("451 4.3.5 Error getting LDAP results, map=%s, name=%s",
4445ba00ec3dSGregory Neil Shapiro 				       map->map_mname, name);
444640266059SGregory Neil Shapiro 		}
444740266059SGregory Neil Shapiro 		errno = save_errno;
44482fb4f839SGregory Neil Shapiro 		goto none;
444940266059SGregory Neil Shapiro 	}
445040266059SGregory Neil Shapiro 
445106f25ae9SGregory Neil Shapiro 	/* Did we match anything? */
4452193538b7SGregory Neil Shapiro 	if (vp == NULL && !bitset(MF_MATCHONLY, map->map_mflags))
44532fb4f839SGregory Neil Shapiro 		goto none;
445406f25ae9SGregory Neil Shapiro 
445506f25ae9SGregory Neil Shapiro 	if (*statp == EX_OK)
445606f25ae9SGregory Neil Shapiro 	{
4457c2aa98e2SPeter Wemm 		if (LogLevel > 9)
4458c2aa98e2SPeter Wemm 			sm_syslog(LOG_INFO, CurEnv->e_id,
4459ba00ec3dSGregory Neil Shapiro 				  "ldap=%s, %.100s=>%s", map->map_mname, name,
4460193538b7SGregory Neil Shapiro 				  vp == NULL ? "<NULL>" : vp);
4461c2aa98e2SPeter Wemm 		if (bitset(MF_MATCHONLY, map->map_mflags))
4462c2aa98e2SPeter Wemm 			result = map_rewrite(map, name, strlen(name), NULL);
4463c2aa98e2SPeter Wemm 		else
4464193538b7SGregory Neil Shapiro 		{
4465193538b7SGregory Neil Shapiro 			/* vp != NULL according to test above */
44662fb4f839SGregory Neil Shapiro 			result = map_rewrite(map, vp, strlen(vp), largs);
4467193538b7SGregory Neil Shapiro 		}
44682fb4f839SGregory Neil Shapiro 		SM_FREE(vp); /* XXX */
446906f25ae9SGregory Neil Shapiro 	}
44702fb4f839SGregory Neil Shapiro 	LARGV_FREE;
4471c2aa98e2SPeter Wemm 	return result;
44722fb4f839SGregory Neil Shapiro 
44732fb4f839SGregory Neil Shapiro   none:
44742fb4f839SGregory Neil Shapiro 	/* other cleanup? */
44752fb4f839SGregory Neil Shapiro 	save_errno = errno;
44762fb4f839SGregory Neil Shapiro 	AV_FREE(argv);
44772fb4f839SGregory Neil Shapiro 	LARGV_FREE;
44782fb4f839SGregory Neil Shapiro 	errno = save_errno;
44792fb4f839SGregory Neil Shapiro 	return NULL;
4480c2aa98e2SPeter Wemm }
4481c2aa98e2SPeter Wemm 
4482c2aa98e2SPeter Wemm /*
448306f25ae9SGregory Neil Shapiro **  LDAPMAP_FINDCONN -- find an LDAP connection to the server
448406f25ae9SGregory Neil Shapiro **
448506f25ae9SGregory Neil Shapiro **	Cache LDAP connections based on the host, port, bind DN,
448642e5d165SGregory Neil Shapiro **	secret, and PID so we don't have multiple connections open to
448742e5d165SGregory Neil Shapiro **	the same server for different maps.  Need a separate connection
448842e5d165SGregory Neil Shapiro **	per PID since a parent process may close the map before the
448942e5d165SGregory Neil Shapiro **	child is done with it.
449006f25ae9SGregory Neil Shapiro **
449106f25ae9SGregory Neil Shapiro **	Parameters:
449206f25ae9SGregory Neil Shapiro **		lmap -- LDAP map information
449306f25ae9SGregory Neil Shapiro **
449406f25ae9SGregory Neil Shapiro **	Returns:
449506f25ae9SGregory Neil Shapiro **		Symbol table entry for the LDAP connection.
4496c2aa98e2SPeter Wemm */
4497c2aa98e2SPeter Wemm 
449806f25ae9SGregory Neil Shapiro static STAB *
ldapmap_findconn(lmap)449906f25ae9SGregory Neil Shapiro ldapmap_findconn(lmap)
450040266059SGregory Neil Shapiro 	SM_LDAP_STRUCT *lmap;
4501c2aa98e2SPeter Wemm {
4502605302a5SGregory Neil Shapiro 	char *format;
450306f25ae9SGregory Neil Shapiro 	char *nbuf;
4504e92d3f3fSGregory Neil Shapiro 	char *id;
450540266059SGregory Neil Shapiro 	STAB *SM_NONVOLATILE s = NULL;
4506c2aa98e2SPeter Wemm 
4507e92d3f3fSGregory Neil Shapiro 	if (lmap->ldap_host != NULL)
4508e92d3f3fSGregory Neil Shapiro 		id = lmap->ldap_host;
4509e92d3f3fSGregory Neil Shapiro 	else if (lmap->ldap_uri != NULL)
4510e92d3f3fSGregory Neil Shapiro 		id = lmap->ldap_uri;
4511e92d3f3fSGregory Neil Shapiro 	else
4512e92d3f3fSGregory Neil Shapiro 		id = "localhost";
4513e92d3f3fSGregory Neil Shapiro 
4514605302a5SGregory Neil Shapiro 	format = "%s%c%d%c%d%c%s%c%s%d";
4515605302a5SGregory Neil Shapiro 	nbuf = sm_stringf_x(format,
4516e92d3f3fSGregory Neil Shapiro 			    id,
451706f25ae9SGregory Neil Shapiro 			    CONDELSE,
451806f25ae9SGregory Neil Shapiro 			    lmap->ldap_port,
451906f25ae9SGregory Neil Shapiro 			    CONDELSE,
4520605302a5SGregory Neil Shapiro 			    lmap->ldap_version,
4521605302a5SGregory Neil Shapiro 			    CONDELSE,
452240266059SGregory Neil Shapiro 			    (lmap->ldap_binddn == NULL ? ""
452340266059SGregory Neil Shapiro 						       : lmap->ldap_binddn),
452406f25ae9SGregory Neil Shapiro 			    CONDELSE,
452540266059SGregory Neil Shapiro 			    (lmap->ldap_secret == NULL ? ""
452640266059SGregory Neil Shapiro 						       : lmap->ldap_secret),
452740266059SGregory Neil Shapiro 			    (int) CurrentPid);
452840266059SGregory Neil Shapiro 	SM_TRY
45298774250cSGregory Neil Shapiro 		s = stab(nbuf, ST_LMAP, ST_ENTER);
453040266059SGregory Neil Shapiro 	SM_FINALLY
45318774250cSGregory Neil Shapiro 		sm_free(nbuf);
453240266059SGregory Neil Shapiro 	SM_END_TRY
453306f25ae9SGregory Neil Shapiro 	return s;
4534c2aa98e2SPeter Wemm }
453506f25ae9SGregory Neil Shapiro /*
453606f25ae9SGregory Neil Shapiro **  LDAPMAP_PARSEARGS -- parse ldap map definition args.
453706f25ae9SGregory Neil Shapiro */
453806f25ae9SGregory Neil Shapiro 
453940266059SGregory Neil Shapiro static struct lamvalues LDAPAuthMethods[] =
454006f25ae9SGregory Neil Shapiro {
454106f25ae9SGregory Neil Shapiro 	{	"none",		LDAP_AUTH_NONE		},
454206f25ae9SGregory Neil Shapiro 	{	"simple",	LDAP_AUTH_SIMPLE	},
454306f25ae9SGregory Neil Shapiro # ifdef LDAP_AUTH_KRBV4
454406f25ae9SGregory Neil Shapiro 	{	"krbv4",	LDAP_AUTH_KRBV4		},
45455b0945b5SGregory Neil Shapiro # endif
454606f25ae9SGregory Neil Shapiro 	{	NULL,		0			}
454706f25ae9SGregory Neil Shapiro };
454806f25ae9SGregory Neil Shapiro 
454940266059SGregory Neil Shapiro static struct ladvalues LDAPAliasDereference[] =
455006f25ae9SGregory Neil Shapiro {
455106f25ae9SGregory Neil Shapiro 	{	"never",	LDAP_DEREF_NEVER	},
455206f25ae9SGregory Neil Shapiro 	{	"always",	LDAP_DEREF_ALWAYS	},
455306f25ae9SGregory Neil Shapiro 	{	"search",	LDAP_DEREF_SEARCHING	},
455406f25ae9SGregory Neil Shapiro 	{	"find",		LDAP_DEREF_FINDING	},
455506f25ae9SGregory Neil Shapiro 	{	NULL,		0			}
455606f25ae9SGregory Neil Shapiro };
455706f25ae9SGregory Neil Shapiro 
455840266059SGregory Neil Shapiro static struct lssvalues LDAPSearchScope[] =
455906f25ae9SGregory Neil Shapiro {
456006f25ae9SGregory Neil Shapiro 	{	"base",		LDAP_SCOPE_BASE		},
456106f25ae9SGregory Neil Shapiro 	{	"one",		LDAP_SCOPE_ONELEVEL	},
456206f25ae9SGregory Neil Shapiro 	{	"sub",		LDAP_SCOPE_SUBTREE	},
456306f25ae9SGregory Neil Shapiro 	{	NULL,		0			}
456406f25ae9SGregory Neil Shapiro };
456506f25ae9SGregory Neil Shapiro 
456606f25ae9SGregory Neil Shapiro bool
ldapmap_parseargs(map,args)456706f25ae9SGregory Neil Shapiro ldapmap_parseargs(map, args)
456806f25ae9SGregory Neil Shapiro 	MAP *map;
456906f25ae9SGregory Neil Shapiro 	char *args;
457006f25ae9SGregory Neil Shapiro {
457140266059SGregory Neil Shapiro 	bool secretread = true;
4572e92d3f3fSGregory Neil Shapiro 	bool attrssetup = false;
457306f25ae9SGregory Neil Shapiro 	int i;
4574c2aa98e2SPeter Wemm 	register char *p = args;
457540266059SGregory Neil Shapiro 	SM_LDAP_STRUCT *lmap;
45762fb4f839SGregory Neil Shapiro 	SM_LDAP_STRUCT *lmap_alloc;
457706f25ae9SGregory Neil Shapiro 	struct lamvalues *lam;
457806f25ae9SGregory Neil Shapiro 	struct ladvalues *lad;
457906f25ae9SGregory Neil Shapiro 	struct lssvalues *lss;
458040266059SGregory Neil Shapiro 	char ldapfilt[MAXLINE];
458106f25ae9SGregory Neil Shapiro 	char m_tmp[MAXPATHLEN + LDAPMAP_MAX_PASSWD];
458206f25ae9SGregory Neil Shapiro 
458306f25ae9SGregory Neil Shapiro 	/* Get ldap struct pointer from map */
458440266059SGregory Neil Shapiro 	lmap = (SM_LDAP_STRUCT *) map->map_db1;
458506f25ae9SGregory Neil Shapiro 
458606f25ae9SGregory Neil Shapiro 	/* Check if setting the initial LDAP defaults */
458706f25ae9SGregory Neil Shapiro 	if (lmap == NULL || lmap != LDAPDefaults)
458806f25ae9SGregory Neil Shapiro 	{
458940266059SGregory Neil Shapiro 		/* We need to alloc an SM_LDAP_STRUCT struct */
45902fb4f839SGregory Neil Shapiro 		lmap_alloc = lmap = (SM_LDAP_STRUCT *) xalloc(sizeof(*lmap));
459106f25ae9SGregory Neil Shapiro 		if (LDAPDefaults == NULL)
459240266059SGregory Neil Shapiro 			sm_ldap_clear(lmap);
459306f25ae9SGregory Neil Shapiro 		else
459406f25ae9SGregory Neil Shapiro 			STRUCTCOPY(*LDAPDefaults, *lmap);
459506f25ae9SGregory Neil Shapiro 	}
45962fb4f839SGregory Neil Shapiro 	else
45972fb4f839SGregory Neil Shapiro 		lmap_alloc = NULL;
459806f25ae9SGregory Neil Shapiro 
459906f25ae9SGregory Neil Shapiro 	/* there is no check whether there is really an argument */
460006f25ae9SGregory Neil Shapiro 	map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL;
460106f25ae9SGregory Neil Shapiro 	map->map_spacesub = SpaceSub;	/* default value */
460240266059SGregory Neil Shapiro 
460340266059SGregory Neil Shapiro 	/* Check if setting up an alias or file class LDAP map */
460440266059SGregory Neil Shapiro 	if (bitset(MF_ALIAS, map->map_mflags))
460540266059SGregory Neil Shapiro 	{
460640266059SGregory Neil Shapiro 		/* Comma separate if used as an alias file */
460740266059SGregory Neil Shapiro 		map->map_coldelim = ',';
460840266059SGregory Neil Shapiro 		if (*args == '\0')
460940266059SGregory Neil Shapiro 		{
461040266059SGregory Neil Shapiro 			int n;
461140266059SGregory Neil Shapiro 			char *lc;
461240266059SGregory Neil Shapiro 			char jbuf[MAXHOSTNAMELEN];
461340266059SGregory Neil Shapiro 			char lcbuf[MAXLINE];
461440266059SGregory Neil Shapiro 
461540266059SGregory Neil Shapiro 			/* Get $j */
4616d0cef73dSGregory Neil Shapiro 			expand("\201j", jbuf, sizeof(jbuf), &BlankEnvelope);
461740266059SGregory Neil Shapiro 			if (jbuf[0] == '\0')
461840266059SGregory Neil Shapiro 			{
461940266059SGregory Neil Shapiro 				(void) sm_strlcpy(jbuf, "localhost",
4620d0cef73dSGregory Neil Shapiro 						  sizeof(jbuf));
462140266059SGregory Neil Shapiro 			}
462240266059SGregory Neil Shapiro 
462340266059SGregory Neil Shapiro 			lc = macvalue(macid("{sendmailMTACluster}"), CurEnv);
462440266059SGregory Neil Shapiro 			if (lc == NULL)
462540266059SGregory Neil Shapiro 				lc = "";
462640266059SGregory Neil Shapiro 			else
462740266059SGregory Neil Shapiro 			{
4628d0cef73dSGregory Neil Shapiro 				expand(lc, lcbuf, sizeof(lcbuf), CurEnv);
462940266059SGregory Neil Shapiro 				lc = lcbuf;
463040266059SGregory Neil Shapiro 			}
463140266059SGregory Neil Shapiro 
4632d0cef73dSGregory Neil Shapiro 			n = sm_snprintf(ldapfilt, sizeof(ldapfilt),
463340266059SGregory Neil Shapiro 					"(&(objectClass=sendmailMTAAliasObject)(sendmailMTAAliasGrouping=aliases)(|(sendmailMTACluster=%s)(sendmailMTAHost=%s))(sendmailMTAKey=%%0))",
463440266059SGregory Neil Shapiro 					lc, jbuf);
4635d0cef73dSGregory Neil Shapiro 			if (n >= sizeof(ldapfilt))
463640266059SGregory Neil Shapiro 			{
463740266059SGregory Neil Shapiro 				syserr("%s: Default LDAP string too long",
463840266059SGregory Neil Shapiro 				       map->map_mname);
46392fb4f839SGregory Neil Shapiro 				goto fail;
464040266059SGregory Neil Shapiro 			}
464140266059SGregory Neil Shapiro 
464240266059SGregory Neil Shapiro 			/* default args for an alias LDAP entry */
464340266059SGregory Neil Shapiro 			lmap->ldap_filter = ldapfilt;
4644e92d3f3fSGregory Neil Shapiro 			lmap->ldap_attr[0] = "objectClass";
4645e92d3f3fSGregory Neil Shapiro 			lmap->ldap_attr_type[0] = SM_LDAP_ATTR_OBJCLASS;
4646e92d3f3fSGregory Neil Shapiro 			lmap->ldap_attr_needobjclass[0] = NULL;
4647e92d3f3fSGregory Neil Shapiro 			lmap->ldap_attr[1] = "sendmailMTAAliasValue";
4648e92d3f3fSGregory Neil Shapiro 			lmap->ldap_attr_type[1] = SM_LDAP_ATTR_NORMAL;
4649e92d3f3fSGregory Neil Shapiro 			lmap->ldap_attr_needobjclass[1] = NULL;
4650e92d3f3fSGregory Neil Shapiro 			lmap->ldap_attr[2] = "sendmailMTAAliasSearch";
4651e92d3f3fSGregory Neil Shapiro 			lmap->ldap_attr_type[2] = SM_LDAP_ATTR_FILTER;
4652e92d3f3fSGregory Neil Shapiro 			lmap->ldap_attr_needobjclass[2] = "sendmailMTAMapObject";
4653e92d3f3fSGregory Neil Shapiro 			lmap->ldap_attr[3] = "sendmailMTAAliasURL";
4654e92d3f3fSGregory Neil Shapiro 			lmap->ldap_attr_type[3] = SM_LDAP_ATTR_URL;
4655e92d3f3fSGregory Neil Shapiro 			lmap->ldap_attr_needobjclass[3] = "sendmailMTAMapObject";
4656e92d3f3fSGregory Neil Shapiro 			lmap->ldap_attr[4] = NULL;
4657e92d3f3fSGregory Neil Shapiro 			lmap->ldap_attr_type[4] = SM_LDAP_ATTR_NONE;
4658e92d3f3fSGregory Neil Shapiro 			lmap->ldap_attr_needobjclass[4] = NULL;
4659e92d3f3fSGregory Neil Shapiro 			attrssetup = true;
466040266059SGregory Neil Shapiro 		}
466140266059SGregory Neil Shapiro 	}
466240266059SGregory Neil Shapiro 	else if (bitset(MF_FILECLASS, map->map_mflags))
466340266059SGregory Neil Shapiro 	{
466440266059SGregory Neil Shapiro 		/* Space separate if used as a file class file */
466540266059SGregory Neil Shapiro 		map->map_coldelim = ' ';
466640266059SGregory Neil Shapiro 	}
466740266059SGregory Neil Shapiro 
46685b0945b5SGregory Neil Shapiro # if LDAP_NETWORK_TIMEOUT
46695b0945b5SGregory Neil Shapiro 	if (0 == lmap->ldap_networktmo)
46705b0945b5SGregory Neil Shapiro 		lmap->ldap_networktmo = (LDAP_NETWORK_TIMEOUT > 1)
46715b0945b5SGregory Neil Shapiro 					? LDAP_NETWORK_TIMEOUT : 60;
46725b0945b5SGregory Neil Shapiro # endif
46739bd497b8SGregory Neil Shapiro 
467406f25ae9SGregory Neil Shapiro 	for (;;)
467506f25ae9SGregory Neil Shapiro 	{
46765b0945b5SGregory Neil Shapiro 		while (SM_ISSPACE(*p))
467706f25ae9SGregory Neil Shapiro 			p++;
467806f25ae9SGregory Neil Shapiro 		if (*p != '-')
467906f25ae9SGregory Neil Shapiro 			break;
468006f25ae9SGregory Neil Shapiro 		switch (*++p)
468106f25ae9SGregory Neil Shapiro 		{
4682ffb83623SGregory Neil Shapiro 		  case 'A':
4683ffb83623SGregory Neil Shapiro 			map->map_mflags |= MF_APPEND;
4684ffb83623SGregory Neil Shapiro 			break;
4685ffb83623SGregory Neil Shapiro 
4686ffb83623SGregory Neil Shapiro 		  case 'a':
4687ffb83623SGregory Neil Shapiro 			map->map_app = ++p;
4688ffb83623SGregory Neil Shapiro 			break;
4689ffb83623SGregory Neil Shapiro 
4690ffb83623SGregory Neil Shapiro 		  case 'D':
4691ffb83623SGregory Neil Shapiro 			map->map_mflags |= MF_DEFER;
4692ffb83623SGregory Neil Shapiro 			break;
4693ffb83623SGregory Neil Shapiro 
4694ffb83623SGregory Neil Shapiro 		  case 'f':
4695ffb83623SGregory Neil Shapiro 			map->map_mflags |= MF_NOFOLDCASE;
4696ffb83623SGregory Neil Shapiro 			break;
4697ffb83623SGregory Neil Shapiro 
4698ffb83623SGregory Neil Shapiro 		  case 'm':
4699ffb83623SGregory Neil Shapiro 			map->map_mflags |= MF_MATCHONLY;
4700ffb83623SGregory Neil Shapiro 			break;
4701ffb83623SGregory Neil Shapiro 
470206f25ae9SGregory Neil Shapiro 		  case 'N':
470306f25ae9SGregory Neil Shapiro 			map->map_mflags |= MF_INCLNULL;
470406f25ae9SGregory Neil Shapiro 			map->map_mflags &= ~MF_TRY0NULL;
470506f25ae9SGregory Neil Shapiro 			break;
470606f25ae9SGregory Neil Shapiro 
470706f25ae9SGregory Neil Shapiro 		  case 'O':
470806f25ae9SGregory Neil Shapiro 			map->map_mflags &= ~MF_TRY1NULL;
470906f25ae9SGregory Neil Shapiro 			break;
471006f25ae9SGregory Neil Shapiro 
471106f25ae9SGregory Neil Shapiro 		  case 'o':
471206f25ae9SGregory Neil Shapiro 			map->map_mflags |= MF_OPTIONAL;
471306f25ae9SGregory Neil Shapiro 			break;
471406f25ae9SGregory Neil Shapiro 
471506f25ae9SGregory Neil Shapiro 		  case 'q':
471606f25ae9SGregory Neil Shapiro 			map->map_mflags |= MF_KEEPQUOTES;
471706f25ae9SGregory Neil Shapiro 			break;
471806f25ae9SGregory Neil Shapiro 
4719ffb83623SGregory Neil Shapiro 		  case 'S':
4720ffb83623SGregory Neil Shapiro 			map->map_spacesub = *++p;
472106f25ae9SGregory Neil Shapiro 			break;
472206f25ae9SGregory Neil Shapiro 
472306f25ae9SGregory Neil Shapiro 		  case 'T':
472406f25ae9SGregory Neil Shapiro 			map->map_tapp = ++p;
472506f25ae9SGregory Neil Shapiro 			break;
472606f25ae9SGregory Neil Shapiro 
472706f25ae9SGregory Neil Shapiro 		  case 't':
472806f25ae9SGregory Neil Shapiro 			map->map_mflags |= MF_NODEFER;
472906f25ae9SGregory Neil Shapiro 			break;
473006f25ae9SGregory Neil Shapiro 
473106f25ae9SGregory Neil Shapiro 		  case 'z':
473206f25ae9SGregory Neil Shapiro 			if (*++p != '\\')
473306f25ae9SGregory Neil Shapiro 				map->map_coldelim = *p;
473406f25ae9SGregory Neil Shapiro 			else
473506f25ae9SGregory Neil Shapiro 			{
473606f25ae9SGregory Neil Shapiro 				switch (*++p)
473706f25ae9SGregory Neil Shapiro 				{
473806f25ae9SGregory Neil Shapiro 				  case 'n':
473906f25ae9SGregory Neil Shapiro 					map->map_coldelim = '\n';
474006f25ae9SGregory Neil Shapiro 					break;
474106f25ae9SGregory Neil Shapiro 
474206f25ae9SGregory Neil Shapiro 				  case 't':
474306f25ae9SGregory Neil Shapiro 					map->map_coldelim = '\t';
474406f25ae9SGregory Neil Shapiro 					break;
474506f25ae9SGregory Neil Shapiro 
474606f25ae9SGregory Neil Shapiro 				  default:
474706f25ae9SGregory Neil Shapiro 					map->map_coldelim = '\\';
474806f25ae9SGregory Neil Shapiro 				}
474906f25ae9SGregory Neil Shapiro 			}
475006f25ae9SGregory Neil Shapiro 			break;
475106f25ae9SGregory Neil Shapiro 
475206f25ae9SGregory Neil Shapiro 			/* Start of ldapmap specific args */
475306f25ae9SGregory Neil Shapiro 		  case '1':
475406f25ae9SGregory Neil Shapiro 			map->map_mflags |= MF_SINGLEMATCH;
475506f25ae9SGregory Neil Shapiro 			break;
475606f25ae9SGregory Neil Shapiro 
47574e4196cbSGregory Neil Shapiro # if _FFR_LDAP_SINGLEDN
47584e4196cbSGregory Neil Shapiro 		  case '2':
47594e4196cbSGregory Neil Shapiro 			map->map_mflags |= MF_SINGLEDN;
47604e4196cbSGregory Neil Shapiro 			break;
47614e4196cbSGregory Neil Shapiro # endif /* _FFR_LDAP_SINGLEDN */
47624e4196cbSGregory Neil Shapiro 
4763ffb83623SGregory Neil Shapiro 		  case 'b':		/* search base */
4764ffb83623SGregory Neil Shapiro 			while (isascii(*++p) && isspace(*p))
4765ffb83623SGregory Neil Shapiro 				continue;
4766ffb83623SGregory Neil Shapiro 			lmap->ldap_base = p;
4767ffb83623SGregory Neil Shapiro 			break;
4768ffb83623SGregory Neil Shapiro 
47695b0945b5SGregory Neil Shapiro # if LDAP_NETWORK_TIMEOUT
4770ffb83623SGregory Neil Shapiro 		  case 'c':		/* network (connect) timeout */
4771ffb83623SGregory Neil Shapiro 			while (isascii(*++p) && isspace(*p))
4772ffb83623SGregory Neil Shapiro 				continue;
47739bd497b8SGregory Neil Shapiro 			lmap->ldap_networktmo = atoi(p);
4774ffb83623SGregory Neil Shapiro 			break;
47755b0945b5SGregory Neil Shapiro # endif /* LDAP_NETWORK_TIMEOUT */
4776ffb83623SGregory Neil Shapiro 
4777ffb83623SGregory Neil Shapiro 		  case 'd':		/* Dn to bind to server as */
4778ffb83623SGregory Neil Shapiro 			while (isascii(*++p) && isspace(*p))
4779ffb83623SGregory Neil Shapiro 				continue;
4780ffb83623SGregory Neil Shapiro 			lmap->ldap_binddn = p;
4781ffb83623SGregory Neil Shapiro 			break;
4782ffb83623SGregory Neil Shapiro 
4783ffb83623SGregory Neil Shapiro 		  case 'H':		/* Use LDAP URI */
4784ffb83623SGregory Neil Shapiro # if !USE_LDAP_INIT
4785ffb83623SGregory Neil Shapiro 			syserr("Must compile with -DUSE_LDAP_INIT to use LDAP URIs (-H) in map %s",
4786ffb83623SGregory Neil Shapiro 			       map->map_mname);
47872fb4f839SGregory Neil Shapiro 			goto fail;
4788ffb83623SGregory Neil Shapiro # else /* !USE_LDAP_INIT */
4789ffb83623SGregory Neil Shapiro 			if (lmap->ldap_host != NULL)
4790ffb83623SGregory Neil Shapiro 			{
4791ffb83623SGregory Neil Shapiro 				syserr("Can not specify both an LDAP host and an LDAP URI in map %s",
4792ffb83623SGregory Neil Shapiro 				       map->map_mname);
47932fb4f839SGregory Neil Shapiro 				goto fail;
4794ffb83623SGregory Neil Shapiro 			}
4795ffb83623SGregory Neil Shapiro 			while (isascii(*++p) && isspace(*p))
4796ffb83623SGregory Neil Shapiro 				continue;
4797ffb83623SGregory Neil Shapiro 			lmap->ldap_uri = p;
4798ffb83623SGregory Neil Shapiro 			break;
4799ffb83623SGregory Neil Shapiro # endif /* !USE_LDAP_INIT */
4800ffb83623SGregory Neil Shapiro 
4801ffb83623SGregory Neil Shapiro 		  case 'h':		/* ldap host */
4802ffb83623SGregory Neil Shapiro 			while (isascii(*++p) && isspace(*p))
4803ffb83623SGregory Neil Shapiro 				continue;
4804ffb83623SGregory Neil Shapiro 			if (lmap->ldap_uri != NULL)
4805ffb83623SGregory Neil Shapiro 			{
4806ffb83623SGregory Neil Shapiro 				syserr("Can not specify both an LDAP host and an LDAP URI in map %s",
4807ffb83623SGregory Neil Shapiro 				       map->map_mname);
48082fb4f839SGregory Neil Shapiro 				goto fail;
4809ffb83623SGregory Neil Shapiro 			}
4810ffb83623SGregory Neil Shapiro 			lmap->ldap_host = p;
4811ffb83623SGregory Neil Shapiro 			break;
4812ffb83623SGregory Neil Shapiro 
4813ffb83623SGregory Neil Shapiro 		  case 'K':
4814ffb83623SGregory Neil Shapiro 			lmap->ldap_multi_args = true;
4815ffb83623SGregory Neil Shapiro 			break;
4816ffb83623SGregory Neil Shapiro 
4817ffb83623SGregory Neil Shapiro 		  case 'k':		/* search field */
4818ffb83623SGregory Neil Shapiro 			while (isascii(*++p) && isspace(*p))
4819ffb83623SGregory Neil Shapiro 				continue;
4820ffb83623SGregory Neil Shapiro 			lmap->ldap_filter = p;
4821ffb83623SGregory Neil Shapiro 			break;
4822ffb83623SGregory Neil Shapiro 
4823ffb83623SGregory Neil Shapiro 		  case 'l':		/* time limit */
4824ffb83623SGregory Neil Shapiro 			while (isascii(*++p) && isspace(*p))
4825ffb83623SGregory Neil Shapiro 				continue;
4826ffb83623SGregory Neil Shapiro 			lmap->ldap_timelimit = atoi(p);
4827ffb83623SGregory Neil Shapiro 			lmap->ldap_timeout.tv_sec = lmap->ldap_timelimit;
4828ffb83623SGregory Neil Shapiro 			break;
4829ffb83623SGregory Neil Shapiro 
4830ffb83623SGregory Neil Shapiro 		  case 'M':		/* Method for binding */
4831ffb83623SGregory Neil Shapiro 			while (isascii(*++p) && isspace(*p))
4832ffb83623SGregory Neil Shapiro 				continue;
4833ffb83623SGregory Neil Shapiro 
4834ffb83623SGregory Neil Shapiro 			if (sm_strncasecmp(p, "LDAP_AUTH_", 10) == 0)
4835ffb83623SGregory Neil Shapiro 				p += 10;
4836ffb83623SGregory Neil Shapiro 
4837ffb83623SGregory Neil Shapiro 			for (lam = LDAPAuthMethods;
4838ffb83623SGregory Neil Shapiro 			     lam != NULL && lam->lam_name != NULL; lam++)
4839ffb83623SGregory Neil Shapiro 			{
4840ffb83623SGregory Neil Shapiro 				if (sm_strncasecmp(p, lam->lam_name,
4841ffb83623SGregory Neil Shapiro 						   strlen(lam->lam_name)) == 0)
4842ffb83623SGregory Neil Shapiro 					break;
4843ffb83623SGregory Neil Shapiro 			}
4844ffb83623SGregory Neil Shapiro 			if (lam->lam_name != NULL)
4845ffb83623SGregory Neil Shapiro 				lmap->ldap_method = lam->lam_code;
4846ffb83623SGregory Neil Shapiro 			else
4847ffb83623SGregory Neil Shapiro 			{
4848ffb83623SGregory Neil Shapiro 				/* bad config line */
4849ffb83623SGregory Neil Shapiro 				if (!bitset(MCF_OPTFILE,
4850ffb83623SGregory Neil Shapiro 					    map->map_class->map_cflags))
4851ffb83623SGregory Neil Shapiro 				{
4852ffb83623SGregory Neil Shapiro 					char *ptr;
4853ffb83623SGregory Neil Shapiro 
4854ffb83623SGregory Neil Shapiro 					if ((ptr = strchr(p, ' ')) != NULL)
4855ffb83623SGregory Neil Shapiro 						*ptr = '\0';
4856ffb83623SGregory Neil Shapiro 					syserr("Method for binding must be [none|simple|krbv4] (not %s) in map %s",
4857ffb83623SGregory Neil Shapiro 						p, map->map_mname);
4858ffb83623SGregory Neil Shapiro 					if (ptr != NULL)
4859ffb83623SGregory Neil Shapiro 						*ptr = ' ';
48602fb4f839SGregory Neil Shapiro 					goto fail;
4861ffb83623SGregory Neil Shapiro 				}
4862ffb83623SGregory Neil Shapiro 			}
4863ffb83623SGregory Neil Shapiro 			break;
4864ffb83623SGregory Neil Shapiro 
4865ffb83623SGregory Neil Shapiro 		  case 'n':		/* retrieve attribute names only */
4866ffb83623SGregory Neil Shapiro 			lmap->ldap_attrsonly = LDAPMAP_TRUE;
4867ffb83623SGregory Neil Shapiro 			break;
4868ffb83623SGregory Neil Shapiro 
4869ffb83623SGregory Neil Shapiro 			/*
4870ffb83623SGregory Neil Shapiro 			**  This is a string that is dependent on the
4871ffb83623SGregory Neil Shapiro 			**  method used defined by 'M'.
4872ffb83623SGregory Neil Shapiro 			*/
4873ffb83623SGregory Neil Shapiro 
4874ffb83623SGregory Neil Shapiro 		  case 'P':		/* Secret password for binding */
4875ffb83623SGregory Neil Shapiro 			 while (isascii(*++p) && isspace(*p))
4876ffb83623SGregory Neil Shapiro 				continue;
4877ffb83623SGregory Neil Shapiro 			lmap->ldap_secret = p;
4878ffb83623SGregory Neil Shapiro 			secretread = false;
4879ffb83623SGregory Neil Shapiro 			break;
4880ffb83623SGregory Neil Shapiro 
4881ffb83623SGregory Neil Shapiro 		  case 'p':		/* ldap port */
4882ffb83623SGregory Neil Shapiro 			while (isascii(*++p) && isspace(*p))
4883ffb83623SGregory Neil Shapiro 				continue;
4884ffb83623SGregory Neil Shapiro 			lmap->ldap_port = atoi(p);
4885ffb83623SGregory Neil Shapiro 			break;
4886ffb83623SGregory Neil Shapiro 
488706f25ae9SGregory Neil Shapiro 			/* args stolen from ldapsearch.c */
488806f25ae9SGregory Neil Shapiro 		  case 'R':		/* don't auto chase referrals */
488906f25ae9SGregory Neil Shapiro # ifdef LDAP_REFERRALS
489006f25ae9SGregory Neil Shapiro 			lmap->ldap_options &= ~LDAP_OPT_REFERRALS;
48915b0945b5SGregory Neil Shapiro # else
489240266059SGregory Neil Shapiro 			syserr("compile with -DLDAP_REFERRALS for referral support");
489306f25ae9SGregory Neil Shapiro # endif /* LDAP_REFERRALS */
489406f25ae9SGregory Neil Shapiro 			break;
489506f25ae9SGregory Neil Shapiro 
489606f25ae9SGregory Neil Shapiro 		  case 'r':		/* alias dereferencing */
489706f25ae9SGregory Neil Shapiro 			while (isascii(*++p) && isspace(*p))
489806f25ae9SGregory Neil Shapiro 				continue;
489906f25ae9SGregory Neil Shapiro 
490040266059SGregory Neil Shapiro 			if (sm_strncasecmp(p, "LDAP_DEREF_", 11) == 0)
490106f25ae9SGregory Neil Shapiro 				p += 11;
490206f25ae9SGregory Neil Shapiro 
490306f25ae9SGregory Neil Shapiro 			for (lad = LDAPAliasDereference;
490406f25ae9SGregory Neil Shapiro 			     lad != NULL && lad->lad_name != NULL; lad++)
490506f25ae9SGregory Neil Shapiro 			{
490640266059SGregory Neil Shapiro 				if (sm_strncasecmp(p, lad->lad_name,
490706f25ae9SGregory Neil Shapiro 						   strlen(lad->lad_name)) == 0)
490806f25ae9SGregory Neil Shapiro 					break;
490906f25ae9SGregory Neil Shapiro 			}
491006f25ae9SGregory Neil Shapiro 			if (lad->lad_name != NULL)
491106f25ae9SGregory Neil Shapiro 				lmap->ldap_deref = lad->lad_code;
491206f25ae9SGregory Neil Shapiro 			else
491306f25ae9SGregory Neil Shapiro 			{
491406f25ae9SGregory Neil Shapiro 				/* bad config line */
491506f25ae9SGregory Neil Shapiro 				if (!bitset(MCF_OPTFILE,
491606f25ae9SGregory Neil Shapiro 					    map->map_class->map_cflags))
491706f25ae9SGregory Neil Shapiro 				{
491806f25ae9SGregory Neil Shapiro 					char *ptr;
491906f25ae9SGregory Neil Shapiro 
492006f25ae9SGregory Neil Shapiro 					if ((ptr = strchr(p, ' ')) != NULL)
492106f25ae9SGregory Neil Shapiro 						*ptr = '\0';
4922602a2b1bSGregory Neil Shapiro 					syserr("Deref must be [never|always|search|find] (not %s) in map %s",
492306f25ae9SGregory Neil Shapiro 						p, map->map_mname);
492406f25ae9SGregory Neil Shapiro 					if (ptr != NULL)
492506f25ae9SGregory Neil Shapiro 						*ptr = ' ';
49262fb4f839SGregory Neil Shapiro 					goto fail;
492706f25ae9SGregory Neil Shapiro 				}
492806f25ae9SGregory Neil Shapiro 			}
492906f25ae9SGregory Neil Shapiro 			break;
493006f25ae9SGregory Neil Shapiro 
493106f25ae9SGregory Neil Shapiro 		  case 's':		/* search scope */
493206f25ae9SGregory Neil Shapiro 			while (isascii(*++p) && isspace(*p))
493306f25ae9SGregory Neil Shapiro 				continue;
493406f25ae9SGregory Neil Shapiro 
493540266059SGregory Neil Shapiro 			if (sm_strncasecmp(p, "LDAP_SCOPE_", 11) == 0)
493606f25ae9SGregory Neil Shapiro 				p += 11;
493706f25ae9SGregory Neil Shapiro 
493806f25ae9SGregory Neil Shapiro 			for (lss = LDAPSearchScope;
493906f25ae9SGregory Neil Shapiro 			     lss != NULL && lss->lss_name != NULL; lss++)
494006f25ae9SGregory Neil Shapiro 			{
494140266059SGregory Neil Shapiro 				if (sm_strncasecmp(p, lss->lss_name,
494206f25ae9SGregory Neil Shapiro 						   strlen(lss->lss_name)) == 0)
494306f25ae9SGregory Neil Shapiro 					break;
494406f25ae9SGregory Neil Shapiro 			}
494506f25ae9SGregory Neil Shapiro 			if (lss->lss_name != NULL)
494606f25ae9SGregory Neil Shapiro 				lmap->ldap_scope = lss->lss_code;
494706f25ae9SGregory Neil Shapiro 			else
494806f25ae9SGregory Neil Shapiro 			{
494906f25ae9SGregory Neil Shapiro 				/* bad config line */
495006f25ae9SGregory Neil Shapiro 				if (!bitset(MCF_OPTFILE,
495106f25ae9SGregory Neil Shapiro 					    map->map_class->map_cflags))
495206f25ae9SGregory Neil Shapiro 				{
495306f25ae9SGregory Neil Shapiro 					char *ptr;
495406f25ae9SGregory Neil Shapiro 
495506f25ae9SGregory Neil Shapiro 					if ((ptr = strchr(p, ' ')) != NULL)
495606f25ae9SGregory Neil Shapiro 						*ptr = '\0';
4957602a2b1bSGregory Neil Shapiro 					syserr("Scope must be [base|one|sub] (not %s) in map %s",
495806f25ae9SGregory Neil Shapiro 						p, map->map_mname);
495906f25ae9SGregory Neil Shapiro 					if (ptr != NULL)
496006f25ae9SGregory Neil Shapiro 						*ptr = ' ';
49612fb4f839SGregory Neil Shapiro 					goto fail;
496206f25ae9SGregory Neil Shapiro 				}
496306f25ae9SGregory Neil Shapiro 			}
496406f25ae9SGregory Neil Shapiro 			break;
496506f25ae9SGregory Neil Shapiro 
4966ffb83623SGregory Neil Shapiro 		  case 'V':
4967ffb83623SGregory Neil Shapiro 			if (*++p != '\\')
4968ffb83623SGregory Neil Shapiro 				lmap->ldap_attrsep = *p;
496906f25ae9SGregory Neil Shapiro 			else
497006f25ae9SGregory Neil Shapiro 			{
4971ffb83623SGregory Neil Shapiro 				switch (*++p)
497206f25ae9SGregory Neil Shapiro 				{
4973ffb83623SGregory Neil Shapiro 				  case 'n':
4974ffb83623SGregory Neil Shapiro 					lmap->ldap_attrsep = '\n';
497506f25ae9SGregory Neil Shapiro 					break;
497606f25ae9SGregory Neil Shapiro 
4977ffb83623SGregory Neil Shapiro 				  case 't':
4978ffb83623SGregory Neil Shapiro 					lmap->ldap_attrsep = '\t';
4979ffb83623SGregory Neil Shapiro 					break;
498006f25ae9SGregory Neil Shapiro 
4981ffb83623SGregory Neil Shapiro 				  default:
4982ffb83623SGregory Neil Shapiro 					lmap->ldap_attrsep = '\\';
4983ffb83623SGregory Neil Shapiro 				}
4984ffb83623SGregory Neil Shapiro 			}
4985ffb83623SGregory Neil Shapiro 			break;
4986ffb83623SGregory Neil Shapiro 
4987ffb83623SGregory Neil Shapiro 		  case 'v':		/* attr to return */
498806f25ae9SGregory Neil Shapiro 			while (isascii(*++p) && isspace(*p))
498906f25ae9SGregory Neil Shapiro 				continue;
4990ffb83623SGregory Neil Shapiro 			lmap->ldap_attr[0] = p;
4991ffb83623SGregory Neil Shapiro 			lmap->ldap_attr[1] = NULL;
499206f25ae9SGregory Neil Shapiro 			break;
499306f25ae9SGregory Neil Shapiro 
4994605302a5SGregory Neil Shapiro 		  case 'w':
4995605302a5SGregory Neil Shapiro 			/* -w should be for passwd, -P should be for version */
4996605302a5SGregory Neil Shapiro 			while (isascii(*++p) && isspace(*p))
4997605302a5SGregory Neil Shapiro 				continue;
4998605302a5SGregory Neil Shapiro 			lmap->ldap_version = atoi(p);
4999605302a5SGregory Neil Shapiro # ifdef LDAP_VERSION_MAX
5000605302a5SGregory Neil Shapiro 			if (lmap->ldap_version > LDAP_VERSION_MAX)
5001605302a5SGregory Neil Shapiro 			{
5002605302a5SGregory Neil Shapiro 				syserr("LDAP version %d exceeds max of %d in map %s",
5003605302a5SGregory Neil Shapiro 				       lmap->ldap_version, LDAP_VERSION_MAX,
5004605302a5SGregory Neil Shapiro 				       map->map_mname);
50052fb4f839SGregory Neil Shapiro 				goto fail;
5006605302a5SGregory Neil Shapiro 			}
5007605302a5SGregory Neil Shapiro # endif /* LDAP_VERSION_MAX */
5008605302a5SGregory Neil Shapiro # ifdef LDAP_VERSION_MIN
5009605302a5SGregory Neil Shapiro 			if (lmap->ldap_version < LDAP_VERSION_MIN)
5010605302a5SGregory Neil Shapiro 			{
5011605302a5SGregory Neil Shapiro 				syserr("LDAP version %d is lower than min of %d in map %s",
5012605302a5SGregory Neil Shapiro 				       lmap->ldap_version, LDAP_VERSION_MIN,
5013605302a5SGregory Neil Shapiro 				       map->map_mname);
50142fb4f839SGregory Neil Shapiro 				goto fail;
5015605302a5SGregory Neil Shapiro 			}
5016605302a5SGregory Neil Shapiro # endif /* LDAP_VERSION_MIN */
5017605302a5SGregory Neil Shapiro 			break;
5018605302a5SGregory Neil Shapiro 
50195b0945b5SGregory Neil Shapiro 		  case 'x':
50205b0945b5SGregory Neil Shapiro # if _FFR_SM_LDAP_DBG
50215b0945b5SGregory Neil Shapiro 			while (isascii(*++p) && isspace(*p))
50225b0945b5SGregory Neil Shapiro 				continue;
50235b0945b5SGregory Neil Shapiro 			lmap->ldap_debug = atoi(p);
50245b0945b5SGregory Neil Shapiro # endif
50255b0945b5SGregory Neil Shapiro 			break;
50265b0945b5SGregory Neil Shapiro 
5027ffb83623SGregory Neil Shapiro 		  case 'Z':
5028ffb83623SGregory Neil Shapiro 			while (isascii(*++p) && isspace(*p))
5029ffb83623SGregory Neil Shapiro 				continue;
5030ffb83623SGregory Neil Shapiro 			lmap->ldap_sizelimit = atoi(p);
5031d0cef73dSGregory Neil Shapiro 			break;
5032d0cef73dSGregory Neil Shapiro 
503306f25ae9SGregory Neil Shapiro 		  default:
503406f25ae9SGregory Neil Shapiro 			syserr("Illegal option %c map %s", *p, map->map_mname);
503506f25ae9SGregory Neil Shapiro 			break;
503606f25ae9SGregory Neil Shapiro 		}
503706f25ae9SGregory Neil Shapiro 
503806f25ae9SGregory Neil Shapiro 		/* need to account for quoted strings here */
50395b0945b5SGregory Neil Shapiro 		while (*p != '\0' && !(SM_ISSPACE(*p)))
504006f25ae9SGregory Neil Shapiro 		{
504106f25ae9SGregory Neil Shapiro 			if (*p == '"')
504206f25ae9SGregory Neil Shapiro 			{
504306f25ae9SGregory Neil Shapiro 				while (*++p != '"' && *p != '\0')
504406f25ae9SGregory Neil Shapiro 					continue;
504506f25ae9SGregory Neil Shapiro 				if (*p != '\0')
504606f25ae9SGregory Neil Shapiro 					p++;
504706f25ae9SGregory Neil Shapiro 			}
504806f25ae9SGregory Neil Shapiro 			else
504906f25ae9SGregory Neil Shapiro 				p++;
505006f25ae9SGregory Neil Shapiro 		}
505106f25ae9SGregory Neil Shapiro 
505206f25ae9SGregory Neil Shapiro 		if (*p != '\0')
505306f25ae9SGregory Neil Shapiro 			*p++ = '\0';
505406f25ae9SGregory Neil Shapiro 	}
505506f25ae9SGregory Neil Shapiro 
505606f25ae9SGregory Neil Shapiro 	if (map->map_app != NULL)
505706f25ae9SGregory Neil Shapiro 		map->map_app = newstr(ldapmap_dequote(map->map_app));
505806f25ae9SGregory Neil Shapiro 	if (map->map_tapp != NULL)
505906f25ae9SGregory Neil Shapiro 		map->map_tapp = newstr(ldapmap_dequote(map->map_tapp));
506006f25ae9SGregory Neil Shapiro 
506106f25ae9SGregory Neil Shapiro 	/*
506206f25ae9SGregory Neil Shapiro 	**  We need to swallow up all the stuff into a struct
506306f25ae9SGregory Neil Shapiro 	**  and dump it into map->map_dbptr1
506406f25ae9SGregory Neil Shapiro 	*/
506506f25ae9SGregory Neil Shapiro 
5066e92d3f3fSGregory Neil Shapiro 	if (lmap->ldap_host != NULL &&
506706f25ae9SGregory Neil Shapiro 	    (LDAPDefaults == NULL ||
506806f25ae9SGregory Neil Shapiro 	     LDAPDefaults == lmap ||
5069e92d3f3fSGregory Neil Shapiro 	     LDAPDefaults->ldap_host != lmap->ldap_host))
5070e92d3f3fSGregory Neil Shapiro 		lmap->ldap_host = newstr(ldapmap_dequote(lmap->ldap_host));
5071e92d3f3fSGregory Neil Shapiro 	map->map_domain = lmap->ldap_host;
5072e92d3f3fSGregory Neil Shapiro 
5073e92d3f3fSGregory Neil Shapiro 	if (lmap->ldap_uri != NULL &&
5074e92d3f3fSGregory Neil Shapiro 	    (LDAPDefaults == NULL ||
5075e92d3f3fSGregory Neil Shapiro 	     LDAPDefaults == lmap ||
5076e92d3f3fSGregory Neil Shapiro 	     LDAPDefaults->ldap_uri != lmap->ldap_uri))
5077e92d3f3fSGregory Neil Shapiro 		lmap->ldap_uri = newstr(ldapmap_dequote(lmap->ldap_uri));
5078e92d3f3fSGregory Neil Shapiro 	map->map_domain = lmap->ldap_uri;
507906f25ae9SGregory Neil Shapiro 
508006f25ae9SGregory Neil Shapiro 	if (lmap->ldap_binddn != NULL &&
508106f25ae9SGregory Neil Shapiro 	    (LDAPDefaults == NULL ||
508206f25ae9SGregory Neil Shapiro 	     LDAPDefaults == lmap ||
508306f25ae9SGregory Neil Shapiro 	     LDAPDefaults->ldap_binddn != lmap->ldap_binddn))
508406f25ae9SGregory Neil Shapiro 		lmap->ldap_binddn = newstr(ldapmap_dequote(lmap->ldap_binddn));
508506f25ae9SGregory Neil Shapiro 
508606f25ae9SGregory Neil Shapiro 	if (lmap->ldap_secret != NULL &&
508706f25ae9SGregory Neil Shapiro 	    (LDAPDefaults == NULL ||
508806f25ae9SGregory Neil Shapiro 	     LDAPDefaults == lmap ||
508906f25ae9SGregory Neil Shapiro 	     LDAPDefaults->ldap_secret != lmap->ldap_secret))
509006f25ae9SGregory Neil Shapiro 	{
509140266059SGregory Neil Shapiro 		SM_FILE_T *sfd;
509206f25ae9SGregory Neil Shapiro 		long sff = SFF_OPENASROOT|SFF_ROOTOK|SFF_NOWLINK|SFF_NOWWFILES|SFF_NOGWFILES;
509306f25ae9SGregory Neil Shapiro 
509406f25ae9SGregory Neil Shapiro 		if (DontLockReadFiles)
509506f25ae9SGregory Neil Shapiro 			sff |= SFF_NOLOCK;
509606f25ae9SGregory Neil Shapiro 
509706f25ae9SGregory Neil Shapiro 		/* need to use method to map secret to passwd string */
509806f25ae9SGregory Neil Shapiro 		switch (lmap->ldap_method)
509906f25ae9SGregory Neil Shapiro 		{
510006f25ae9SGregory Neil Shapiro 		  case LDAP_AUTH_NONE:
510106f25ae9SGregory Neil Shapiro 			/* Do nothing */
510206f25ae9SGregory Neil Shapiro 			break;
510306f25ae9SGregory Neil Shapiro 
510406f25ae9SGregory Neil Shapiro 		  case LDAP_AUTH_SIMPLE:
510506f25ae9SGregory Neil Shapiro 
510606f25ae9SGregory Neil Shapiro 			/*
510706f25ae9SGregory Neil Shapiro 			**  Secret is the name of a file with
510806f25ae9SGregory Neil Shapiro 			**  the first line as the password.
510906f25ae9SGregory Neil Shapiro 			*/
511006f25ae9SGregory Neil Shapiro 
511106f25ae9SGregory Neil Shapiro 			/* Already read in the secret? */
511206f25ae9SGregory Neil Shapiro 			if (secretread)
511306f25ae9SGregory Neil Shapiro 				break;
511406f25ae9SGregory Neil Shapiro 
511506f25ae9SGregory Neil Shapiro 			sfd = safefopen(ldapmap_dequote(lmap->ldap_secret),
511606f25ae9SGregory Neil Shapiro 					O_RDONLY, 0, sff);
511706f25ae9SGregory Neil Shapiro 			if (sfd == NULL)
511806f25ae9SGregory Neil Shapiro 			{
511906f25ae9SGregory Neil Shapiro 				syserr("LDAP map: cannot open secret %s",
512006f25ae9SGregory Neil Shapiro 				       ldapmap_dequote(lmap->ldap_secret));
51212fb4f839SGregory Neil Shapiro 				goto fail;
512206f25ae9SGregory Neil Shapiro 			}
5123d0cef73dSGregory Neil Shapiro 			lmap->ldap_secret = sfgets(m_tmp, sizeof(m_tmp),
512442e5d165SGregory Neil Shapiro 						   sfd, TimeOuts.to_fileopen,
512542e5d165SGregory Neil Shapiro 						   "ldapmap_parseargs");
512640266059SGregory Neil Shapiro 			(void) sm_io_close(sfd, SM_TIME_DEFAULT);
512794c01205SGregory Neil Shapiro 			if (strlen(m_tmp) > LDAPMAP_MAX_PASSWD)
512894c01205SGregory Neil Shapiro 			{
512994c01205SGregory Neil Shapiro 				syserr("LDAP map: secret in %s too long",
513094c01205SGregory Neil Shapiro 				       ldapmap_dequote(lmap->ldap_secret));
51312fb4f839SGregory Neil Shapiro 				goto fail;
513294c01205SGregory Neil Shapiro 			}
513306f25ae9SGregory Neil Shapiro 			if (lmap->ldap_secret != NULL &&
513406f25ae9SGregory Neil Shapiro 			    strlen(m_tmp) > 0)
513506f25ae9SGregory Neil Shapiro 			{
513606f25ae9SGregory Neil Shapiro 				/* chomp newline */
513706f25ae9SGregory Neil Shapiro 				if (m_tmp[strlen(m_tmp) - 1] == '\n')
513806f25ae9SGregory Neil Shapiro 					m_tmp[strlen(m_tmp) - 1] = '\0';
513906f25ae9SGregory Neil Shapiro 
514006f25ae9SGregory Neil Shapiro 				lmap->ldap_secret = m_tmp;
514106f25ae9SGregory Neil Shapiro 			}
514206f25ae9SGregory Neil Shapiro 			break;
514306f25ae9SGregory Neil Shapiro 
514406f25ae9SGregory Neil Shapiro # ifdef LDAP_AUTH_KRBV4
514506f25ae9SGregory Neil Shapiro 		  case LDAP_AUTH_KRBV4:
514606f25ae9SGregory Neil Shapiro 
514706f25ae9SGregory Neil Shapiro 			/*
514806f25ae9SGregory Neil Shapiro 			**  Secret is where the ticket file is
514906f25ae9SGregory Neil Shapiro 			**  stashed
515006f25ae9SGregory Neil Shapiro 			*/
515106f25ae9SGregory Neil Shapiro 
5152d0cef73dSGregory Neil Shapiro 			(void) sm_snprintf(m_tmp, sizeof(m_tmp),
515306f25ae9SGregory Neil Shapiro 				"KRBTKFILE=%s",
515406f25ae9SGregory Neil Shapiro 				ldapmap_dequote(lmap->ldap_secret));
515506f25ae9SGregory Neil Shapiro 			lmap->ldap_secret = m_tmp;
515606f25ae9SGregory Neil Shapiro 			break;
515706f25ae9SGregory Neil Shapiro # endif /* LDAP_AUTH_KRBV4 */
515806f25ae9SGregory Neil Shapiro 
515906f25ae9SGregory Neil Shapiro 		  default:	       /* Should NEVER get here */
516006f25ae9SGregory Neil Shapiro 			syserr("LDAP map: Illegal value in lmap method");
51612fb4f839SGregory Neil Shapiro 			goto fail;
516240266059SGregory Neil Shapiro 			/* NOTREACHED */
516306f25ae9SGregory Neil Shapiro 			break;
516406f25ae9SGregory Neil Shapiro 		}
516506f25ae9SGregory Neil Shapiro 	}
516606f25ae9SGregory Neil Shapiro 
516706f25ae9SGregory Neil Shapiro 	if (lmap->ldap_secret != NULL &&
516806f25ae9SGregory Neil Shapiro 	    (LDAPDefaults == NULL ||
516906f25ae9SGregory Neil Shapiro 	     LDAPDefaults == lmap ||
517006f25ae9SGregory Neil Shapiro 	     LDAPDefaults->ldap_secret != lmap->ldap_secret))
517106f25ae9SGregory Neil Shapiro 		lmap->ldap_secret = newstr(ldapmap_dequote(lmap->ldap_secret));
517206f25ae9SGregory Neil Shapiro 
517306f25ae9SGregory Neil Shapiro 	if (lmap->ldap_base != NULL &&
517406f25ae9SGregory Neil Shapiro 	    (LDAPDefaults == NULL ||
517506f25ae9SGregory Neil Shapiro 	     LDAPDefaults == lmap ||
517606f25ae9SGregory Neil Shapiro 	     LDAPDefaults->ldap_base != lmap->ldap_base))
517706f25ae9SGregory Neil Shapiro 		lmap->ldap_base = newstr(ldapmap_dequote(lmap->ldap_base));
517806f25ae9SGregory Neil Shapiro 
517906f25ae9SGregory Neil Shapiro 	/*
518006f25ae9SGregory Neil Shapiro 	**  Save the server from extra work.  If request is for a single
518106f25ae9SGregory Neil Shapiro 	**  match, tell the server to only return enough records to
518206f25ae9SGregory Neil Shapiro 	**  determine if there is a single match or not.  This can not
518306f25ae9SGregory Neil Shapiro 	**  be one since the server would only return one and we wouldn't
518406f25ae9SGregory Neil Shapiro 	**  know if there were others available.
518506f25ae9SGregory Neil Shapiro 	*/
518606f25ae9SGregory Neil Shapiro 
518706f25ae9SGregory Neil Shapiro 	if (bitset(MF_SINGLEMATCH, map->map_mflags))
518806f25ae9SGregory Neil Shapiro 		lmap->ldap_sizelimit = 2;
518906f25ae9SGregory Neil Shapiro 
519006f25ae9SGregory Neil Shapiro 	/* If setting defaults, don't process ldap_filter and ldap_attr */
519106f25ae9SGregory Neil Shapiro 	if (lmap == LDAPDefaults)
519240266059SGregory Neil Shapiro 		return true;
519306f25ae9SGregory Neil Shapiro 
519406f25ae9SGregory Neil Shapiro 	if (lmap->ldap_filter != NULL)
519506f25ae9SGregory Neil Shapiro 		lmap->ldap_filter = newstr(ldapmap_dequote(lmap->ldap_filter));
519606f25ae9SGregory Neil Shapiro 	else
519706f25ae9SGregory Neil Shapiro 	{
519806f25ae9SGregory Neil Shapiro 		if (!bitset(MCF_OPTFILE, map->map_class->map_cflags))
519906f25ae9SGregory Neil Shapiro 		{
520006f25ae9SGregory Neil Shapiro 			syserr("No filter given in map %s", map->map_mname);
52012fb4f839SGregory Neil Shapiro 			goto fail;
520206f25ae9SGregory Neil Shapiro 		}
520306f25ae9SGregory Neil Shapiro 	}
520406f25ae9SGregory Neil Shapiro 
5205e92d3f3fSGregory Neil Shapiro 	if (!attrssetup && lmap->ldap_attr[0] != NULL)
520606f25ae9SGregory Neil Shapiro 	{
520740266059SGregory Neil Shapiro 		bool recurse = false;
5208605302a5SGregory Neil Shapiro 		bool normalseen = false;
520940266059SGregory Neil Shapiro 
521006f25ae9SGregory Neil Shapiro 		i = 0;
521106f25ae9SGregory Neil Shapiro 		p = ldapmap_dequote(lmap->ldap_attr[0]);
521206f25ae9SGregory Neil Shapiro 		lmap->ldap_attr[0] = NULL;
521306f25ae9SGregory Neil Shapiro 
5214605302a5SGregory Neil Shapiro 		/* Prime the attr list with the objectClass attribute */
5215605302a5SGregory Neil Shapiro 		lmap->ldap_attr[i] = "objectClass";
5216605302a5SGregory Neil Shapiro 		lmap->ldap_attr_type[i] = SM_LDAP_ATTR_OBJCLASS;
5217605302a5SGregory Neil Shapiro 		lmap->ldap_attr_needobjclass[i] = NULL;
5218605302a5SGregory Neil Shapiro 		i++;
5219605302a5SGregory Neil Shapiro 
522006f25ae9SGregory Neil Shapiro 		while (p != NULL)
522106f25ae9SGregory Neil Shapiro 		{
522206f25ae9SGregory Neil Shapiro 			char *v;
522306f25ae9SGregory Neil Shapiro 
52245b0945b5SGregory Neil Shapiro 			while (SM_ISSPACE(*p))
522506f25ae9SGregory Neil Shapiro 				p++;
522606f25ae9SGregory Neil Shapiro 			if (*p == '\0')
522706f25ae9SGregory Neil Shapiro 				break;
522806f25ae9SGregory Neil Shapiro 			v = p;
522906f25ae9SGregory Neil Shapiro 			p = strchr(v, ',');
523006f25ae9SGregory Neil Shapiro 			if (p != NULL)
523106f25ae9SGregory Neil Shapiro 				*p++ = '\0';
523206f25ae9SGregory Neil Shapiro 
5233193538b7SGregory Neil Shapiro 			if (i >= LDAPMAP_MAX_ATTR)
523406f25ae9SGregory Neil Shapiro 			{
523506f25ae9SGregory Neil Shapiro 				syserr("Too many return attributes in %s (max %d)",
523606f25ae9SGregory Neil Shapiro 				       map->map_mname, LDAPMAP_MAX_ATTR);
52372fb4f839SGregory Neil Shapiro 				goto fail;
523806f25ae9SGregory Neil Shapiro 			}
523906f25ae9SGregory Neil Shapiro 			if (*v != '\0')
524040266059SGregory Neil Shapiro 			{
5241605302a5SGregory Neil Shapiro 				int j;
5242605302a5SGregory Neil Shapiro 				int use;
524340266059SGregory Neil Shapiro 				char *type;
5244605302a5SGregory Neil Shapiro 				char *needobjclass;
524540266059SGregory Neil Shapiro 
524640266059SGregory Neil Shapiro 				type = strchr(v, ':');
524740266059SGregory Neil Shapiro 				if (type != NULL)
5248605302a5SGregory Neil Shapiro 				{
524940266059SGregory Neil Shapiro 					*type++ = '\0';
5250605302a5SGregory Neil Shapiro 					needobjclass = strchr(type, ':');
5251605302a5SGregory Neil Shapiro 					if (needobjclass != NULL)
5252605302a5SGregory Neil Shapiro 						*needobjclass++ = '\0';
525340266059SGregory Neil Shapiro 				}
5254605302a5SGregory Neil Shapiro 				else
5255605302a5SGregory Neil Shapiro 				{
5256605302a5SGregory Neil Shapiro 					needobjclass = NULL;
5257605302a5SGregory Neil Shapiro 				}
5258605302a5SGregory Neil Shapiro 
5259605302a5SGregory Neil Shapiro 				use = i;
5260605302a5SGregory Neil Shapiro 
5261605302a5SGregory Neil Shapiro 				/* allow override on "objectClass" type */
52622fb4f839SGregory Neil Shapiro 				if (SM_STRCASEEQ(v, "objectClass") &&
5263605302a5SGregory Neil Shapiro 				    lmap->ldap_attr_type[0] == SM_LDAP_ATTR_OBJCLASS)
5264605302a5SGregory Neil Shapiro 				{
5265605302a5SGregory Neil Shapiro 					use = 0;
5266605302a5SGregory Neil Shapiro 				}
5267605302a5SGregory Neil Shapiro 				else
5268605302a5SGregory Neil Shapiro 				{
5269605302a5SGregory Neil Shapiro 					/*
5270605302a5SGregory Neil Shapiro 					**  Don't add something to attribute
5271605302a5SGregory Neil Shapiro 					**  list twice.
5272605302a5SGregory Neil Shapiro 					*/
5273605302a5SGregory Neil Shapiro 
5274605302a5SGregory Neil Shapiro 					for (j = 1; j < i; j++)
5275605302a5SGregory Neil Shapiro 					{
52762fb4f839SGregory Neil Shapiro 						if (SM_STRCASEEQ(v, lmap->ldap_attr[j]))
5277605302a5SGregory Neil Shapiro 						{
5278605302a5SGregory Neil Shapiro 							syserr("Duplicate attribute (%s) in %s",
5279605302a5SGregory Neil Shapiro 							       v, map->map_mname);
52802fb4f839SGregory Neil Shapiro 							goto fail;
5281605302a5SGregory Neil Shapiro 						}
5282605302a5SGregory Neil Shapiro 					}
5283605302a5SGregory Neil Shapiro 
5284605302a5SGregory Neil Shapiro 					lmap->ldap_attr[use] = newstr(v);
5285605302a5SGregory Neil Shapiro 					if (needobjclass != NULL &&
5286605302a5SGregory Neil Shapiro 					    *needobjclass != '\0' &&
5287605302a5SGregory Neil Shapiro 					    *needobjclass != '*')
5288605302a5SGregory Neil Shapiro 					{
5289605302a5SGregory Neil Shapiro 						lmap->ldap_attr_needobjclass[use] = newstr(needobjclass);
5290605302a5SGregory Neil Shapiro 					}
5291605302a5SGregory Neil Shapiro 					else
5292605302a5SGregory Neil Shapiro 					{
5293605302a5SGregory Neil Shapiro 						lmap->ldap_attr_needobjclass[use] = NULL;
5294605302a5SGregory Neil Shapiro 					}
5295605302a5SGregory Neil Shapiro 
5296605302a5SGregory Neil Shapiro 				}
5297605302a5SGregory Neil Shapiro 
5298605302a5SGregory Neil Shapiro 				if (type != NULL && *type != '\0')
5299605302a5SGregory Neil Shapiro 				{
53002fb4f839SGregory Neil Shapiro 					if (SM_STRCASEEQ(type, "dn"))
530140266059SGregory Neil Shapiro 					{
530240266059SGregory Neil Shapiro 						recurse = true;
5303605302a5SGregory Neil Shapiro 						lmap->ldap_attr_type[use] = SM_LDAP_ATTR_DN;
530440266059SGregory Neil Shapiro 					}
53052fb4f839SGregory Neil Shapiro 					else if (SM_STRCASEEQ(type, "filter"))
530640266059SGregory Neil Shapiro 					{
530740266059SGregory Neil Shapiro 						recurse = true;
5308605302a5SGregory Neil Shapiro 						lmap->ldap_attr_type[use] = SM_LDAP_ATTR_FILTER;
530940266059SGregory Neil Shapiro 					}
53102fb4f839SGregory Neil Shapiro 					else if (SM_STRCASEEQ(type, "url"))
531140266059SGregory Neil Shapiro 					{
531240266059SGregory Neil Shapiro 						recurse = true;
5313605302a5SGregory Neil Shapiro 						lmap->ldap_attr_type[use] = SM_LDAP_ATTR_URL;
531440266059SGregory Neil Shapiro 					}
53152fb4f839SGregory Neil Shapiro 					else if (SM_STRCASEEQ(type, "normal"))
531640266059SGregory Neil Shapiro 					{
5317605302a5SGregory Neil Shapiro 						lmap->ldap_attr_type[use] = SM_LDAP_ATTR_NORMAL;
5318605302a5SGregory Neil Shapiro 						normalseen = true;
531940266059SGregory Neil Shapiro 					}
532040266059SGregory Neil Shapiro 					else
532140266059SGregory Neil Shapiro 					{
532240266059SGregory Neil Shapiro 						syserr("Unknown attribute type (%s) in %s",
532340266059SGregory Neil Shapiro 						       type, map->map_mname);
53242fb4f839SGregory Neil Shapiro 						goto fail;
532540266059SGregory Neil Shapiro 					}
532640266059SGregory Neil Shapiro 				}
532740266059SGregory Neil Shapiro 				else
5328605302a5SGregory Neil Shapiro 				{
5329605302a5SGregory Neil Shapiro 					lmap->ldap_attr_type[use] = SM_LDAP_ATTR_NORMAL;
5330605302a5SGregory Neil Shapiro 					normalseen = true;
5331605302a5SGregory Neil Shapiro 				}
533240266059SGregory Neil Shapiro 				i++;
533340266059SGregory Neil Shapiro 			}
533406f25ae9SGregory Neil Shapiro 		}
533506f25ae9SGregory Neil Shapiro 		lmap->ldap_attr[i] = NULL;
5336b6bacd31SGregory Neil Shapiro 
5337b6bacd31SGregory Neil Shapiro 		/* Set in case needed in future code */
5338e92d3f3fSGregory Neil Shapiro 		attrssetup = true;
5339b6bacd31SGregory Neil Shapiro 
5340605302a5SGregory Neil Shapiro 		if (recurse && !normalseen)
534140266059SGregory Neil Shapiro 		{
5342605302a5SGregory Neil Shapiro 			syserr("LDAP recursion requested in %s but no returnable attribute given",
534340266059SGregory Neil Shapiro 			       map->map_mname);
53442fb4f839SGregory Neil Shapiro 			goto fail;
534506f25ae9SGregory Neil Shapiro 		}
534640266059SGregory Neil Shapiro 		if (recurse && lmap->ldap_attrsonly == LDAPMAP_TRUE)
534740266059SGregory Neil Shapiro 		{
534840266059SGregory Neil Shapiro 			syserr("LDAP recursion requested in %s can not be used with -n",
534940266059SGregory Neil Shapiro 			       map->map_mname);
53502fb4f839SGregory Neil Shapiro 			goto fail;
535140266059SGregory Neil Shapiro 		}
535240266059SGregory Neil Shapiro 	}
535306f25ae9SGregory Neil Shapiro 	map->map_db1 = (ARBPTR_T) lmap;
535440266059SGregory Neil Shapiro 	return true;
53552fb4f839SGregory Neil Shapiro   fail:
53562fb4f839SGregory Neil Shapiro 	SM_FREE(lmap_alloc);
53572fb4f839SGregory Neil Shapiro 	return false;
535806f25ae9SGregory Neil Shapiro }
535906f25ae9SGregory Neil Shapiro 
536006f25ae9SGregory Neil Shapiro /*
536106f25ae9SGregory Neil Shapiro **  LDAPMAP_SET_DEFAULTS -- Read default map spec from LDAPDefaults in .cf
536206f25ae9SGregory Neil Shapiro **
536306f25ae9SGregory Neil Shapiro **	Parameters:
536406f25ae9SGregory Neil Shapiro **		spec -- map argument string from LDAPDefaults option
536506f25ae9SGregory Neil Shapiro **
536606f25ae9SGregory Neil Shapiro **	Returns:
536706f25ae9SGregory Neil Shapiro **		None.
536806f25ae9SGregory Neil Shapiro */
536906f25ae9SGregory Neil Shapiro 
537006f25ae9SGregory Neil Shapiro void
ldapmap_set_defaults(spec)537106f25ae9SGregory Neil Shapiro ldapmap_set_defaults(spec)
537206f25ae9SGregory Neil Shapiro 	char *spec;
537306f25ae9SGregory Neil Shapiro {
5374602a2b1bSGregory Neil Shapiro 	STAB *class;
537506f25ae9SGregory Neil Shapiro 	MAP map;
537606f25ae9SGregory Neil Shapiro 
537706f25ae9SGregory Neil Shapiro 	/* Allocate and set the default values */
537806f25ae9SGregory Neil Shapiro 	if (LDAPDefaults == NULL)
5379d0cef73dSGregory Neil Shapiro 		LDAPDefaults = (SM_LDAP_STRUCT *) xalloc(sizeof(*LDAPDefaults));
538040266059SGregory Neil Shapiro 	sm_ldap_clear(LDAPDefaults);
538106f25ae9SGregory Neil Shapiro 
5382d0cef73dSGregory Neil Shapiro 	memset(&map, '\0', sizeof(map));
5383602a2b1bSGregory Neil Shapiro 
5384602a2b1bSGregory Neil Shapiro 	/* look up the class */
5385602a2b1bSGregory Neil Shapiro 	class = stab("ldap", ST_MAPCLASS, ST_FIND);
5386602a2b1bSGregory Neil Shapiro 	if (class == NULL)
5387602a2b1bSGregory Neil Shapiro 	{
5388602a2b1bSGregory Neil Shapiro 		syserr("readcf: LDAPDefaultSpec: class ldap not available");
5389602a2b1bSGregory Neil Shapiro 		return;
5390602a2b1bSGregory Neil Shapiro 	}
5391602a2b1bSGregory Neil Shapiro 	map.map_class = &class->s_mapclass;
539206f25ae9SGregory Neil Shapiro 	map.map_db1 = (ARBPTR_T) LDAPDefaults;
5393602a2b1bSGregory Neil Shapiro 	map.map_mname = "O LDAPDefaultSpec";
539406f25ae9SGregory Neil Shapiro 
539506f25ae9SGregory Neil Shapiro 	(void) ldapmap_parseargs(&map, spec);
539606f25ae9SGregory Neil Shapiro 
539706f25ae9SGregory Neil Shapiro 	/* These should never be set in LDAPDefaults */
539806f25ae9SGregory Neil Shapiro 	if (map.map_mflags != (MF_TRY0NULL|MF_TRY1NULL) ||
539906f25ae9SGregory Neil Shapiro 	    map.map_spacesub != SpaceSub ||
540006f25ae9SGregory Neil Shapiro 	    map.map_app != NULL ||
540106f25ae9SGregory Neil Shapiro 	    map.map_tapp != NULL)
540206f25ae9SGregory Neil Shapiro 	{
540306f25ae9SGregory Neil Shapiro 		syserr("readcf: option LDAPDefaultSpec: Do not set non-LDAP specific flags");
54045b0945b5SGregory Neil Shapiro 		SM_FREE(map.map_app);
54055b0945b5SGregory Neil Shapiro 		SM_FREE(map.map_tapp);
540606f25ae9SGregory Neil Shapiro 	}
540706f25ae9SGregory Neil Shapiro 
540806f25ae9SGregory Neil Shapiro 	if (LDAPDefaults->ldap_filter != NULL)
540906f25ae9SGregory Neil Shapiro 	{
541006f25ae9SGregory Neil Shapiro 		syserr("readcf: option LDAPDefaultSpec: Do not set the LDAP search filter");
5411605302a5SGregory Neil Shapiro 
541206f25ae9SGregory Neil Shapiro 		/* don't free, it isn't malloc'ed in parseargs */
541306f25ae9SGregory Neil Shapiro 		LDAPDefaults->ldap_filter = NULL;
541406f25ae9SGregory Neil Shapiro 	}
541506f25ae9SGregory Neil Shapiro 
541606f25ae9SGregory Neil Shapiro 	if (LDAPDefaults->ldap_attr[0] != NULL)
541706f25ae9SGregory Neil Shapiro 	{
541806f25ae9SGregory Neil Shapiro 		syserr("readcf: option LDAPDefaultSpec: Do not set the requested LDAP attributes");
541906f25ae9SGregory Neil Shapiro 		/* don't free, they aren't malloc'ed in parseargs */
542006f25ae9SGregory Neil Shapiro 		LDAPDefaults->ldap_attr[0] = NULL;
542106f25ae9SGregory Neil Shapiro 	}
542206f25ae9SGregory Neil Shapiro }
542306f25ae9SGregory Neil Shapiro #endif /* LDAPMAP */
542440266059SGregory Neil Shapiro /*
542506f25ae9SGregory Neil Shapiro **  PH map
542606f25ae9SGregory Neil Shapiro */
542706f25ae9SGregory Neil Shapiro 
542840266059SGregory Neil Shapiro #if PH_MAP
542906f25ae9SGregory Neil Shapiro 
543006f25ae9SGregory Neil Shapiro /*
543106f25ae9SGregory Neil Shapiro **  Support for the CCSO Nameserver (ph/qi).
543206f25ae9SGregory Neil Shapiro **  This code is intended to replace the so-called "ph mailer".
5433d0cef73dSGregory Neil Shapiro **  Contributed by Mark D. Roth.  Contact him for support.
543406f25ae9SGregory Neil Shapiro */
543506f25ae9SGregory Neil Shapiro 
543640266059SGregory Neil Shapiro /* what version of the ph map code we're running */
543713bd1963SGregory Neil Shapiro static char phmap_id[128];
543840266059SGregory Neil Shapiro 
543940266059SGregory Neil Shapiro /* sendmail version for phmap id string */
544040266059SGregory Neil Shapiro extern const char Version[];
544106f25ae9SGregory Neil Shapiro 
5442e92d3f3fSGregory Neil Shapiro /* assume we're using nph-1.2.x if not specified */
544313bd1963SGregory Neil Shapiro # ifndef NPH_VERSION
5444e92d3f3fSGregory Neil Shapiro #  define NPH_VERSION		10200
544513bd1963SGregory Neil Shapiro # endif
544613bd1963SGregory Neil Shapiro 
544713bd1963SGregory Neil Shapiro /* compatibility for versions older than nph-1.2.0 */
544813bd1963SGregory Neil Shapiro # if NPH_VERSION < 10200
544913bd1963SGregory Neil Shapiro #  define PH_OPEN_ROUNDROBIN	PH_ROUNDROBIN
545013bd1963SGregory Neil Shapiro #  define PH_OPEN_DONTID	PH_DONTID
545113bd1963SGregory Neil Shapiro #  define PH_CLOSE_FAST		PH_FASTCLOSE
545213bd1963SGregory Neil Shapiro #  define PH_ERR_DATAERR	PH_DATAERR
545313bd1963SGregory Neil Shapiro #  define PH_ERR_NOMATCH	PH_NOMATCH
545413bd1963SGregory Neil Shapiro # endif /* NPH_VERSION < 10200 */
545513bd1963SGregory Neil Shapiro 
545606f25ae9SGregory Neil Shapiro /*
545706f25ae9SGregory Neil Shapiro **  PH_MAP_PARSEARGS -- parse ph map definition args.
545806f25ae9SGregory Neil Shapiro */
545906f25ae9SGregory Neil Shapiro 
546006f25ae9SGregory Neil Shapiro bool
ph_map_parseargs(map,args)546106f25ae9SGregory Neil Shapiro ph_map_parseargs(map, args)
546206f25ae9SGregory Neil Shapiro 	MAP *map;
546306f25ae9SGregory Neil Shapiro 	char *args;
546406f25ae9SGregory Neil Shapiro {
546540266059SGregory Neil Shapiro 	register bool done;
546606f25ae9SGregory Neil Shapiro 	register char *p = args;
546740266059SGregory Neil Shapiro 	PH_MAP_STRUCT *pmap = NULL;
546840266059SGregory Neil Shapiro 
546940266059SGregory Neil Shapiro 	/* initialize version string */
5470d0cef73dSGregory Neil Shapiro 	(void) sm_snprintf(phmap_id, sizeof(phmap_id),
547140266059SGregory Neil Shapiro 			   "sendmail-%s phmap-20010529 libphclient-%s",
547240266059SGregory Neil Shapiro 			   Version, libphclient_version);
5473c2aa98e2SPeter Wemm 
5474d0cef73dSGregory Neil Shapiro 	pmap = (PH_MAP_STRUCT *) xalloc(sizeof(*pmap));
5475c2aa98e2SPeter Wemm 
547606f25ae9SGregory Neil Shapiro 	/* defaults */
547706f25ae9SGregory Neil Shapiro 	pmap->ph_servers = NULL;
547806f25ae9SGregory Neil Shapiro 	pmap->ph_field_list = NULL;
547940266059SGregory Neil Shapiro 	pmap->ph = NULL;
548006f25ae9SGregory Neil Shapiro 	pmap->ph_timeout = 0;
548140266059SGregory Neil Shapiro 	pmap->ph_fastclose = 0;
5482c2aa98e2SPeter Wemm 
5483c2aa98e2SPeter Wemm 	map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL;
5484c2aa98e2SPeter Wemm 	for (;;)
5485c2aa98e2SPeter Wemm 	{
54865b0945b5SGregory Neil Shapiro 		while (SM_ISSPACE(*p))
5487c2aa98e2SPeter Wemm 			p++;
5488c2aa98e2SPeter Wemm 		if (*p != '-')
5489c2aa98e2SPeter Wemm 			break;
5490c2aa98e2SPeter Wemm 		switch (*++p)
5491c2aa98e2SPeter Wemm 		{
5492c2aa98e2SPeter Wemm 		  case 'N':
5493c2aa98e2SPeter Wemm 			map->map_mflags |= MF_INCLNULL;
5494c2aa98e2SPeter Wemm 			map->map_mflags &= ~MF_TRY0NULL;
5495c2aa98e2SPeter Wemm 			break;
5496c2aa98e2SPeter Wemm 
5497c2aa98e2SPeter Wemm 		  case 'O':
5498c2aa98e2SPeter Wemm 			map->map_mflags &= ~MF_TRY1NULL;
5499c2aa98e2SPeter Wemm 			break;
5500c2aa98e2SPeter Wemm 
5501c2aa98e2SPeter Wemm 		  case 'o':
5502c2aa98e2SPeter Wemm 			map->map_mflags |= MF_OPTIONAL;
5503c2aa98e2SPeter Wemm 			break;
5504c2aa98e2SPeter Wemm 
5505c2aa98e2SPeter Wemm 		  case 'f':
5506c2aa98e2SPeter Wemm 			map->map_mflags |= MF_NOFOLDCASE;
5507c2aa98e2SPeter Wemm 			break;
5508c2aa98e2SPeter Wemm 
5509c2aa98e2SPeter Wemm 		  case 'm':
5510c2aa98e2SPeter Wemm 			map->map_mflags |= MF_MATCHONLY;
5511c2aa98e2SPeter Wemm 			break;
5512c2aa98e2SPeter Wemm 
5513c2aa98e2SPeter Wemm 		  case 'A':
5514c2aa98e2SPeter Wemm 			map->map_mflags |= MF_APPEND;
5515c2aa98e2SPeter Wemm 			break;
5516c2aa98e2SPeter Wemm 
5517c2aa98e2SPeter Wemm 		  case 'q':
5518c2aa98e2SPeter Wemm 			map->map_mflags |= MF_KEEPQUOTES;
5519c2aa98e2SPeter Wemm 			break;
5520c2aa98e2SPeter Wemm 
5521c2aa98e2SPeter Wemm 		  case 't':
5522c2aa98e2SPeter Wemm 			map->map_mflags |= MF_NODEFER;
5523c2aa98e2SPeter Wemm 			break;
5524c2aa98e2SPeter Wemm 
5525c2aa98e2SPeter Wemm 		  case 'a':
5526c2aa98e2SPeter Wemm 			map->map_app = ++p;
5527c2aa98e2SPeter Wemm 			break;
5528c2aa98e2SPeter Wemm 
5529c2aa98e2SPeter Wemm 		  case 'T':
5530c2aa98e2SPeter Wemm 			map->map_tapp = ++p;
5531c2aa98e2SPeter Wemm 			break;
5532c2aa98e2SPeter Wemm 
553306f25ae9SGregory Neil Shapiro 		  case 'l':
5534c2aa98e2SPeter Wemm 			while (isascii(*++p) && isspace(*p))
5535c2aa98e2SPeter Wemm 				continue;
553606f25ae9SGregory Neil Shapiro 			pmap->ph_timeout = atoi(p);
553706f25ae9SGregory Neil Shapiro 			break;
553806f25ae9SGregory Neil Shapiro 
553906f25ae9SGregory Neil Shapiro 		  case 'S':
554006f25ae9SGregory Neil Shapiro 			map->map_spacesub = *++p;
5541c2aa98e2SPeter Wemm 			break;
5542c2aa98e2SPeter Wemm 
554306f25ae9SGregory Neil Shapiro 		  case 'D':
554406f25ae9SGregory Neil Shapiro 			map->map_mflags |= MF_DEFER;
554506f25ae9SGregory Neil Shapiro 			break;
554606f25ae9SGregory Neil Shapiro 
554706f25ae9SGregory Neil Shapiro 		  case 'h':		/* PH server list */
5548c2aa98e2SPeter Wemm 			while (isascii(*++p) && isspace(*p))
5549c2aa98e2SPeter Wemm 				continue;
555006f25ae9SGregory Neil Shapiro 			pmap->ph_servers = p;
5551c2aa98e2SPeter Wemm 			break;
5552c2aa98e2SPeter Wemm 
555340266059SGregory Neil Shapiro 		  case 'k':		/* fields to search for */
5554c2aa98e2SPeter Wemm 			while (isascii(*++p) && isspace(*p))
5555c2aa98e2SPeter Wemm 				continue;
555606f25ae9SGregory Neil Shapiro 			pmap->ph_field_list = p;
5557c2aa98e2SPeter Wemm 			break;
5558c2aa98e2SPeter Wemm 
555906f25ae9SGregory Neil Shapiro 		  default:
556040266059SGregory Neil Shapiro 			syserr("ph_map_parseargs: unknown option -%c", *p);
5561c2aa98e2SPeter Wemm 		}
5562c2aa98e2SPeter Wemm 
556306f25ae9SGregory Neil Shapiro 		/* try to account for quoted strings */
55645b0945b5SGregory Neil Shapiro 		done = SM_ISSPACE(*p);
5565c2aa98e2SPeter Wemm 		while (*p != '\0' && !done)
5566c2aa98e2SPeter Wemm 		{
5567c2aa98e2SPeter Wemm 			if (*p == '"')
5568c2aa98e2SPeter Wemm 			{
5569c2aa98e2SPeter Wemm 				while (*++p != '"' && *p != '\0')
5570c2aa98e2SPeter Wemm 					continue;
5571c2aa98e2SPeter Wemm 				if (*p != '\0')
5572c2aa98e2SPeter Wemm 					p++;
5573c2aa98e2SPeter Wemm 			}
5574c2aa98e2SPeter Wemm 			else
5575c2aa98e2SPeter Wemm 				p++;
55765b0945b5SGregory Neil Shapiro 			done = SM_ISSPACE(*p);
5577c2aa98e2SPeter Wemm 		}
5578c2aa98e2SPeter Wemm 
5579c2aa98e2SPeter Wemm 		if (*p != '\0')
5580c2aa98e2SPeter Wemm 			*p++ = '\0';
5581c2aa98e2SPeter Wemm 	}
5582c2aa98e2SPeter Wemm 
5583c2aa98e2SPeter Wemm 	if (map->map_app != NULL)
558406f25ae9SGregory Neil Shapiro 		map->map_app = newstr(ph_map_dequote(map->map_app));
5585c2aa98e2SPeter Wemm 	if (map->map_tapp != NULL)
558606f25ae9SGregory Neil Shapiro 		map->map_tapp = newstr(ph_map_dequote(map->map_tapp));
5587c2aa98e2SPeter Wemm 
558806f25ae9SGregory Neil Shapiro 	if (pmap->ph_field_list != NULL)
558906f25ae9SGregory Neil Shapiro 		pmap->ph_field_list = newstr(ph_map_dequote(pmap->ph_field_list));
5590c2aa98e2SPeter Wemm 
559106f25ae9SGregory Neil Shapiro 	if (pmap->ph_servers != NULL)
559206f25ae9SGregory Neil Shapiro 		pmap->ph_servers = newstr(ph_map_dequote(pmap->ph_servers));
5593c2aa98e2SPeter Wemm 	else
5594c2aa98e2SPeter Wemm 	{
559506f25ae9SGregory Neil Shapiro 		syserr("ph_map_parseargs: -h flag is required");
559640266059SGregory Neil Shapiro 		return false;
5597c2aa98e2SPeter Wemm 	}
5598c2aa98e2SPeter Wemm 
559906f25ae9SGregory Neil Shapiro 	map->map_db1 = (ARBPTR_T) pmap;
560040266059SGregory Neil Shapiro 	return true;
5601c2aa98e2SPeter Wemm }
5602c2aa98e2SPeter Wemm 
560306f25ae9SGregory Neil Shapiro /*
560406f25ae9SGregory Neil Shapiro **  PH_MAP_CLOSE -- close the connection to the ph server
560506f25ae9SGregory Neil Shapiro */
560606f25ae9SGregory Neil Shapiro 
560706f25ae9SGregory Neil Shapiro void
ph_map_close(map)560806f25ae9SGregory Neil Shapiro ph_map_close(map)
560906f25ae9SGregory Neil Shapiro 	MAP *map;
561006f25ae9SGregory Neil Shapiro {
561106f25ae9SGregory Neil Shapiro 	PH_MAP_STRUCT *pmap;
561206f25ae9SGregory Neil Shapiro 
561306f25ae9SGregory Neil Shapiro 	pmap = (PH_MAP_STRUCT *)map->map_db1;
561440266059SGregory Neil Shapiro 	if (tTd(38, 9))
5615605302a5SGregory Neil Shapiro 		sm_dprintf("ph_map_close(%s): pmap->ph_fastclose=%d\n",
561640266059SGregory Neil Shapiro 			   map->map_mname, pmap->ph_fastclose);
561740266059SGregory Neil Shapiro 
561840266059SGregory Neil Shapiro 
561940266059SGregory Neil Shapiro 	if (pmap->ph != NULL)
562040266059SGregory Neil Shapiro 	{
562140266059SGregory Neil Shapiro 		ph_set_sendhook(pmap->ph, NULL);
562240266059SGregory Neil Shapiro 		ph_set_recvhook(pmap->ph, NULL);
562340266059SGregory Neil Shapiro 		ph_close(pmap->ph, pmap->ph_fastclose);
562440266059SGregory Neil Shapiro 	}
562540266059SGregory Neil Shapiro 
562640266059SGregory Neil Shapiro 	map->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
562706f25ae9SGregory Neil Shapiro }
562806f25ae9SGregory Neil Shapiro 
562906f25ae9SGregory Neil Shapiro static jmp_buf  PHTimeout;
563006f25ae9SGregory Neil Shapiro 
563106f25ae9SGregory Neil Shapiro /* ARGSUSED */
563206f25ae9SGregory Neil Shapiro static void
ph_timeout(unused)563340266059SGregory Neil Shapiro ph_timeout(unused)
563440266059SGregory Neil Shapiro 	int unused;
563506f25ae9SGregory Neil Shapiro {
56368774250cSGregory Neil Shapiro 	/*
56378774250cSGregory Neil Shapiro 	**  NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
56388774250cSGregory Neil Shapiro 	**	ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
56398774250cSGregory Neil Shapiro 	**	DOING.
56408774250cSGregory Neil Shapiro 	*/
56418774250cSGregory Neil Shapiro 
56428774250cSGregory Neil Shapiro 	errno = ETIMEDOUT;
564306f25ae9SGregory Neil Shapiro 	longjmp(PHTimeout, 1);
564406f25ae9SGregory Neil Shapiro }
564506f25ae9SGregory Neil Shapiro 
564640266059SGregory Neil Shapiro static void
564713bd1963SGregory Neil Shapiro # if NPH_VERSION >= 10200
ph_map_send_debug(appdata,text)564813bd1963SGregory Neil Shapiro ph_map_send_debug(appdata, text)
564913bd1963SGregory Neil Shapiro 	void *appdata;
565013bd1963SGregory Neil Shapiro # else
565140266059SGregory Neil Shapiro ph_map_send_debug(text)
565213bd1963SGregory Neil Shapiro # endif
565340266059SGregory Neil Shapiro 	char *text;
565406f25ae9SGregory Neil Shapiro {
565540266059SGregory Neil Shapiro 	if (LogLevel > 9)
565640266059SGregory Neil Shapiro 		sm_syslog(LOG_NOTICE, CurEnv->e_id,
565740266059SGregory Neil Shapiro 			  "ph_map_send_debug: ==> %s", text);
565840266059SGregory Neil Shapiro 	if (tTd(38, 20))
565940266059SGregory Neil Shapiro 		sm_dprintf("ph_map_send_debug: ==> %s\n", text);
566006f25ae9SGregory Neil Shapiro }
566106f25ae9SGregory Neil Shapiro 
566240266059SGregory Neil Shapiro static void
566313bd1963SGregory Neil Shapiro # if NPH_VERSION >= 10200
ph_map_recv_debug(appdata,text)566413bd1963SGregory Neil Shapiro ph_map_recv_debug(appdata, text)
566513bd1963SGregory Neil Shapiro 	void *appdata;
566613bd1963SGregory Neil Shapiro # else
566740266059SGregory Neil Shapiro ph_map_recv_debug(text)
566813bd1963SGregory Neil Shapiro # endif
566940266059SGregory Neil Shapiro 	char *text;
567040266059SGregory Neil Shapiro {
567140266059SGregory Neil Shapiro 	if (LogLevel > 10)
567240266059SGregory Neil Shapiro 		sm_syslog(LOG_NOTICE, CurEnv->e_id,
567340266059SGregory Neil Shapiro 			  "ph_map_recv_debug: <== %s", text);
567440266059SGregory Neil Shapiro 	if (tTd(38, 21))
567540266059SGregory Neil Shapiro 		sm_dprintf("ph_map_recv_debug: <== %s\n", text);
567640266059SGregory Neil Shapiro }
567740266059SGregory Neil Shapiro 
567840266059SGregory Neil Shapiro /*
567906f25ae9SGregory Neil Shapiro **  PH_MAP_OPEN -- sub for opening PH map
568006f25ae9SGregory Neil Shapiro */
568106f25ae9SGregory Neil Shapiro bool
ph_map_open(map,mode)568206f25ae9SGregory Neil Shapiro ph_map_open(map, mode)
568306f25ae9SGregory Neil Shapiro 	MAP *map;
568406f25ae9SGregory Neil Shapiro 	int mode;
568506f25ae9SGregory Neil Shapiro {
568606f25ae9SGregory Neil Shapiro 	PH_MAP_STRUCT *pmap;
568740266059SGregory Neil Shapiro 	register SM_EVENT *ev = NULL;
568840266059SGregory Neil Shapiro 	int save_errno = 0;
568940266059SGregory Neil Shapiro 	char *hostlist, *host;
569006f25ae9SGregory Neil Shapiro 
569106f25ae9SGregory Neil Shapiro 	if (tTd(38, 2))
569240266059SGregory Neil Shapiro 		sm_dprintf("ph_map_open(%s)\n", map->map_mname);
569306f25ae9SGregory Neil Shapiro 
569406f25ae9SGregory Neil Shapiro 	mode &= O_ACCMODE;
569506f25ae9SGregory Neil Shapiro 	if (mode != O_RDONLY)
569606f25ae9SGregory Neil Shapiro 	{
569706f25ae9SGregory Neil Shapiro 		/* issue a pseudo-error message */
569840266059SGregory Neil Shapiro 		errno = SM_EMAPCANTWRITE;
569940266059SGregory Neil Shapiro 		return false;
570006f25ae9SGregory Neil Shapiro 	}
570106f25ae9SGregory Neil Shapiro 
570242e5d165SGregory Neil Shapiro 	if (CurEnv != NULL && CurEnv->e_sendmode == SM_DEFER &&
570342e5d165SGregory Neil Shapiro 	    bitset(MF_DEFER, map->map_mflags))
570442e5d165SGregory Neil Shapiro 	{
570542e5d165SGregory Neil Shapiro 		if (tTd(9, 1))
570640266059SGregory Neil Shapiro 			sm_dprintf("ph_map_open(%s) => DEFERRED\n",
570742e5d165SGregory Neil Shapiro 				   map->map_mname);
570842e5d165SGregory Neil Shapiro 
570942e5d165SGregory Neil Shapiro 		/*
571042e5d165SGregory Neil Shapiro 		**  Unset MF_DEFER here so that map_lookup() returns
571142e5d165SGregory Neil Shapiro 		**  a temporary failure using the bogus map and
571242e5d165SGregory Neil Shapiro 		**  map->map_tapp instead of the default permanent error.
571342e5d165SGregory Neil Shapiro 		*/
571442e5d165SGregory Neil Shapiro 
571542e5d165SGregory Neil Shapiro 		map->map_mflags &= ~MF_DEFER;
571640266059SGregory Neil Shapiro 		return false;
571742e5d165SGregory Neil Shapiro 	}
571842e5d165SGregory Neil Shapiro 
571906f25ae9SGregory Neil Shapiro 	pmap = (PH_MAP_STRUCT *)map->map_db1;
572040266059SGregory Neil Shapiro 	pmap->ph_fastclose = 0;		/* refresh field for reopen */
572106f25ae9SGregory Neil Shapiro 
572240266059SGregory Neil Shapiro 	/* try each host in the list */
572306f25ae9SGregory Neil Shapiro 	hostlist = newstr(pmap->ph_servers);
572440266059SGregory Neil Shapiro 	for (host = strtok(hostlist, " ");
572540266059SGregory Neil Shapiro 	     host != NULL;
572640266059SGregory Neil Shapiro 	     host = strtok(NULL, " "))
572706f25ae9SGregory Neil Shapiro 	{
572840266059SGregory Neil Shapiro 		/* set timeout */
572906f25ae9SGregory Neil Shapiro 		if (pmap->ph_timeout != 0)
573006f25ae9SGregory Neil Shapiro 		{
573106f25ae9SGregory Neil Shapiro 			if (setjmp(PHTimeout) != 0)
573206f25ae9SGregory Neil Shapiro 			{
573306f25ae9SGregory Neil Shapiro 				ev = NULL;
573406f25ae9SGregory Neil Shapiro 				if (LogLevel > 1)
573506f25ae9SGregory Neil Shapiro 					sm_syslog(LOG_NOTICE, CurEnv->e_id,
573606f25ae9SGregory Neil Shapiro 						  "timeout connecting to PH server %.100s",
573740266059SGregory Neil Shapiro 						  host);
573806f25ae9SGregory Neil Shapiro 				errno = ETIMEDOUT;
573906f25ae9SGregory Neil Shapiro 				goto ph_map_open_abort;
574006f25ae9SGregory Neil Shapiro 			}
574140266059SGregory Neil Shapiro 			ev = sm_setevent(pmap->ph_timeout, ph_timeout, 0);
574206f25ae9SGregory Neil Shapiro 		}
574306f25ae9SGregory Neil Shapiro 
574440266059SGregory Neil Shapiro 		/* open connection to server */
574513bd1963SGregory Neil Shapiro 		if (ph_open(&(pmap->ph), host,
574613bd1963SGregory Neil Shapiro 			    PH_OPEN_ROUNDROBIN|PH_OPEN_DONTID,
574713bd1963SGregory Neil Shapiro 			    ph_map_send_debug, ph_map_recv_debug
574813bd1963SGregory Neil Shapiro # if NPH_VERSION >= 10200
574913bd1963SGregory Neil Shapiro 			    , NULL
575013bd1963SGregory Neil Shapiro # endif
575113bd1963SGregory Neil Shapiro 			    ) == 0
575213bd1963SGregory Neil Shapiro 		    && ph_id(pmap->ph, phmap_id) == 0)
575340266059SGregory Neil Shapiro 		{
575440266059SGregory Neil Shapiro 			if (ev != NULL)
575540266059SGregory Neil Shapiro 				sm_clrevent(ev);
575640266059SGregory Neil Shapiro 			sm_free(hostlist); /* XXX */
575740266059SGregory Neil Shapiro 			return true;
575840266059SGregory Neil Shapiro 		}
575940266059SGregory Neil Shapiro 
576040266059SGregory Neil Shapiro   ph_map_open_abort:
576140266059SGregory Neil Shapiro 		save_errno = errno;
576240266059SGregory Neil Shapiro 		if (ev != NULL)
576340266059SGregory Neil Shapiro 			sm_clrevent(ev);
576413bd1963SGregory Neil Shapiro 		pmap->ph_fastclose = PH_CLOSE_FAST;
576540266059SGregory Neil Shapiro 		ph_map_close(map);
576606f25ae9SGregory Neil Shapiro 		errno = save_errno;
576740266059SGregory Neil Shapiro 	}
576840266059SGregory Neil Shapiro 
576942e5d165SGregory Neil Shapiro 	if (bitset(MF_NODEFER, map->map_mflags))
577006f25ae9SGregory Neil Shapiro 	{
577142e5d165SGregory Neil Shapiro 		if (errno == 0)
577206f25ae9SGregory Neil Shapiro 			errno = EAGAIN;
577342e5d165SGregory Neil Shapiro 		syserr("ph_map_open: %s: cannot connect to PH server",
577442e5d165SGregory Neil Shapiro 		       map->map_mname);
577506f25ae9SGregory Neil Shapiro 	}
577642e5d165SGregory Neil Shapiro 	else if (!bitset(MF_OPTIONAL, map->map_mflags) && LogLevel > 1)
577706f25ae9SGregory Neil Shapiro 		sm_syslog(LOG_NOTICE, CurEnv->e_id,
577842e5d165SGregory Neil Shapiro 			  "ph_map_open: %s: cannot connect to PH server",
577942e5d165SGregory Neil Shapiro 			  map->map_mname);
578040266059SGregory Neil Shapiro 	sm_free(hostlist); /* XXX */
578140266059SGregory Neil Shapiro 	return false;
578206f25ae9SGregory Neil Shapiro }
578306f25ae9SGregory Neil Shapiro 
578406f25ae9SGregory Neil Shapiro /*
578506f25ae9SGregory Neil Shapiro **  PH_MAP_LOOKUP -- look up key from ph server
578606f25ae9SGregory Neil Shapiro */
578706f25ae9SGregory Neil Shapiro 
578806f25ae9SGregory Neil Shapiro char *
ph_map_lookup(map,key,args,pstat)578906f25ae9SGregory Neil Shapiro ph_map_lookup(map, key, args, pstat)
579006f25ae9SGregory Neil Shapiro 	MAP *map;
579106f25ae9SGregory Neil Shapiro 	char *key;
579206f25ae9SGregory Neil Shapiro 	char **args;
579306f25ae9SGregory Neil Shapiro 	int *pstat;
579406f25ae9SGregory Neil Shapiro {
579540266059SGregory Neil Shapiro 	int i, save_errno = 0;
579640266059SGregory Neil Shapiro 	register SM_EVENT *ev = NULL;
579706f25ae9SGregory Neil Shapiro 	PH_MAP_STRUCT *pmap;
579840266059SGregory Neil Shapiro 	char *value = NULL;
579906f25ae9SGregory Neil Shapiro 
580006f25ae9SGregory Neil Shapiro 	pmap = (PH_MAP_STRUCT *)map->map_db1;
580106f25ae9SGregory Neil Shapiro 
580206f25ae9SGregory Neil Shapiro 	*pstat = EX_OK;
580306f25ae9SGregory Neil Shapiro 
580440266059SGregory Neil Shapiro 	/* set timeout */
580506f25ae9SGregory Neil Shapiro 	if (pmap->ph_timeout != 0)
580606f25ae9SGregory Neil Shapiro 	{
580706f25ae9SGregory Neil Shapiro 		if (setjmp(PHTimeout) != 0)
580806f25ae9SGregory Neil Shapiro 		{
580906f25ae9SGregory Neil Shapiro 			ev = NULL;
581006f25ae9SGregory Neil Shapiro 			if (LogLevel > 1)
581106f25ae9SGregory Neil Shapiro 				sm_syslog(LOG_NOTICE, CurEnv->e_id,
581206f25ae9SGregory Neil Shapiro 					  "timeout during PH lookup of %.100s",
581306f25ae9SGregory Neil Shapiro 					  key);
581406f25ae9SGregory Neil Shapiro 			errno = ETIMEDOUT;
581506f25ae9SGregory Neil Shapiro 			*pstat = EX_TEMPFAIL;
581606f25ae9SGregory Neil Shapiro 			goto ph_map_lookup_abort;
581706f25ae9SGregory Neil Shapiro 		}
581840266059SGregory Neil Shapiro 		ev = sm_setevent(pmap->ph_timeout, ph_timeout, 0);
581906f25ae9SGregory Neil Shapiro 	}
582006f25ae9SGregory Neil Shapiro 
582140266059SGregory Neil Shapiro 	/* perform lookup */
582240266059SGregory Neil Shapiro 	i = ph_email_resolve(pmap->ph, key, pmap->ph_field_list, &value);
582340266059SGregory Neil Shapiro 	if (i == -1)
582406f25ae9SGregory Neil Shapiro 		*pstat = EX_TEMPFAIL;
582513bd1963SGregory Neil Shapiro 	else if (i == PH_ERR_NOMATCH || i == PH_ERR_DATAERR)
582640266059SGregory Neil Shapiro 		*pstat = EX_UNAVAILABLE;
582706f25ae9SGregory Neil Shapiro 
582806f25ae9SGregory Neil Shapiro   ph_map_lookup_abort:
582906f25ae9SGregory Neil Shapiro 	if (ev != NULL)
583040266059SGregory Neil Shapiro 		sm_clrevent(ev);
583106f25ae9SGregory Neil Shapiro 
583206f25ae9SGregory Neil Shapiro 	/*
583340266059SGregory Neil Shapiro 	**  Close the connection if the timer popped
583406f25ae9SGregory Neil Shapiro 	**  or we got a temporary PH error
583506f25ae9SGregory Neil Shapiro 	*/
583606f25ae9SGregory Neil Shapiro 
583706f25ae9SGregory Neil Shapiro 	if (*pstat == EX_TEMPFAIL)
583806f25ae9SGregory Neil Shapiro 	{
583940266059SGregory Neil Shapiro 		save_errno = errno;
584013bd1963SGregory Neil Shapiro 		pmap->ph_fastclose = PH_CLOSE_FAST;
584140266059SGregory Neil Shapiro 		ph_map_close(map);
584240266059SGregory Neil Shapiro 		errno = save_errno;
584306f25ae9SGregory Neil Shapiro 	}
584406f25ae9SGregory Neil Shapiro 
584506f25ae9SGregory Neil Shapiro 	if (*pstat == EX_OK)
584606f25ae9SGregory Neil Shapiro 	{
584706f25ae9SGregory Neil Shapiro 		if (tTd(38,20))
584840266059SGregory Neil Shapiro 			sm_dprintf("ph_map_lookup: %s => %s\n", key, value);
584906f25ae9SGregory Neil Shapiro 
585006f25ae9SGregory Neil Shapiro 		if (bitset(MF_MATCHONLY, map->map_mflags))
585140266059SGregory Neil Shapiro 			return map_rewrite(map, key, strlen(key), NULL);
585206f25ae9SGregory Neil Shapiro 		else
585340266059SGregory Neil Shapiro 			return map_rewrite(map, value, strlen(value), args);
585406f25ae9SGregory Neil Shapiro 	}
585540266059SGregory Neil Shapiro 
585640266059SGregory Neil Shapiro 	return NULL;
585706f25ae9SGregory Neil Shapiro }
585806f25ae9SGregory Neil Shapiro #endif /* PH_MAP */
5859d0cef73dSGregory Neil Shapiro 
586040266059SGregory Neil Shapiro /*
5861c2aa98e2SPeter Wemm **  syslog map
5862c2aa98e2SPeter Wemm */
5863c2aa98e2SPeter Wemm 
5864c2aa98e2SPeter Wemm #define map_prio	map_lockfd	/* overload field */
5865c2aa98e2SPeter Wemm 
5866c2aa98e2SPeter Wemm /*
5867c2aa98e2SPeter Wemm **  SYSLOG_MAP_PARSEARGS -- check for priority level to syslog messages.
5868c2aa98e2SPeter Wemm */
5869c2aa98e2SPeter Wemm 
5870c2aa98e2SPeter Wemm bool
syslog_map_parseargs(map,args)5871c2aa98e2SPeter Wemm syslog_map_parseargs(map, args)
5872c2aa98e2SPeter Wemm 	MAP *map;
5873c2aa98e2SPeter Wemm 	char *args;
5874c2aa98e2SPeter Wemm {
5875c2aa98e2SPeter Wemm 	char *p = args;
5876c2aa98e2SPeter Wemm 	char *priority = NULL;
5877c2aa98e2SPeter Wemm 
587806f25ae9SGregory Neil Shapiro 	/* there is no check whether there is really an argument */
587906f25ae9SGregory Neil Shapiro 	while (*p != '\0')
5880c2aa98e2SPeter Wemm 	{
58815b0945b5SGregory Neil Shapiro 		while (SM_ISSPACE(*p))
5882c2aa98e2SPeter Wemm 			p++;
5883c2aa98e2SPeter Wemm 		if (*p != '-')
5884c2aa98e2SPeter Wemm 			break;
588506f25ae9SGregory Neil Shapiro 		++p;
588606f25ae9SGregory Neil Shapiro 		if (*p == 'D')
588706f25ae9SGregory Neil Shapiro 		{
588806f25ae9SGregory Neil Shapiro 			map->map_mflags |= MF_DEFER;
588906f25ae9SGregory Neil Shapiro 			++p;
589006f25ae9SGregory Neil Shapiro 		}
589106f25ae9SGregory Neil Shapiro 		else if (*p == 'S')
589206f25ae9SGregory Neil Shapiro 		{
589306f25ae9SGregory Neil Shapiro 			map->map_spacesub = *++p;
589406f25ae9SGregory Neil Shapiro 			if (*p != '\0')
589506f25ae9SGregory Neil Shapiro 				p++;
589606f25ae9SGregory Neil Shapiro 		}
589706f25ae9SGregory Neil Shapiro 		else if (*p == 'L')
589806f25ae9SGregory Neil Shapiro 		{
58995b0945b5SGregory Neil Shapiro 			while (*++p != '\0' && SM_ISSPACE(*p))
590006f25ae9SGregory Neil Shapiro 				continue;
590106f25ae9SGregory Neil Shapiro 			if (*p == '\0')
590206f25ae9SGregory Neil Shapiro 				break;
590306f25ae9SGregory Neil Shapiro 			priority = p;
59045b0945b5SGregory Neil Shapiro 			while (*p != '\0' && !(SM_ISSPACE(*p)))
5905c2aa98e2SPeter Wemm 				p++;
5906c2aa98e2SPeter Wemm 			if (*p != '\0')
5907c2aa98e2SPeter Wemm 				*p++ = '\0';
5908c2aa98e2SPeter Wemm 		}
590906f25ae9SGregory Neil Shapiro 		else
591006f25ae9SGregory Neil Shapiro 		{
591106f25ae9SGregory Neil Shapiro 			syserr("Illegal option %c map syslog", *p);
591206f25ae9SGregory Neil Shapiro 			++p;
591306f25ae9SGregory Neil Shapiro 		}
591406f25ae9SGregory Neil Shapiro 	}
5915c2aa98e2SPeter Wemm 
5916c2aa98e2SPeter Wemm 	if (priority == NULL)
5917c2aa98e2SPeter Wemm 		map->map_prio = LOG_INFO;
5918c2aa98e2SPeter Wemm 	else
5919c2aa98e2SPeter Wemm 	{
592040266059SGregory Neil Shapiro 		if (sm_strncasecmp("LOG_", priority, 4) == 0)
5921c2aa98e2SPeter Wemm 			priority += 4;
5922c2aa98e2SPeter Wemm 
5923c2aa98e2SPeter Wemm #ifdef LOG_EMERG
59242fb4f839SGregory Neil Shapiro 		if (SM_STRCASEEQ("EMERG", priority))
5925c2aa98e2SPeter Wemm 			map->map_prio = LOG_EMERG;
5926c2aa98e2SPeter Wemm 		else
59272fb4f839SGregory Neil Shapiro #endif
5928c2aa98e2SPeter Wemm #ifdef LOG_ALERT
59292fb4f839SGregory Neil Shapiro 		if (SM_STRCASEEQ("ALERT", priority))
5930c2aa98e2SPeter Wemm 			map->map_prio = LOG_ALERT;
5931c2aa98e2SPeter Wemm 		else
59322fb4f839SGregory Neil Shapiro #endif
5933c2aa98e2SPeter Wemm #ifdef LOG_CRIT
59342fb4f839SGregory Neil Shapiro 		if (SM_STRCASEEQ("CRIT", priority))
5935c2aa98e2SPeter Wemm 			map->map_prio = LOG_CRIT;
5936c2aa98e2SPeter Wemm 		else
59372fb4f839SGregory Neil Shapiro #endif
5938c2aa98e2SPeter Wemm #ifdef LOG_ERR
59392fb4f839SGregory Neil Shapiro 		if (SM_STRCASEEQ("ERR", priority))
5940c2aa98e2SPeter Wemm 			map->map_prio = LOG_ERR;
5941c2aa98e2SPeter Wemm 		else
59422fb4f839SGregory Neil Shapiro #endif
5943c2aa98e2SPeter Wemm #ifdef LOG_WARNING
59442fb4f839SGregory Neil Shapiro 		if (SM_STRCASEEQ("WARNING", priority))
5945c2aa98e2SPeter Wemm 			map->map_prio = LOG_WARNING;
5946c2aa98e2SPeter Wemm 		else
59472fb4f839SGregory Neil Shapiro #endif
5948c2aa98e2SPeter Wemm #ifdef LOG_NOTICE
59492fb4f839SGregory Neil Shapiro 		if (SM_STRCASEEQ("NOTICE", priority))
5950c2aa98e2SPeter Wemm 			map->map_prio = LOG_NOTICE;
5951c2aa98e2SPeter Wemm 		else
59522fb4f839SGregory Neil Shapiro #endif
5953c2aa98e2SPeter Wemm #ifdef LOG_INFO
59542fb4f839SGregory Neil Shapiro 		if (SM_STRCASEEQ("INFO", priority))
5955c2aa98e2SPeter Wemm 			map->map_prio = LOG_INFO;
5956c2aa98e2SPeter Wemm 		else
59572fb4f839SGregory Neil Shapiro #endif
5958c2aa98e2SPeter Wemm #ifdef LOG_DEBUG
59592fb4f839SGregory Neil Shapiro 		if (SM_STRCASEEQ("DEBUG", priority))
5960c2aa98e2SPeter Wemm 			map->map_prio = LOG_DEBUG;
5961c2aa98e2SPeter Wemm 		else
59622fb4f839SGregory Neil Shapiro #endif
5963c2aa98e2SPeter Wemm 		{
596440266059SGregory Neil Shapiro 			syserr("syslog_map_parseargs: Unknown priority %s",
5965c2aa98e2SPeter Wemm 			       priority);
596640266059SGregory Neil Shapiro 			return false;
5967c2aa98e2SPeter Wemm 		}
5968c2aa98e2SPeter Wemm 	}
59692fb4f839SGregory Neil Shapiro #if _FFR_8BITENVADDR
59702fb4f839SGregory Neil Shapiro 	map->map_mflags |= MF_KEEPXFMT;
59712fb4f839SGregory Neil Shapiro #endif
597240266059SGregory Neil Shapiro 	return true;
5973c2aa98e2SPeter Wemm }
5974c2aa98e2SPeter Wemm 
5975c2aa98e2SPeter Wemm /*
5976c2aa98e2SPeter Wemm **  SYSLOG_MAP_LOOKUP -- rewrite and syslog message.  Always return empty string
5977c2aa98e2SPeter Wemm */
5978c2aa98e2SPeter Wemm 
5979c2aa98e2SPeter Wemm char *
syslog_map_lookup(map,string,args,statp)5980c2aa98e2SPeter Wemm syslog_map_lookup(map, string, args, statp)
5981c2aa98e2SPeter Wemm 	MAP *map;
5982c2aa98e2SPeter Wemm 	char *string;
5983c2aa98e2SPeter Wemm 	char **args;
5984c2aa98e2SPeter Wemm 	int *statp;
5985c2aa98e2SPeter Wemm {
5986c2aa98e2SPeter Wemm 	char *ptr = map_rewrite(map, string, strlen(string), args);
5987c2aa98e2SPeter Wemm 
5988c2aa98e2SPeter Wemm 	if (ptr != NULL)
5989c2aa98e2SPeter Wemm 	{
5990c2aa98e2SPeter Wemm 		if (tTd(38, 20))
599140266059SGregory Neil Shapiro 			sm_dprintf("syslog_map_lookup(%s (priority %d): %s\n",
5992c2aa98e2SPeter Wemm 				map->map_mname, map->map_prio, ptr);
5993c2aa98e2SPeter Wemm 
5994c2aa98e2SPeter Wemm 		sm_syslog(map->map_prio, CurEnv->e_id, "%s", ptr);
5995c2aa98e2SPeter Wemm 	}
5996c2aa98e2SPeter Wemm 
5997c2aa98e2SPeter Wemm 	*statp = EX_OK;
5998c2aa98e2SPeter Wemm 	return "";
5999c2aa98e2SPeter Wemm }
6000c2aa98e2SPeter Wemm 
6001d0cef73dSGregory Neil Shapiro #if _FFR_DPRINTF_MAP
6002d0cef73dSGregory Neil Shapiro /*
6003d0cef73dSGregory Neil Shapiro **  dprintf map
6004d0cef73dSGregory Neil Shapiro */
6005d0cef73dSGregory Neil Shapiro 
6006d0cef73dSGregory Neil Shapiro #define map_dbg_level	map_lockfd	/* overload field */
6007d0cef73dSGregory Neil Shapiro 
6008d0cef73dSGregory Neil Shapiro /*
6009d0cef73dSGregory Neil Shapiro **  DPRINTF_MAP_PARSEARGS -- check for priority level to dprintf messages.
6010d0cef73dSGregory Neil Shapiro */
6011d0cef73dSGregory Neil Shapiro 
6012d0cef73dSGregory Neil Shapiro bool
dprintf_map_parseargs(map,args)6013d0cef73dSGregory Neil Shapiro dprintf_map_parseargs(map, args)
6014d0cef73dSGregory Neil Shapiro 	MAP *map;
6015d0cef73dSGregory Neil Shapiro 	char *args;
6016d0cef73dSGregory Neil Shapiro {
6017d0cef73dSGregory Neil Shapiro 	char *p = args;
6018d0cef73dSGregory Neil Shapiro 	char *dbg_level = NULL;
6019d0cef73dSGregory Neil Shapiro 
6020d0cef73dSGregory Neil Shapiro 	/* there is no check whether there is really an argument */
6021d0cef73dSGregory Neil Shapiro 	while (*p != '\0')
6022d0cef73dSGregory Neil Shapiro 	{
60235b0945b5SGregory Neil Shapiro 		while (SM_ISSPACE(*p))
6024d0cef73dSGregory Neil Shapiro 			p++;
6025d0cef73dSGregory Neil Shapiro 		if (*p != '-')
6026d0cef73dSGregory Neil Shapiro 			break;
6027d0cef73dSGregory Neil Shapiro 		++p;
6028d0cef73dSGregory Neil Shapiro 		if (*p == 'D')
6029d0cef73dSGregory Neil Shapiro 		{
6030d0cef73dSGregory Neil Shapiro 			map->map_mflags |= MF_DEFER;
6031d0cef73dSGregory Neil Shapiro 			++p;
6032d0cef73dSGregory Neil Shapiro 		}
6033d0cef73dSGregory Neil Shapiro 		else if (*p == 'S')
6034d0cef73dSGregory Neil Shapiro 		{
6035d0cef73dSGregory Neil Shapiro 			map->map_spacesub = *++p;
6036d0cef73dSGregory Neil Shapiro 			if (*p != '\0')
6037d0cef73dSGregory Neil Shapiro 				p++;
6038d0cef73dSGregory Neil Shapiro 		}
6039d0cef73dSGregory Neil Shapiro 		else if (*p == 'd')
6040d0cef73dSGregory Neil Shapiro 		{
60415b0945b5SGregory Neil Shapiro 			while (*++p != '\0' && SM_ISSPACE(*p))
6042d0cef73dSGregory Neil Shapiro 				continue;
6043d0cef73dSGregory Neil Shapiro 			if (*p == '\0')
6044d0cef73dSGregory Neil Shapiro 				break;
6045d0cef73dSGregory Neil Shapiro 			dbg_level = p;
60465b0945b5SGregory Neil Shapiro 			while (*p != '\0' && !(SM_ISSPACE(*p)))
6047d0cef73dSGregory Neil Shapiro 				p++;
6048d0cef73dSGregory Neil Shapiro 			if (*p != '\0')
6049d0cef73dSGregory Neil Shapiro 				*p++ = '\0';
6050d0cef73dSGregory Neil Shapiro 		}
6051d0cef73dSGregory Neil Shapiro 		else
6052d0cef73dSGregory Neil Shapiro 		{
6053d0cef73dSGregory Neil Shapiro 			syserr("Illegal option %c map dprintf", *p);
6054d0cef73dSGregory Neil Shapiro 			++p;
6055d0cef73dSGregory Neil Shapiro 		}
6056d0cef73dSGregory Neil Shapiro 	}
6057d0cef73dSGregory Neil Shapiro 
6058d0cef73dSGregory Neil Shapiro 	if (dbg_level == NULL)
6059d0cef73dSGregory Neil Shapiro 		map->map_dbg_level = 0;
6060d0cef73dSGregory Neil Shapiro 	else
6061d0cef73dSGregory Neil Shapiro 	{
6062d0cef73dSGregory Neil Shapiro 		if (!(isascii(*dbg_level) && isdigit(*dbg_level)))
6063d0cef73dSGregory Neil Shapiro 		{
6064d0cef73dSGregory Neil Shapiro 			syserr("dprintf map \"%s\", file %s: -d should specify a number, not %s",
6065d0cef73dSGregory Neil Shapiro 				map->map_mname, map->map_file,
6066d0cef73dSGregory Neil Shapiro 				dbg_level);
6067d0cef73dSGregory Neil Shapiro 			return false;
6068d0cef73dSGregory Neil Shapiro 		}
6069d0cef73dSGregory Neil Shapiro 		map->map_dbg_level = atoi(dbg_level);
6070d0cef73dSGregory Neil Shapiro 	}
60712fb4f839SGregory Neil Shapiro # if _FFR_8BITENVADDR
60722fb4f839SGregory Neil Shapiro 	map->map_mflags |= MF_KEEPXFMT;
60732fb4f839SGregory Neil Shapiro # endif
6074d0cef73dSGregory Neil Shapiro 	return true;
6075d0cef73dSGregory Neil Shapiro }
6076d0cef73dSGregory Neil Shapiro 
6077d0cef73dSGregory Neil Shapiro /*
6078d0cef73dSGregory Neil Shapiro **  DPRINTF_MAP_LOOKUP -- rewrite and print message.  Always return empty string
6079d0cef73dSGregory Neil Shapiro */
6080d0cef73dSGregory Neil Shapiro 
6081d0cef73dSGregory Neil Shapiro char *
dprintf_map_lookup(map,string,args,statp)6082d0cef73dSGregory Neil Shapiro dprintf_map_lookup(map, string, args, statp)
6083d0cef73dSGregory Neil Shapiro 	MAP *map;
6084d0cef73dSGregory Neil Shapiro 	char *string;
6085d0cef73dSGregory Neil Shapiro 	char **args;
6086d0cef73dSGregory Neil Shapiro 	int *statp;
6087d0cef73dSGregory Neil Shapiro {
6088d0cef73dSGregory Neil Shapiro 	char *ptr = map_rewrite(map, string, strlen(string), args);
6089d0cef73dSGregory Neil Shapiro 
6090d0cef73dSGregory Neil Shapiro 	if (ptr != NULL && tTd(85, map->map_dbg_level))
6091d0cef73dSGregory Neil Shapiro 		sm_dprintf("%s\n", ptr);
6092d0cef73dSGregory Neil Shapiro 	*statp = EX_OK;
6093d0cef73dSGregory Neil Shapiro 	return "";
6094d0cef73dSGregory Neil Shapiro }
6095d0cef73dSGregory Neil Shapiro #endif /* _FFR_DPRINTF_MAP */
6096d0cef73dSGregory Neil Shapiro 
609740266059SGregory Neil Shapiro /*
6098c2aa98e2SPeter Wemm **  HESIOD Modules
6099c2aa98e2SPeter Wemm */
6100c2aa98e2SPeter Wemm 
610140266059SGregory Neil Shapiro #if HESIOD
6102c2aa98e2SPeter Wemm 
6103c2aa98e2SPeter Wemm bool
hes_map_open(map,mode)6104c2aa98e2SPeter Wemm hes_map_open(map, mode)
6105c2aa98e2SPeter Wemm 	MAP *map;
6106c2aa98e2SPeter Wemm 	int mode;
6107c2aa98e2SPeter Wemm {
6108c2aa98e2SPeter Wemm 	if (tTd(38, 2))
610940266059SGregory Neil Shapiro 		sm_dprintf("hes_map_open(%s, %s, %d)\n",
6110c2aa98e2SPeter Wemm 			map->map_mname, map->map_file, mode);
6111c2aa98e2SPeter Wemm 
6112c2aa98e2SPeter Wemm 	if (mode != O_RDONLY)
6113c2aa98e2SPeter Wemm 	{
6114c2aa98e2SPeter Wemm 		/* issue a pseudo-error message */
611540266059SGregory Neil Shapiro 		errno = SM_EMAPCANTWRITE;
611640266059SGregory Neil Shapiro 		return false;
6117c2aa98e2SPeter Wemm 	}
6118c2aa98e2SPeter Wemm 
6119c2aa98e2SPeter Wemm # ifdef HESIOD_INIT
6120c2aa98e2SPeter Wemm 	if (HesiodContext != NULL || hesiod_init(&HesiodContext) == 0)
612140266059SGregory Neil Shapiro 		return true;
6122c2aa98e2SPeter Wemm 
6123c2aa98e2SPeter Wemm 	if (!bitset(MF_OPTIONAL, map->map_mflags))
6124605302a5SGregory Neil Shapiro 		syserr("451 4.3.5 cannot initialize Hesiod map (%s)",
612540266059SGregory Neil Shapiro 			sm_errstring(errno));
612640266059SGregory Neil Shapiro 	return false;
612706f25ae9SGregory Neil Shapiro # else /* HESIOD_INIT */
6128c2aa98e2SPeter Wemm 	if (hes_error() == HES_ER_UNINIT)
6129c2aa98e2SPeter Wemm 		hes_init();
6130c2aa98e2SPeter Wemm 	switch (hes_error())
6131c2aa98e2SPeter Wemm 	{
6132c2aa98e2SPeter Wemm 	  case HES_ER_OK:
6133c2aa98e2SPeter Wemm 	  case HES_ER_NOTFOUND:
613440266059SGregory Neil Shapiro 		return true;
6135c2aa98e2SPeter Wemm 	}
6136c2aa98e2SPeter Wemm 
6137c2aa98e2SPeter Wemm 	if (!bitset(MF_OPTIONAL, map->map_mflags))
6138605302a5SGregory Neil Shapiro 		syserr("451 4.3.5 cannot initialize Hesiod map (%d)", hes_error());
6139c2aa98e2SPeter Wemm 
614040266059SGregory Neil Shapiro 	return false;
6141c2aa98e2SPeter Wemm # endif /* HESIOD_INIT */
6142c2aa98e2SPeter Wemm }
6143c2aa98e2SPeter Wemm 
6144c2aa98e2SPeter Wemm char *
hes_map_lookup(map,name,av,statp)6145c2aa98e2SPeter Wemm hes_map_lookup(map, name, av, statp)
6146c2aa98e2SPeter Wemm 	MAP *map;
6147c2aa98e2SPeter Wemm 	char *name;
6148c2aa98e2SPeter Wemm 	char **av;
6149c2aa98e2SPeter Wemm 	int *statp;
6150c2aa98e2SPeter Wemm {
6151c2aa98e2SPeter Wemm 	char **hp;
6152c2aa98e2SPeter Wemm 
6153c2aa98e2SPeter Wemm 	if (tTd(38, 20))
615440266059SGregory Neil Shapiro 		sm_dprintf("hes_map_lookup(%s, %s)\n", map->map_file, name);
6155c2aa98e2SPeter Wemm 
6156c2aa98e2SPeter Wemm 	if (name[0] == '\\')
6157c2aa98e2SPeter Wemm 	{
6158c2aa98e2SPeter Wemm 		char *np;
6159c2aa98e2SPeter Wemm 		int nl;
61608774250cSGregory Neil Shapiro 		int save_errno;
61612fb4f839SGregory Neil Shapiro 		char nbuf[MAXNAME]; /* EAI:ok - larger buffer used if needed */
6162c2aa98e2SPeter Wemm 
6163c2aa98e2SPeter Wemm 		nl = strlen(name);
6164d0cef73dSGregory Neil Shapiro 		if (nl < sizeof(nbuf) - 1)
6165c2aa98e2SPeter Wemm 			np = nbuf;
6166c2aa98e2SPeter Wemm 		else
61672fb4f839SGregory Neil Shapiro 			np = xalloc(nl + 2);
6168c2aa98e2SPeter Wemm 		np[0] = '\\';
61692fb4f839SGregory Neil Shapiro 		(void) sm_strlcpy(&np[1], name, sizeof(nbuf) - 1);
6170c2aa98e2SPeter Wemm # ifdef HESIOD_INIT
6171c2aa98e2SPeter Wemm 		hp = hesiod_resolve(HesiodContext, np, map->map_file);
61725b0945b5SGregory Neil Shapiro # else
6173c2aa98e2SPeter Wemm 		hp = hes_resolve(np, map->map_file);
61742fb4f839SGregory Neil Shapiro # endif
61758774250cSGregory Neil Shapiro 		save_errno = errno;
6176c2aa98e2SPeter Wemm 		if (np != nbuf)
61772fb4f839SGregory Neil Shapiro 			SM_FREE(np); /* XXX */
61788774250cSGregory Neil Shapiro 		errno = save_errno;
6179c2aa98e2SPeter Wemm 	}
6180c2aa98e2SPeter Wemm 	else
6181c2aa98e2SPeter Wemm 	{
6182c2aa98e2SPeter Wemm # ifdef HESIOD_INIT
6183c2aa98e2SPeter Wemm 		hp = hesiod_resolve(HesiodContext, name, map->map_file);
61845b0945b5SGregory Neil Shapiro # else
6185c2aa98e2SPeter Wemm 		hp = hes_resolve(name, map->map_file);
6186c2aa98e2SPeter Wemm # endif /* HESIOD_INIT */
6187c2aa98e2SPeter Wemm 	}
6188c2aa98e2SPeter Wemm # ifdef HESIOD_INIT
61898774250cSGregory Neil Shapiro 	if (hp == NULL || *hp == NULL)
6190c2aa98e2SPeter Wemm 	{
6191c2aa98e2SPeter Wemm 		switch (errno)
6192c2aa98e2SPeter Wemm 		{
6193c2aa98e2SPeter Wemm 		  case ENOENT:
6194c2aa98e2SPeter Wemm 			  *statp = EX_NOTFOUND;
6195c2aa98e2SPeter Wemm 			  break;
6196c2aa98e2SPeter Wemm 		  case ECONNREFUSED:
6197c2aa98e2SPeter Wemm 			  *statp = EX_TEMPFAIL;
6198c2aa98e2SPeter Wemm 			  break;
619940266059SGregory Neil Shapiro 		  case EMSGSIZE:
6200c2aa98e2SPeter Wemm 		  case ENOMEM:
6201c2aa98e2SPeter Wemm 		  default:
6202c2aa98e2SPeter Wemm 			  *statp = EX_UNAVAILABLE;
6203c2aa98e2SPeter Wemm 			  break;
6204c2aa98e2SPeter Wemm 		}
6205c86d5965SGregory Neil Shapiro 		if (hp != NULL)
62068774250cSGregory Neil Shapiro 			hesiod_free_list(HesiodContext, hp);
6207c2aa98e2SPeter Wemm 		return NULL;
6208c2aa98e2SPeter Wemm 	}
620906f25ae9SGregory Neil Shapiro # else /* HESIOD_INIT */
6210c2aa98e2SPeter Wemm 	if (hp == NULL || hp[0] == NULL)
6211c2aa98e2SPeter Wemm 	{
6212c2aa98e2SPeter Wemm 		switch (hes_error())
6213c2aa98e2SPeter Wemm 		{
6214c2aa98e2SPeter Wemm 		  case HES_ER_OK:
6215c2aa98e2SPeter Wemm 			*statp = EX_OK;
6216c2aa98e2SPeter Wemm 			break;
6217c2aa98e2SPeter Wemm 
6218c2aa98e2SPeter Wemm 		  case HES_ER_NOTFOUND:
6219c2aa98e2SPeter Wemm 			*statp = EX_NOTFOUND;
6220c2aa98e2SPeter Wemm 			break;
6221c2aa98e2SPeter Wemm 
6222c2aa98e2SPeter Wemm 		  case HES_ER_CONFIG:
6223c2aa98e2SPeter Wemm 			*statp = EX_UNAVAILABLE;
6224c2aa98e2SPeter Wemm 			break;
6225c2aa98e2SPeter Wemm 
6226c2aa98e2SPeter Wemm 		  case HES_ER_NET:
6227c2aa98e2SPeter Wemm 			*statp = EX_TEMPFAIL;
6228c2aa98e2SPeter Wemm 			break;
6229c2aa98e2SPeter Wemm 		}
6230c2aa98e2SPeter Wemm 		return NULL;
6231c2aa98e2SPeter Wemm 	}
6232c2aa98e2SPeter Wemm # endif /* HESIOD_INIT */
6233c2aa98e2SPeter Wemm 
6234c2aa98e2SPeter Wemm 	if (bitset(MF_MATCHONLY, map->map_mflags))
6235c2aa98e2SPeter Wemm 		return map_rewrite(map, name, strlen(name), NULL);
6236c2aa98e2SPeter Wemm 	else
6237c2aa98e2SPeter Wemm 		return map_rewrite(map, hp[0], strlen(hp[0]), av);
6238c2aa98e2SPeter Wemm }
6239c2aa98e2SPeter Wemm 
624040266059SGregory Neil Shapiro /*
624140266059SGregory Neil Shapiro **  HES_MAP_CLOSE -- free the Hesiod context
624240266059SGregory Neil Shapiro */
624340266059SGregory Neil Shapiro 
624440266059SGregory Neil Shapiro void
hes_map_close(map)624540266059SGregory Neil Shapiro hes_map_close(map)
624640266059SGregory Neil Shapiro 	MAP *map;
624740266059SGregory Neil Shapiro {
624840266059SGregory Neil Shapiro 	if (tTd(38, 20))
624940266059SGregory Neil Shapiro 		sm_dprintf("hes_map_close(%s)\n", map->map_file);
625040266059SGregory Neil Shapiro 
625140266059SGregory Neil Shapiro # ifdef HESIOD_INIT
625240266059SGregory Neil Shapiro 	/* Free the hesiod context */
625340266059SGregory Neil Shapiro 	if (HesiodContext != NULL)
625440266059SGregory Neil Shapiro 	{
625540266059SGregory Neil Shapiro 		hesiod_end(HesiodContext);
625640266059SGregory Neil Shapiro 		HesiodContext = NULL;
625740266059SGregory Neil Shapiro 	}
625840266059SGregory Neil Shapiro # endif /* HESIOD_INIT */
625940266059SGregory Neil Shapiro }
626040266059SGregory Neil Shapiro 
626106f25ae9SGregory Neil Shapiro #endif /* HESIOD */
626240266059SGregory Neil Shapiro /*
6263c2aa98e2SPeter Wemm **  NeXT NETINFO Modules
6264c2aa98e2SPeter Wemm */
6265c2aa98e2SPeter Wemm 
6266c2aa98e2SPeter Wemm #if NETINFO
6267c2aa98e2SPeter Wemm 
6268c2aa98e2SPeter Wemm # define NETINFO_DEFAULT_DIR		"/aliases"
6269c2aa98e2SPeter Wemm # define NETINFO_DEFAULT_PROPERTY	"members"
6270c2aa98e2SPeter Wemm 
6271c2aa98e2SPeter Wemm /*
6272c2aa98e2SPeter Wemm **  NI_MAP_OPEN -- open NetInfo Aliases
6273c2aa98e2SPeter Wemm */
6274c2aa98e2SPeter Wemm 
6275c2aa98e2SPeter Wemm bool
ni_map_open(map,mode)6276c2aa98e2SPeter Wemm ni_map_open(map, mode)
6277c2aa98e2SPeter Wemm 	MAP *map;
6278c2aa98e2SPeter Wemm 	int mode;
6279c2aa98e2SPeter Wemm {
6280c2aa98e2SPeter Wemm 	if (tTd(38, 2))
628140266059SGregory Neil Shapiro 		sm_dprintf("ni_map_open(%s, %s, %d)\n",
6282c2aa98e2SPeter Wemm 			map->map_mname, map->map_file, mode);
6283c2aa98e2SPeter Wemm 	mode &= O_ACCMODE;
6284c2aa98e2SPeter Wemm 
6285c2aa98e2SPeter Wemm 	if (*map->map_file == '\0')
6286c2aa98e2SPeter Wemm 		map->map_file = NETINFO_DEFAULT_DIR;
6287c2aa98e2SPeter Wemm 
6288c2aa98e2SPeter Wemm 	if (map->map_valcolnm == NULL)
6289c2aa98e2SPeter Wemm 		map->map_valcolnm = NETINFO_DEFAULT_PROPERTY;
6290c2aa98e2SPeter Wemm 
629140266059SGregory Neil Shapiro 	if (map->map_coldelim == '\0')
629240266059SGregory Neil Shapiro 	{
629340266059SGregory Neil Shapiro 		if (bitset(MF_ALIAS, map->map_mflags))
6294c2aa98e2SPeter Wemm 			map->map_coldelim = ',';
629540266059SGregory Neil Shapiro 		else if (bitset(MF_FILECLASS, map->map_mflags))
629640266059SGregory Neil Shapiro 			map->map_coldelim = ' ';
629740266059SGregory Neil Shapiro 	}
629840266059SGregory Neil Shapiro 	return true;
6299c2aa98e2SPeter Wemm }
6300c2aa98e2SPeter Wemm 
6301c2aa98e2SPeter Wemm 
6302c2aa98e2SPeter Wemm /*
6303c2aa98e2SPeter Wemm **  NI_MAP_LOOKUP -- look up a datum in NetInfo
6304c2aa98e2SPeter Wemm */
6305c2aa98e2SPeter Wemm 
6306c2aa98e2SPeter Wemm char *
ni_map_lookup(map,name,av,statp)6307c2aa98e2SPeter Wemm ni_map_lookup(map, name, av, statp)
6308c2aa98e2SPeter Wemm 	MAP *map;
6309c2aa98e2SPeter Wemm 	char *name;
6310c2aa98e2SPeter Wemm 	char **av;
6311c2aa98e2SPeter Wemm 	int *statp;
6312c2aa98e2SPeter Wemm {
6313c2aa98e2SPeter Wemm 	char *res;
6314c2aa98e2SPeter Wemm 	char *propval;
6315c2aa98e2SPeter Wemm 
6316c2aa98e2SPeter Wemm 	if (tTd(38, 20))
631740266059SGregory Neil Shapiro 		sm_dprintf("ni_map_lookup(%s, %s)\n", map->map_mname, name);
6318c2aa98e2SPeter Wemm 
6319c2aa98e2SPeter Wemm 	propval = ni_propval(map->map_file, map->map_keycolnm, name,
6320c2aa98e2SPeter Wemm 			     map->map_valcolnm, map->map_coldelim);
6321c2aa98e2SPeter Wemm 
6322c2aa98e2SPeter Wemm 	if (propval == NULL)
6323c2aa98e2SPeter Wemm 		return NULL;
6324c2aa98e2SPeter Wemm 
632540266059SGregory Neil Shapiro 	SM_TRY
6326c2aa98e2SPeter Wemm 		if (bitset(MF_MATCHONLY, map->map_mflags))
6327c2aa98e2SPeter Wemm 			res = map_rewrite(map, name, strlen(name), NULL);
6328c2aa98e2SPeter Wemm 		else
6329c2aa98e2SPeter Wemm 			res = map_rewrite(map, propval, strlen(propval), av);
633040266059SGregory Neil Shapiro 	SM_FINALLY
63318774250cSGregory Neil Shapiro 		sm_free(propval);
633240266059SGregory Neil Shapiro 	SM_END_TRY
6333c2aa98e2SPeter Wemm 	return res;
6334c2aa98e2SPeter Wemm }
6335c2aa98e2SPeter Wemm 
6336c2aa98e2SPeter Wemm 
633706f25ae9SGregory Neil Shapiro static bool
ni_getcanonname(name,hbsize,statp)6338c2aa98e2SPeter Wemm ni_getcanonname(name, hbsize, statp)
6339c2aa98e2SPeter Wemm 	char *name;
6340c2aa98e2SPeter Wemm 	int hbsize;
6341c2aa98e2SPeter Wemm 	int *statp;
6342c2aa98e2SPeter Wemm {
6343c2aa98e2SPeter Wemm 	char *vptr;
6344c2aa98e2SPeter Wemm 	char *ptr;
63452fb4f839SGregory Neil Shapiro 	char nbuf[MAXNAME + 1];	/* EAI:hostname */
6346c2aa98e2SPeter Wemm 
6347c2aa98e2SPeter Wemm 	if (tTd(38, 20))
634840266059SGregory Neil Shapiro 		sm_dprintf("ni_getcanonname(%s)\n", name);
6349c2aa98e2SPeter Wemm 
6350d0cef73dSGregory Neil Shapiro 	if (sm_strlcpy(nbuf, name, sizeof(nbuf)) >= sizeof(nbuf))
6351c2aa98e2SPeter Wemm 	{
6352c2aa98e2SPeter Wemm 		*statp = EX_UNAVAILABLE;
635340266059SGregory Neil Shapiro 		return false;
6354c2aa98e2SPeter Wemm 	}
6355602a2b1bSGregory Neil Shapiro 	(void) shorten_hostname(nbuf);
6356c2aa98e2SPeter Wemm 
6357c2aa98e2SPeter Wemm 	/* we only accept single token search key */
6358c2aa98e2SPeter Wemm 	if (strchr(nbuf, '.'))
6359c2aa98e2SPeter Wemm 	{
6360c2aa98e2SPeter Wemm 		*statp = EX_NOHOST;
636140266059SGregory Neil Shapiro 		return false;
6362c2aa98e2SPeter Wemm 	}
6363c2aa98e2SPeter Wemm 
6364c2aa98e2SPeter Wemm 	/* Do the search */
6365c2aa98e2SPeter Wemm 	vptr = ni_propval("/machines", NULL, nbuf, "name", '\n');
6366c2aa98e2SPeter Wemm 
6367c2aa98e2SPeter Wemm 	if (vptr == NULL)
6368c2aa98e2SPeter Wemm 	{
6369c2aa98e2SPeter Wemm 		*statp = EX_NOHOST;
637040266059SGregory Neil Shapiro 		return false;
6371c2aa98e2SPeter Wemm 	}
6372c2aa98e2SPeter Wemm 
6373c2aa98e2SPeter Wemm 	/* Only want the first machine name */
6374c2aa98e2SPeter Wemm 	if ((ptr = strchr(vptr, '\n')) != NULL)
6375c2aa98e2SPeter Wemm 		*ptr = '\0';
6376c2aa98e2SPeter Wemm 
637740266059SGregory Neil Shapiro 	if (sm_strlcpy(name, vptr, hbsize) >= hbsize)
6378c2aa98e2SPeter Wemm 	{
637940266059SGregory Neil Shapiro 		sm_free(vptr);
638040266059SGregory Neil Shapiro 		*statp = EX_UNAVAILABLE;
638140266059SGregory Neil Shapiro 		return true;
638240266059SGregory Neil Shapiro 	}
63838774250cSGregory Neil Shapiro 	sm_free(vptr);
6384c2aa98e2SPeter Wemm 	*statp = EX_OK;
638540266059SGregory Neil Shapiro 	return false;
6386c2aa98e2SPeter Wemm }
6387065a643dSPeter Wemm #endif /* NETINFO */
638840266059SGregory Neil Shapiro /*
6389c2aa98e2SPeter Wemm **  TEXT (unindexed text file) Modules
6390c2aa98e2SPeter Wemm **
6391c2aa98e2SPeter Wemm **	This code donated by Sun Microsystems.
6392c2aa98e2SPeter Wemm */
6393c2aa98e2SPeter Wemm 
6394c2aa98e2SPeter Wemm #define map_sff		map_lockfd	/* overload field */
6395c2aa98e2SPeter Wemm 
6396c2aa98e2SPeter Wemm 
6397c2aa98e2SPeter Wemm /*
6398c2aa98e2SPeter Wemm **  TEXT_MAP_OPEN -- open text table
6399c2aa98e2SPeter Wemm */
6400c2aa98e2SPeter Wemm 
6401c2aa98e2SPeter Wemm bool
text_map_open(map,mode)6402c2aa98e2SPeter Wemm text_map_open(map, mode)
6403c2aa98e2SPeter Wemm 	MAP *map;
6404c2aa98e2SPeter Wemm 	int mode;
6405c2aa98e2SPeter Wemm {
640606f25ae9SGregory Neil Shapiro 	long sff;
6407c2aa98e2SPeter Wemm 	int i;
6408c2aa98e2SPeter Wemm 
6409c2aa98e2SPeter Wemm 	if (tTd(38, 2))
641040266059SGregory Neil Shapiro 		sm_dprintf("text_map_open(%s, %s, %d)\n",
6411c2aa98e2SPeter Wemm 			map->map_mname, map->map_file, mode);
6412c2aa98e2SPeter Wemm 
6413c2aa98e2SPeter Wemm 	mode &= O_ACCMODE;
6414c2aa98e2SPeter Wemm 	if (mode != O_RDONLY)
6415c2aa98e2SPeter Wemm 	{
6416c2aa98e2SPeter Wemm 		errno = EPERM;
641740266059SGregory Neil Shapiro 		return false;
6418c2aa98e2SPeter Wemm 	}
6419c2aa98e2SPeter Wemm 
6420c2aa98e2SPeter Wemm 	if (*map->map_file == '\0')
6421c2aa98e2SPeter Wemm 	{
6422c2aa98e2SPeter Wemm 		syserr("text map \"%s\": file name required",
6423c2aa98e2SPeter Wemm 			map->map_mname);
642440266059SGregory Neil Shapiro 		return false;
6425c2aa98e2SPeter Wemm 	}
6426c2aa98e2SPeter Wemm 
6427c2aa98e2SPeter Wemm 	if (map->map_file[0] != '/')
6428c2aa98e2SPeter Wemm 	{
6429c2aa98e2SPeter Wemm 		syserr("text map \"%s\": file name must be fully qualified",
6430c2aa98e2SPeter Wemm 			map->map_mname);
643140266059SGregory Neil Shapiro 		return false;
6432c2aa98e2SPeter Wemm 	}
6433c2aa98e2SPeter Wemm 
6434c2aa98e2SPeter Wemm 	sff = SFF_ROOTOK|SFF_REGONLY;
643506f25ae9SGregory Neil Shapiro 	if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail))
6436c2aa98e2SPeter Wemm 		sff |= SFF_NOWLINK;
643706f25ae9SGregory Neil Shapiro 	if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail))
6438c2aa98e2SPeter Wemm 		sff |= SFF_SAFEDIRPATH;
6439c2aa98e2SPeter Wemm 	if ((i = safefile(map->map_file, RunAsUid, RunAsGid, RunAsUserName,
6440c2aa98e2SPeter Wemm 			  sff, S_IRUSR, NULL)) != 0)
6441c2aa98e2SPeter Wemm 	{
644206f25ae9SGregory Neil Shapiro 		int save_errno = errno;
644306f25ae9SGregory Neil Shapiro 
6444c2aa98e2SPeter Wemm 		/* cannot open this map */
6445c2aa98e2SPeter Wemm 		if (tTd(38, 2))
644640266059SGregory Neil Shapiro 			sm_dprintf("\tunsafe map file: %d\n", i);
644706f25ae9SGregory Neil Shapiro 		errno = save_errno;
6448c2aa98e2SPeter Wemm 		if (!bitset(MF_OPTIONAL, map->map_mflags))
6449c2aa98e2SPeter Wemm 			syserr("text map \"%s\": unsafe map file %s",
6450c2aa98e2SPeter Wemm 				map->map_mname, map->map_file);
645140266059SGregory Neil Shapiro 		return false;
6452c2aa98e2SPeter Wemm 	}
6453c2aa98e2SPeter Wemm 
6454c2aa98e2SPeter Wemm 	if (map->map_keycolnm == NULL)
6455c2aa98e2SPeter Wemm 		map->map_keycolno = 0;
6456c2aa98e2SPeter Wemm 	else
6457c2aa98e2SPeter Wemm 	{
6458c2aa98e2SPeter Wemm 		if (!(isascii(*map->map_keycolnm) && isdigit(*map->map_keycolnm)))
6459c2aa98e2SPeter Wemm 		{
6460c2aa98e2SPeter Wemm 			syserr("text map \"%s\", file %s: -k should specify a number, not %s",
6461c2aa98e2SPeter Wemm 				map->map_mname, map->map_file,
6462c2aa98e2SPeter Wemm 				map->map_keycolnm);
646340266059SGregory Neil Shapiro 			return false;
6464c2aa98e2SPeter Wemm 		}
6465c2aa98e2SPeter Wemm 		map->map_keycolno = atoi(map->map_keycolnm);
6466c2aa98e2SPeter Wemm 	}
6467c2aa98e2SPeter Wemm 
6468c2aa98e2SPeter Wemm 	if (map->map_valcolnm == NULL)
6469c2aa98e2SPeter Wemm 		map->map_valcolno = 0;
6470c2aa98e2SPeter Wemm 	else
6471c2aa98e2SPeter Wemm 	{
6472c2aa98e2SPeter Wemm 		if (!(isascii(*map->map_valcolnm) && isdigit(*map->map_valcolnm)))
6473c2aa98e2SPeter Wemm 		{
6474c2aa98e2SPeter Wemm 			syserr("text map \"%s\", file %s: -v should specify a number, not %s",
6475c2aa98e2SPeter Wemm 					map->map_mname, map->map_file,
6476c2aa98e2SPeter Wemm 					map->map_valcolnm);
647740266059SGregory Neil Shapiro 			return false;
6478c2aa98e2SPeter Wemm 		}
6479c2aa98e2SPeter Wemm 		map->map_valcolno = atoi(map->map_valcolnm);
6480c2aa98e2SPeter Wemm 	}
6481c2aa98e2SPeter Wemm 
6482c2aa98e2SPeter Wemm 	if (tTd(38, 2))
6483c2aa98e2SPeter Wemm 	{
648440266059SGregory Neil Shapiro 		sm_dprintf("text_map_open(%s, %s): delimiter = ",
6485c2aa98e2SPeter Wemm 			map->map_mname, map->map_file);
6486c2aa98e2SPeter Wemm 		if (map->map_coldelim == '\0')
648740266059SGregory Neil Shapiro 			sm_dprintf("(white space)\n");
6488c2aa98e2SPeter Wemm 		else
648940266059SGregory Neil Shapiro 			sm_dprintf("%c\n", map->map_coldelim);
6490c2aa98e2SPeter Wemm 	}
6491c2aa98e2SPeter Wemm 
6492c2aa98e2SPeter Wemm 	map->map_sff = sff;
649340266059SGregory Neil Shapiro 	return true;
6494c2aa98e2SPeter Wemm }
6495c2aa98e2SPeter Wemm 
6496c2aa98e2SPeter Wemm 
6497c2aa98e2SPeter Wemm /*
6498c2aa98e2SPeter Wemm **  TEXT_MAP_LOOKUP -- look up a datum in a TEXT table
6499c2aa98e2SPeter Wemm */
6500c2aa98e2SPeter Wemm 
6501c2aa98e2SPeter Wemm char *
text_map_lookup(map,name,av,statp)6502c2aa98e2SPeter Wemm text_map_lookup(map, name, av, statp)
6503c2aa98e2SPeter Wemm 	MAP *map;
6504c2aa98e2SPeter Wemm 	char *name;
6505c2aa98e2SPeter Wemm 	char **av;
6506c2aa98e2SPeter Wemm 	int *statp;
6507c2aa98e2SPeter Wemm {
6508c2aa98e2SPeter Wemm 	char *vp;
6509c2aa98e2SPeter Wemm 	auto int vsize;
6510c2aa98e2SPeter Wemm 	int buflen;
651140266059SGregory Neil Shapiro 	SM_FILE_T *f;
6512c2aa98e2SPeter Wemm 	char delim;
6513c2aa98e2SPeter Wemm 	int key_idx;
6514c2aa98e2SPeter Wemm 	bool found_it;
651506f25ae9SGregory Neil Shapiro 	long sff = map->map_sff;
65162fb4f839SGregory Neil Shapiro 	char search_key[MAXNAME + 1];	/* EAI:ok */
6517c2aa98e2SPeter Wemm 	char linebuf[MAXLINE];
65182fb4f839SGregory Neil Shapiro 	char buf[MAXNAME + 1];	/* EAI:ok */
6519c2aa98e2SPeter Wemm 
652040266059SGregory Neil Shapiro 	found_it = false;
6521c2aa98e2SPeter Wemm 	if (tTd(38, 20))
652240266059SGregory Neil Shapiro 		sm_dprintf("text_map_lookup(%s, %s)\n", map->map_mname, name);
6523c2aa98e2SPeter Wemm 
6524c2aa98e2SPeter Wemm 	buflen = strlen(name);
6525d0cef73dSGregory Neil Shapiro 	if (buflen > sizeof(search_key) - 1)
6526d0cef73dSGregory Neil Shapiro 		buflen = sizeof(search_key) - 1;	/* XXX just cut if off? */
652706f25ae9SGregory Neil Shapiro 	memmove(search_key, name, buflen);
6528c2aa98e2SPeter Wemm 	search_key[buflen] = '\0';
6529c2aa98e2SPeter Wemm 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
65302fb4f839SGregory Neil Shapiro 		makelower_buf(search_key, search_key, sizeof(search_key));
6531c2aa98e2SPeter Wemm 
6532c2aa98e2SPeter Wemm 	f = safefopen(map->map_file, O_RDONLY, FileMode, sff);
6533c2aa98e2SPeter Wemm 	if (f == NULL)
6534c2aa98e2SPeter Wemm 	{
6535c2aa98e2SPeter Wemm 		map->map_mflags &= ~(MF_VALID|MF_OPEN);
6536c2aa98e2SPeter Wemm 		*statp = EX_UNAVAILABLE;
6537c2aa98e2SPeter Wemm 		return NULL;
6538c2aa98e2SPeter Wemm 	}
6539c2aa98e2SPeter Wemm 	key_idx = map->map_keycolno;
6540c2aa98e2SPeter Wemm 	delim = map->map_coldelim;
654194c01205SGregory Neil Shapiro 	while (sm_io_fgets(f, SM_TIME_DEFAULT,
6542552d4955SGregory Neil Shapiro 			   linebuf, sizeof(linebuf)) >= 0)
6543c2aa98e2SPeter Wemm 	{
6544c2aa98e2SPeter Wemm 		char *p;
6545c2aa98e2SPeter Wemm 
6546c2aa98e2SPeter Wemm 		/* skip comment line */
6547c2aa98e2SPeter Wemm 		if (linebuf[0] == '#')
6548c2aa98e2SPeter Wemm 			continue;
6549c2aa98e2SPeter Wemm 		p = strchr(linebuf, '\n');
6550c2aa98e2SPeter Wemm 		if (p != NULL)
6551c2aa98e2SPeter Wemm 			*p = '\0';
6552d0cef73dSGregory Neil Shapiro 		p = get_column(linebuf, key_idx, delim, buf, sizeof(buf));
65532fb4f839SGregory Neil Shapiro 		if (p != NULL && SM_STRCASEEQ(search_key, p))
6554c2aa98e2SPeter Wemm 		{
655540266059SGregory Neil Shapiro 			found_it = true;
6556c2aa98e2SPeter Wemm 			break;
6557c2aa98e2SPeter Wemm 		}
6558c2aa98e2SPeter Wemm 	}
655940266059SGregory Neil Shapiro 	(void) sm_io_close(f, SM_TIME_DEFAULT);
6560c2aa98e2SPeter Wemm 	if (!found_it)
6561c2aa98e2SPeter Wemm 	{
6562c2aa98e2SPeter Wemm 		*statp = EX_NOTFOUND;
6563c2aa98e2SPeter Wemm 		return NULL;
6564c2aa98e2SPeter Wemm 	}
6565d0cef73dSGregory Neil Shapiro 	vp = get_column(linebuf, map->map_valcolno, delim, buf, sizeof(buf));
6566065a643dSPeter Wemm 	if (vp == NULL)
6567065a643dSPeter Wemm 	{
6568065a643dSPeter Wemm 		*statp = EX_NOTFOUND;
6569065a643dSPeter Wemm 		return NULL;
6570065a643dSPeter Wemm 	}
6571c2aa98e2SPeter Wemm 	vsize = strlen(vp);
6572c2aa98e2SPeter Wemm 	*statp = EX_OK;
6573c2aa98e2SPeter Wemm 	if (bitset(MF_MATCHONLY, map->map_mflags))
6574c2aa98e2SPeter Wemm 		return map_rewrite(map, name, strlen(name), NULL);
6575c2aa98e2SPeter Wemm 	else
6576c2aa98e2SPeter Wemm 		return map_rewrite(map, vp, vsize, av);
6577c2aa98e2SPeter Wemm }
6578c2aa98e2SPeter Wemm 
6579c2aa98e2SPeter Wemm /*
6580c2aa98e2SPeter Wemm **  TEXT_GETCANONNAME -- look up canonical name in hosts file
6581c2aa98e2SPeter Wemm */
6582c2aa98e2SPeter Wemm 
658306f25ae9SGregory Neil Shapiro static bool
text_getcanonname(name,hbsize,statp)6584c2aa98e2SPeter Wemm text_getcanonname(name, hbsize, statp)
6585c2aa98e2SPeter Wemm 	char *name;
6586c2aa98e2SPeter Wemm 	int hbsize;
6587c2aa98e2SPeter Wemm 	int *statp;
6588c2aa98e2SPeter Wemm {
6589c2aa98e2SPeter Wemm 	bool found;
6590602a2b1bSGregory Neil Shapiro 	char *dot;
659140266059SGregory Neil Shapiro 	SM_FILE_T *f;
6592c2aa98e2SPeter Wemm 	char linebuf[MAXLINE];
65932fb4f839SGregory Neil Shapiro 	char cbuf[MAXNAME + 1];	/* EAI:hostname */
65942fb4f839SGregory Neil Shapiro 	char nbuf[MAXNAME + 1];	/* EAI:hostname */
6595c2aa98e2SPeter Wemm 
6596c2aa98e2SPeter Wemm 	if (tTd(38, 20))
659740266059SGregory Neil Shapiro 		sm_dprintf("text_getcanonname(%s)\n", name);
6598c2aa98e2SPeter Wemm 
6599d0cef73dSGregory Neil Shapiro 	if (sm_strlcpy(nbuf, name, sizeof(nbuf)) >= sizeof(nbuf))
6600c2aa98e2SPeter Wemm 	{
6601c2aa98e2SPeter Wemm 		*statp = EX_UNAVAILABLE;
660240266059SGregory Neil Shapiro 		return false;
6603c2aa98e2SPeter Wemm 	}
6604602a2b1bSGregory Neil Shapiro 	dot = shorten_hostname(nbuf);
6605c2aa98e2SPeter Wemm 
660640266059SGregory Neil Shapiro 	f = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, HostsFile, SM_IO_RDONLY,
660740266059SGregory Neil Shapiro 		       NULL);
6608c2aa98e2SPeter Wemm 	if (f == NULL)
6609c2aa98e2SPeter Wemm 	{
6610c2aa98e2SPeter Wemm 		*statp = EX_UNAVAILABLE;
661140266059SGregory Neil Shapiro 		return false;
6612c2aa98e2SPeter Wemm 	}
661340266059SGregory Neil Shapiro 	found = false;
661440266059SGregory Neil Shapiro 	while (!found &&
661594c01205SGregory Neil Shapiro 		sm_io_fgets(f, SM_TIME_DEFAULT,
6616552d4955SGregory Neil Shapiro 			    linebuf, sizeof(linebuf)) >= 0)
6617c2aa98e2SPeter Wemm 	{
6618c2aa98e2SPeter Wemm 		char *p = strpbrk(linebuf, "#\n");
6619c2aa98e2SPeter Wemm 
6620c2aa98e2SPeter Wemm 		if (p != NULL)
6621c2aa98e2SPeter Wemm 			*p = '\0';
6622c2aa98e2SPeter Wemm 		if (linebuf[0] != '\0')
6623602a2b1bSGregory Neil Shapiro 			found = extract_canonname(nbuf, dot, linebuf,
6624d0cef73dSGregory Neil Shapiro 						  cbuf, sizeof(cbuf));
6625c2aa98e2SPeter Wemm 	}
662640266059SGregory Neil Shapiro 	(void) sm_io_close(f, SM_TIME_DEFAULT);
6627c2aa98e2SPeter Wemm 	if (!found)
6628c2aa98e2SPeter Wemm 	{
6629c2aa98e2SPeter Wemm 		*statp = EX_NOHOST;
663040266059SGregory Neil Shapiro 		return false;
6631c2aa98e2SPeter Wemm 	}
6632c2aa98e2SPeter Wemm 
663340266059SGregory Neil Shapiro 	if (sm_strlcpy(name, cbuf, hbsize) >= hbsize)
6634c2aa98e2SPeter Wemm 	{
6635c2aa98e2SPeter Wemm 		*statp = EX_UNAVAILABLE;
663640266059SGregory Neil Shapiro 		return false;
6637c2aa98e2SPeter Wemm 	}
663840266059SGregory Neil Shapiro 	*statp = EX_OK;
663940266059SGregory Neil Shapiro 	return true;
664040266059SGregory Neil Shapiro }
664140266059SGregory Neil Shapiro /*
6642c2aa98e2SPeter Wemm **  STAB (Symbol Table) Modules
6643c2aa98e2SPeter Wemm */
6644c2aa98e2SPeter Wemm 
6645c2aa98e2SPeter Wemm 
6646c2aa98e2SPeter Wemm /*
6647c2aa98e2SPeter Wemm **  STAB_MAP_LOOKUP -- look up alias in symbol table
6648c2aa98e2SPeter Wemm */
6649c2aa98e2SPeter Wemm 
6650c2aa98e2SPeter Wemm /* ARGSUSED2 */
6651c2aa98e2SPeter Wemm char *
stab_map_lookup(map,name,av,pstat)6652c2aa98e2SPeter Wemm stab_map_lookup(map, name, av, pstat)
6653c2aa98e2SPeter Wemm 	register MAP *map;
6654c2aa98e2SPeter Wemm 	char *name;
6655c2aa98e2SPeter Wemm 	char **av;
6656c2aa98e2SPeter Wemm 	int *pstat;
6657c2aa98e2SPeter Wemm {
6658c2aa98e2SPeter Wemm 	register STAB *s;
6659c2aa98e2SPeter Wemm 
6660c2aa98e2SPeter Wemm 	if (tTd(38, 20))
666140266059SGregory Neil Shapiro 		sm_dprintf("stab_lookup(%s, %s)\n",
6662c2aa98e2SPeter Wemm 			map->map_mname, name);
6663c2aa98e2SPeter Wemm 
6664c2aa98e2SPeter Wemm 	s = stab(name, ST_ALIAS, ST_FIND);
666513d88268SGregory Neil Shapiro 	if (s == NULL)
666606f25ae9SGregory Neil Shapiro 		return NULL;
666713d88268SGregory Neil Shapiro 	if (bitset(MF_MATCHONLY, map->map_mflags))
666813d88268SGregory Neil Shapiro 		return map_rewrite(map, name, strlen(name), NULL);
666913d88268SGregory Neil Shapiro 	else
667013d88268SGregory Neil Shapiro 		return map_rewrite(map, s->s_alias, strlen(s->s_alias), av);
6671c2aa98e2SPeter Wemm }
6672c2aa98e2SPeter Wemm 
6673c2aa98e2SPeter Wemm /*
6674c2aa98e2SPeter Wemm **  STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild)
6675c2aa98e2SPeter Wemm */
6676c2aa98e2SPeter Wemm 
6677c2aa98e2SPeter Wemm void
stab_map_store(map,lhs,rhs)6678c2aa98e2SPeter Wemm stab_map_store(map, lhs, rhs)
6679c2aa98e2SPeter Wemm 	register MAP *map;
6680c2aa98e2SPeter Wemm 	char *lhs;
6681c2aa98e2SPeter Wemm 	char *rhs;
6682c2aa98e2SPeter Wemm {
6683c2aa98e2SPeter Wemm 	register STAB *s;
6684c2aa98e2SPeter Wemm 
6685c2aa98e2SPeter Wemm 	s = stab(lhs, ST_ALIAS, ST_ENTER);
6686c2aa98e2SPeter Wemm 	s->s_alias = newstr(rhs);
6687c2aa98e2SPeter Wemm }
6688c2aa98e2SPeter Wemm 
6689c2aa98e2SPeter Wemm 
6690c2aa98e2SPeter Wemm /*
6691c2aa98e2SPeter Wemm **  STAB_MAP_OPEN -- initialize (reads data file)
6692c2aa98e2SPeter Wemm **
66936f9c8e5bSGregory Neil Shapiro **	This is a weird case -- it is only intended as a fallback for
6694c2aa98e2SPeter Wemm **	aliases.  For this reason, opens for write (only during a
6695c2aa98e2SPeter Wemm **	"newaliases") always fails, and opens for read open the
6696c2aa98e2SPeter Wemm **	actual underlying text file instead of the database.
6697c2aa98e2SPeter Wemm */
6698c2aa98e2SPeter Wemm 
6699c2aa98e2SPeter Wemm bool
stab_map_open(map,mode)6700c2aa98e2SPeter Wemm stab_map_open(map, mode)
6701c2aa98e2SPeter Wemm 	register MAP *map;
6702c2aa98e2SPeter Wemm 	int mode;
6703c2aa98e2SPeter Wemm {
670440266059SGregory Neil Shapiro 	SM_FILE_T *af;
670506f25ae9SGregory Neil Shapiro 	long sff;
6706c2aa98e2SPeter Wemm 	struct stat st;
6707c2aa98e2SPeter Wemm 
6708c2aa98e2SPeter Wemm 	if (tTd(38, 2))
670940266059SGregory Neil Shapiro 		sm_dprintf("stab_map_open(%s, %s, %d)\n",
6710c2aa98e2SPeter Wemm 			map->map_mname, map->map_file, mode);
6711c2aa98e2SPeter Wemm 
6712c2aa98e2SPeter Wemm 	mode &= O_ACCMODE;
6713c2aa98e2SPeter Wemm 	if (mode != O_RDONLY)
6714c2aa98e2SPeter Wemm 	{
6715c2aa98e2SPeter Wemm 		errno = EPERM;
671640266059SGregory Neil Shapiro 		return false;
6717c2aa98e2SPeter Wemm 	}
6718c2aa98e2SPeter Wemm 
6719c2aa98e2SPeter Wemm 	sff = SFF_ROOTOK|SFF_REGONLY;
672006f25ae9SGregory Neil Shapiro 	if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail))
6721c2aa98e2SPeter Wemm 		sff |= SFF_NOWLINK;
672206f25ae9SGregory Neil Shapiro 	if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail))
6723c2aa98e2SPeter Wemm 		sff |= SFF_SAFEDIRPATH;
6724c2aa98e2SPeter Wemm 	af = safefopen(map->map_file, O_RDONLY, 0444, sff);
6725c2aa98e2SPeter Wemm 	if (af == NULL)
672640266059SGregory Neil Shapiro 		return false;
672740266059SGregory Neil Shapiro 	readaliases(map, af, false, false);
6728c2aa98e2SPeter Wemm 
672940266059SGregory Neil Shapiro 	if (fstat(sm_io_getinfo(af, SM_IO_WHAT_FD, NULL), &st) >= 0)
6730c2aa98e2SPeter Wemm 		map->map_mtime = st.st_mtime;
673140266059SGregory Neil Shapiro 	(void) sm_io_close(af, SM_TIME_DEFAULT);
6732c2aa98e2SPeter Wemm 
673340266059SGregory Neil Shapiro 	return true;
6734c2aa98e2SPeter Wemm }
673540266059SGregory Neil Shapiro /*
6736c2aa98e2SPeter Wemm **  Implicit Modules
6737c2aa98e2SPeter Wemm **
6738c2aa98e2SPeter Wemm **	Tries several types.  For back compatibility of aliases.
6739c2aa98e2SPeter Wemm */
6740c2aa98e2SPeter Wemm 
6741c2aa98e2SPeter Wemm 
6742c2aa98e2SPeter Wemm /*
6743c2aa98e2SPeter Wemm **  IMPL_MAP_LOOKUP -- lookup in best open database
6744c2aa98e2SPeter Wemm */
6745c2aa98e2SPeter Wemm 
6746c2aa98e2SPeter Wemm char *
impl_map_lookup(map,name,av,pstat)6747c2aa98e2SPeter Wemm impl_map_lookup(map, name, av, pstat)
6748c2aa98e2SPeter Wemm 	MAP *map;
6749c2aa98e2SPeter Wemm 	char *name;
6750c2aa98e2SPeter Wemm 	char **av;
6751c2aa98e2SPeter Wemm 	int *pstat;
6752c2aa98e2SPeter Wemm {
6753c2aa98e2SPeter Wemm 	if (tTd(38, 20))
675440266059SGregory Neil Shapiro 		sm_dprintf("impl_map_lookup(%s, %s)\n",
6755c2aa98e2SPeter Wemm 			map->map_mname, name);
6756c2aa98e2SPeter Wemm 
675740266059SGregory Neil Shapiro #if NEWDB
6758c2aa98e2SPeter Wemm 	if (bitset(MF_IMPL_HASH, map->map_mflags))
6759c2aa98e2SPeter Wemm 		return db_map_lookup(map, name, av, pstat);
67605b0945b5SGregory Neil Shapiro #endif
676140266059SGregory Neil Shapiro #if NDBM
6762c2aa98e2SPeter Wemm 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
6763c2aa98e2SPeter Wemm 		return ndbm_map_lookup(map, name, av, pstat);
67645b0945b5SGregory Neil Shapiro #endif
67655b0945b5SGregory Neil Shapiro #if CDB
67665b0945b5SGregory Neil Shapiro 	if (bitset(MF_IMPL_CDB, map->map_mflags))
67675b0945b5SGregory Neil Shapiro 		return cdb_map_lookup(map, name, av, pstat);
67685b0945b5SGregory Neil Shapiro #endif
6769c2aa98e2SPeter Wemm 	return stab_map_lookup(map, name, av, pstat);
6770c2aa98e2SPeter Wemm }
6771c2aa98e2SPeter Wemm 
6772c2aa98e2SPeter Wemm /*
6773c2aa98e2SPeter Wemm **  IMPL_MAP_STORE -- store in open databases
6774c2aa98e2SPeter Wemm */
6775c2aa98e2SPeter Wemm 
6776c2aa98e2SPeter Wemm void
impl_map_store(map,lhs,rhs)6777c2aa98e2SPeter Wemm impl_map_store(map, lhs, rhs)
6778c2aa98e2SPeter Wemm 	MAP *map;
6779c2aa98e2SPeter Wemm 	char *lhs;
6780c2aa98e2SPeter Wemm 	char *rhs;
6781c2aa98e2SPeter Wemm {
6782c2aa98e2SPeter Wemm 	if (tTd(38, 12))
678340266059SGregory Neil Shapiro 		sm_dprintf("impl_map_store(%s, %s, %s)\n",
6784c2aa98e2SPeter Wemm 			map->map_mname, lhs, rhs);
678540266059SGregory Neil Shapiro #if NEWDB
6786c2aa98e2SPeter Wemm 	if (bitset(MF_IMPL_HASH, map->map_mflags))
6787c2aa98e2SPeter Wemm 		db_map_store(map, lhs, rhs);
67885b0945b5SGregory Neil Shapiro #endif
678940266059SGregory Neil Shapiro #if NDBM
6790c2aa98e2SPeter Wemm 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
6791c2aa98e2SPeter Wemm 		ndbm_map_store(map, lhs, rhs);
67925b0945b5SGregory Neil Shapiro #endif
67935b0945b5SGregory Neil Shapiro #if CDB
67945b0945b5SGregory Neil Shapiro 	if (bitset(MF_IMPL_CDB, map->map_mflags))
67955b0945b5SGregory Neil Shapiro 		cdb_map_store(map, lhs, rhs);
67965b0945b5SGregory Neil Shapiro #endif
6797c2aa98e2SPeter Wemm 	stab_map_store(map, lhs, rhs);
6798c2aa98e2SPeter Wemm }
6799c2aa98e2SPeter Wemm 
6800c2aa98e2SPeter Wemm /*
6801c2aa98e2SPeter Wemm **  IMPL_MAP_OPEN -- implicit database open
6802c2aa98e2SPeter Wemm */
6803c2aa98e2SPeter Wemm 
6804c2aa98e2SPeter Wemm bool
impl_map_open(map,mode)6805c2aa98e2SPeter Wemm impl_map_open(map, mode)
6806c2aa98e2SPeter Wemm 	MAP *map;
6807c2aa98e2SPeter Wemm 	int mode;
6808c2aa98e2SPeter Wemm {
68095b0945b5SGregory Neil Shapiro 	bool wasopt;
68105b0945b5SGregory Neil Shapiro 
6811c2aa98e2SPeter Wemm 	if (tTd(38, 2))
681240266059SGregory Neil Shapiro 		sm_dprintf("impl_map_open(%s, %s, %d)\n",
6813c2aa98e2SPeter Wemm 			map->map_mname, map->map_file, mode);
6814c2aa98e2SPeter Wemm 
6815c2aa98e2SPeter Wemm 	mode &= O_ACCMODE;
68165b0945b5SGregory Neil Shapiro 	wasopt = bitset(MF_OPTIONAL, map->map_mflags);
68175b0945b5SGregory Neil Shapiro 
68185b0945b5SGregory Neil Shapiro 	/* suppress error msgs */
68195b0945b5SGregory Neil Shapiro 	map->map_mflags |= MF_OPTIONAL;
682040266059SGregory Neil Shapiro #if NEWDB
6821c2aa98e2SPeter Wemm 	map->map_mflags |= MF_IMPL_HASH;
6822c2aa98e2SPeter Wemm 	if (hash_map_open(map, mode))
6823c2aa98e2SPeter Wemm 	{
6824c2aa98e2SPeter Wemm # ifdef NDBM_YP_COMPAT
6825c2aa98e2SPeter Wemm 		if (mode == O_RDONLY || strstr(map->map_file, "/yp/") == NULL)
68265b0945b5SGregory Neil Shapiro # endif
68275b0945b5SGregory Neil Shapiro 			goto ok;
6828c2aa98e2SPeter Wemm 	}
6829c2aa98e2SPeter Wemm 	else
6830c2aa98e2SPeter Wemm 		map->map_mflags &= ~MF_IMPL_HASH;
683106f25ae9SGregory Neil Shapiro #endif /* NEWDB */
683240266059SGregory Neil Shapiro #if NDBM
6833c2aa98e2SPeter Wemm 	map->map_mflags |= MF_IMPL_NDBM;
6834c2aa98e2SPeter Wemm 	if (ndbm_map_open(map, mode))
68355b0945b5SGregory Neil Shapiro 		goto ok;
6836c2aa98e2SPeter Wemm 	else
6837c2aa98e2SPeter Wemm 		map->map_mflags &= ~MF_IMPL_NDBM;
683806f25ae9SGregory Neil Shapiro #endif /* NDBM */
6839c2aa98e2SPeter Wemm 
68405b0945b5SGregory Neil Shapiro #if CDB
68415b0945b5SGregory Neil Shapiro 	map->map_mflags |= MF_IMPL_CDB;
68425b0945b5SGregory Neil Shapiro 	if (cdb_map_open(map, mode))
68435b0945b5SGregory Neil Shapiro 		goto ok;
68445b0945b5SGregory Neil Shapiro 	else
68455b0945b5SGregory Neil Shapiro 		map->map_mflags &= ~MF_IMPL_CDB;
68465b0945b5SGregory Neil Shapiro #endif /* CDB */
68475b0945b5SGregory Neil Shapiro 
68485b0945b5SGregory Neil Shapiro 	if (!bitset(MF_ALIAS, map->map_mflags))
68495b0945b5SGregory Neil Shapiro 		goto fail;
68505b0945b5SGregory Neil Shapiro #if NEWDB || NDBM || CDB
6851c2aa98e2SPeter Wemm 	if (Verbose)
6852c2aa98e2SPeter Wemm 		message("WARNING: cannot open alias database %s%s",
6853c2aa98e2SPeter Wemm 			map->map_file,
6854c2aa98e2SPeter Wemm 			mode == O_RDONLY ? "; reading text version" : "");
68555b0945b5SGregory Neil Shapiro #else
6856c2aa98e2SPeter Wemm 	if (mode != O_RDONLY)
6857c2aa98e2SPeter Wemm 		usrerr("Cannot rebuild aliases: no database format defined");
68585b0945b5SGregory Neil Shapiro #endif
6859c2aa98e2SPeter Wemm 
68605b0945b5SGregory Neil Shapiro 	if (mode == O_RDONLY && stab_map_open(map, mode))
68615b0945b5SGregory Neil Shapiro 		goto ok;
68625b0945b5SGregory Neil Shapiro 
68635b0945b5SGregory Neil Shapiro   fail:
68645b0945b5SGregory Neil Shapiro 	if (!wasopt)
68655b0945b5SGregory Neil Shapiro 		map->map_mflags &= ~MF_OPTIONAL;
686640266059SGregory Neil Shapiro 	return false;
68675b0945b5SGregory Neil Shapiro 
68685b0945b5SGregory Neil Shapiro   ok:
68695b0945b5SGregory Neil Shapiro 	if (!wasopt)
68705b0945b5SGregory Neil Shapiro 		map->map_mflags &= ~MF_OPTIONAL;
68715b0945b5SGregory Neil Shapiro 	return true;
6872c2aa98e2SPeter Wemm }
6873c2aa98e2SPeter Wemm 
6874c2aa98e2SPeter Wemm 
6875c2aa98e2SPeter Wemm /*
6876c2aa98e2SPeter Wemm **  IMPL_MAP_CLOSE -- close any open database(s)
6877c2aa98e2SPeter Wemm */
6878c2aa98e2SPeter Wemm 
6879c2aa98e2SPeter Wemm void
impl_map_close(map)6880c2aa98e2SPeter Wemm impl_map_close(map)
6881c2aa98e2SPeter Wemm 	MAP *map;
6882c2aa98e2SPeter Wemm {
6883c2aa98e2SPeter Wemm 	if (tTd(38, 9))
688440266059SGregory Neil Shapiro 		sm_dprintf("impl_map_close(%s, %s, %lx)\n",
6885c2aa98e2SPeter Wemm 			map->map_mname, map->map_file, map->map_mflags);
688640266059SGregory Neil Shapiro #if NEWDB
6887c2aa98e2SPeter Wemm 	if (bitset(MF_IMPL_HASH, map->map_mflags))
6888c2aa98e2SPeter Wemm 	{
6889c2aa98e2SPeter Wemm 		db_map_close(map);
6890c2aa98e2SPeter Wemm 		map->map_mflags &= ~MF_IMPL_HASH;
6891c2aa98e2SPeter Wemm 	}
689206f25ae9SGregory Neil Shapiro #endif /* NEWDB */
6893c2aa98e2SPeter Wemm 
689440266059SGregory Neil Shapiro #if NDBM
6895c2aa98e2SPeter Wemm 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
6896c2aa98e2SPeter Wemm 	{
6897c2aa98e2SPeter Wemm 		ndbm_map_close(map);
6898c2aa98e2SPeter Wemm 		map->map_mflags &= ~MF_IMPL_NDBM;
6899c2aa98e2SPeter Wemm 	}
690006f25ae9SGregory Neil Shapiro #endif /* NDBM */
69015b0945b5SGregory Neil Shapiro #if CDB
69025b0945b5SGregory Neil Shapiro 	if (bitset(MF_IMPL_CDB, map->map_mflags))
69035b0945b5SGregory Neil Shapiro 	{
69045b0945b5SGregory Neil Shapiro 		cdb_map_close(map);
69055b0945b5SGregory Neil Shapiro 		map->map_mflags &= ~MF_IMPL_CDB;
6906c2aa98e2SPeter Wemm 	}
69075b0945b5SGregory Neil Shapiro #endif /* CDB */
69085b0945b5SGregory Neil Shapiro }
69095b0945b5SGregory Neil Shapiro 
691040266059SGregory Neil Shapiro /*
6911c2aa98e2SPeter Wemm **  User map class.
6912c2aa98e2SPeter Wemm **
6913c2aa98e2SPeter Wemm **	Provides access to the system password file.
6914c2aa98e2SPeter Wemm */
6915c2aa98e2SPeter Wemm 
6916c2aa98e2SPeter Wemm /*
6917c2aa98e2SPeter Wemm **  USER_MAP_OPEN -- open user map
6918c2aa98e2SPeter Wemm **
6919c2aa98e2SPeter Wemm **	Really just binds field names to field numbers.
6920c2aa98e2SPeter Wemm */
6921c2aa98e2SPeter Wemm 
6922c2aa98e2SPeter Wemm bool
user_map_open(map,mode)6923c2aa98e2SPeter Wemm user_map_open(map, mode)
6924c2aa98e2SPeter Wemm 	MAP *map;
6925c2aa98e2SPeter Wemm 	int mode;
6926c2aa98e2SPeter Wemm {
6927c2aa98e2SPeter Wemm 	if (tTd(38, 2))
692840266059SGregory Neil Shapiro 		sm_dprintf("user_map_open(%s, %d)\n",
6929c2aa98e2SPeter Wemm 			map->map_mname, mode);
6930c2aa98e2SPeter Wemm 
6931c2aa98e2SPeter Wemm 	mode &= O_ACCMODE;
6932c2aa98e2SPeter Wemm 	if (mode != O_RDONLY)
6933c2aa98e2SPeter Wemm 	{
6934c2aa98e2SPeter Wemm 		/* issue a pseudo-error message */
693540266059SGregory Neil Shapiro 		errno = SM_EMAPCANTWRITE;
693640266059SGregory Neil Shapiro 		return false;
6937c2aa98e2SPeter Wemm 	}
6938c2aa98e2SPeter Wemm 	if (map->map_valcolnm == NULL)
693906f25ae9SGregory Neil Shapiro 		/* EMPTY */
6940c2aa98e2SPeter Wemm 		/* nothing */ ;
69412fb4f839SGregory Neil Shapiro 	else if (SM_STRCASEEQ(map->map_valcolnm, "name"))
6942c2aa98e2SPeter Wemm 		map->map_valcolno = 1;
69432fb4f839SGregory Neil Shapiro 	else if (SM_STRCASEEQ(map->map_valcolnm, "passwd"))
6944c2aa98e2SPeter Wemm 		map->map_valcolno = 2;
69452fb4f839SGregory Neil Shapiro 	else if (SM_STRCASEEQ(map->map_valcolnm, "uid"))
6946c2aa98e2SPeter Wemm 		map->map_valcolno = 3;
69472fb4f839SGregory Neil Shapiro 	else if (SM_STRCASEEQ(map->map_valcolnm, "gid"))
6948c2aa98e2SPeter Wemm 		map->map_valcolno = 4;
69492fb4f839SGregory Neil Shapiro 	else if (SM_STRCASEEQ(map->map_valcolnm, "gecos"))
6950c2aa98e2SPeter Wemm 		map->map_valcolno = 5;
69512fb4f839SGregory Neil Shapiro 	else if (SM_STRCASEEQ(map->map_valcolnm, "dir"))
6952c2aa98e2SPeter Wemm 		map->map_valcolno = 6;
69532fb4f839SGregory Neil Shapiro 	else if (SM_STRCASEEQ(map->map_valcolnm, "shell"))
6954c2aa98e2SPeter Wemm 		map->map_valcolno = 7;
6955c2aa98e2SPeter Wemm 	else
6956c2aa98e2SPeter Wemm 	{
6957c2aa98e2SPeter Wemm 		syserr("User map %s: unknown column name %s",
6958c2aa98e2SPeter Wemm 			map->map_mname, map->map_valcolnm);
695940266059SGregory Neil Shapiro 		return false;
6960c2aa98e2SPeter Wemm 	}
696140266059SGregory Neil Shapiro 	return true;
6962c2aa98e2SPeter Wemm }
6963c2aa98e2SPeter Wemm 
6964c2aa98e2SPeter Wemm 
6965c2aa98e2SPeter Wemm /*
6966c2aa98e2SPeter Wemm **  USER_MAP_LOOKUP -- look up a user in the passwd file.
6967c2aa98e2SPeter Wemm */
6968c2aa98e2SPeter Wemm 
6969c2aa98e2SPeter Wemm /* ARGSUSED3 */
6970c2aa98e2SPeter Wemm char *
user_map_lookup(map,key,av,statp)6971c2aa98e2SPeter Wemm user_map_lookup(map, key, av, statp)
6972c2aa98e2SPeter Wemm 	MAP *map;
6973c2aa98e2SPeter Wemm 	char *key;
6974c2aa98e2SPeter Wemm 	char **av;
6975c2aa98e2SPeter Wemm 	int *statp;
6976c2aa98e2SPeter Wemm {
6977c2aa98e2SPeter Wemm 	auto bool fuzzy;
697840266059SGregory Neil Shapiro 	SM_MBDB_T user;
6979c2aa98e2SPeter Wemm 
6980c2aa98e2SPeter Wemm 	if (tTd(38, 20))
698140266059SGregory Neil Shapiro 		sm_dprintf("user_map_lookup(%s, %s)\n",
6982c2aa98e2SPeter Wemm 			map->map_mname, key);
6983c2aa98e2SPeter Wemm 
698440266059SGregory Neil Shapiro 	*statp = finduser(key, &fuzzy, &user);
698540266059SGregory Neil Shapiro 	if (*statp != EX_OK)
6986c2aa98e2SPeter Wemm 		return NULL;
6987c2aa98e2SPeter Wemm 	if (bitset(MF_MATCHONLY, map->map_mflags))
6988c2aa98e2SPeter Wemm 		return map_rewrite(map, key, strlen(key), NULL);
6989c2aa98e2SPeter Wemm 	else
6990c2aa98e2SPeter Wemm 	{
6991c2aa98e2SPeter Wemm 		char *rwval = NULL;
6992c2aa98e2SPeter Wemm 		char buf[30];
6993c2aa98e2SPeter Wemm 
6994c2aa98e2SPeter Wemm 		switch (map->map_valcolno)
6995c2aa98e2SPeter Wemm 		{
6996c2aa98e2SPeter Wemm 		  case 0:
6997c2aa98e2SPeter Wemm 		  case 1:
699840266059SGregory Neil Shapiro 			rwval = user.mbdb_name;
6999c2aa98e2SPeter Wemm 			break;
7000c2aa98e2SPeter Wemm 
7001c2aa98e2SPeter Wemm 		  case 2:
700240266059SGregory Neil Shapiro 			rwval = "x";	/* passwd no longer supported */
7003c2aa98e2SPeter Wemm 			break;
7004c2aa98e2SPeter Wemm 
7005c2aa98e2SPeter Wemm 		  case 3:
7006d0cef73dSGregory Neil Shapiro 			(void) sm_snprintf(buf, sizeof(buf), "%d",
700740266059SGregory Neil Shapiro 					   (int) user.mbdb_uid);
7008c2aa98e2SPeter Wemm 			rwval = buf;
7009c2aa98e2SPeter Wemm 			break;
7010c2aa98e2SPeter Wemm 
7011c2aa98e2SPeter Wemm 		  case 4:
7012d0cef73dSGregory Neil Shapiro 			(void) sm_snprintf(buf, sizeof(buf), "%d",
701340266059SGregory Neil Shapiro 					   (int) user.mbdb_gid);
7014c2aa98e2SPeter Wemm 			rwval = buf;
7015c2aa98e2SPeter Wemm 			break;
7016c2aa98e2SPeter Wemm 
7017c2aa98e2SPeter Wemm 		  case 5:
701840266059SGregory Neil Shapiro 			rwval = user.mbdb_fullname;
7019c2aa98e2SPeter Wemm 			break;
7020c2aa98e2SPeter Wemm 
7021c2aa98e2SPeter Wemm 		  case 6:
702240266059SGregory Neil Shapiro 			rwval = user.mbdb_homedir;
7023c2aa98e2SPeter Wemm 			break;
7024c2aa98e2SPeter Wemm 
7025c2aa98e2SPeter Wemm 		  case 7:
702640266059SGregory Neil Shapiro 			rwval = user.mbdb_shell;
7027c2aa98e2SPeter Wemm 			break;
7028af9557fdSGregory Neil Shapiro 		  default:
7029af9557fdSGregory Neil Shapiro 			syserr("user_map %s: bogus field %d",
7030af9557fdSGregory Neil Shapiro 				map->map_mname, map->map_valcolno);
7031af9557fdSGregory Neil Shapiro 			return NULL;
7032c2aa98e2SPeter Wemm 		}
7033c2aa98e2SPeter Wemm 		return map_rewrite(map, rwval, strlen(rwval), av);
7034c2aa98e2SPeter Wemm 	}
7035c2aa98e2SPeter Wemm }
703640266059SGregory Neil Shapiro /*
7037c2aa98e2SPeter Wemm **  Program map type.
7038c2aa98e2SPeter Wemm **
7039c2aa98e2SPeter Wemm **	This provides access to arbitrary programs.  It should be used
7040c2aa98e2SPeter Wemm **	only very sparingly, since there is no way to bound the cost
7041c2aa98e2SPeter Wemm **	of invoking an arbitrary program.
7042c2aa98e2SPeter Wemm */
7043c2aa98e2SPeter Wemm 
7044c2aa98e2SPeter Wemm char *
prog_map_lookup(map,name,av,statp)7045c2aa98e2SPeter Wemm prog_map_lookup(map, name, av, statp)
7046c2aa98e2SPeter Wemm 	MAP *map;
7047c2aa98e2SPeter Wemm 	char *name;
7048c2aa98e2SPeter Wemm 	char **av;
7049c2aa98e2SPeter Wemm 	int *statp;
7050c2aa98e2SPeter Wemm {
7051c2aa98e2SPeter Wemm 	int i;
705206f25ae9SGregory Neil Shapiro 	int save_errno;
7053c2aa98e2SPeter Wemm 	int fd;
705406f25ae9SGregory Neil Shapiro 	int status;
7055c2aa98e2SPeter Wemm 	auto pid_t pid;
705606f25ae9SGregory Neil Shapiro 	register char *p;
7057c2aa98e2SPeter Wemm 	char *rval;
7058c2aa98e2SPeter Wemm 	char *argv[MAXPV + 1];
7059c2aa98e2SPeter Wemm 	char buf[MAXLINE];
7060c2aa98e2SPeter Wemm 
7061c2aa98e2SPeter Wemm 	if (tTd(38, 20))
706240266059SGregory Neil Shapiro 		sm_dprintf("prog_map_lookup(%s, %s) %s\n",
7063c2aa98e2SPeter Wemm 			map->map_mname, name, map->map_file);
7064c2aa98e2SPeter Wemm 
7065c2aa98e2SPeter Wemm 	i = 0;
7066c2aa98e2SPeter Wemm 	argv[i++] = map->map_file;
7067c2aa98e2SPeter Wemm 	if (map->map_rebuild != NULL)
7068c2aa98e2SPeter Wemm 	{
7069d0cef73dSGregory Neil Shapiro 		(void) sm_strlcpy(buf, map->map_rebuild, sizeof(buf));
7070c2aa98e2SPeter Wemm 		for (p = strtok(buf, " \t"); p != NULL; p = strtok(NULL, " \t"))
7071c2aa98e2SPeter Wemm 		{
7072c2aa98e2SPeter Wemm 			if (i >= MAXPV - 1)
7073c2aa98e2SPeter Wemm 				break;
7074c2aa98e2SPeter Wemm 			argv[i++] = p;
7075c2aa98e2SPeter Wemm 		}
7076c2aa98e2SPeter Wemm 	}
7077c2aa98e2SPeter Wemm 	argv[i++] = name;
7078c2aa98e2SPeter Wemm 	argv[i] = NULL;
7079c2aa98e2SPeter Wemm 	if (tTd(38, 21))
7080c2aa98e2SPeter Wemm 	{
708140266059SGregory Neil Shapiro 		sm_dprintf("prog_open:");
7082c2aa98e2SPeter Wemm 		for (i = 0; argv[i] != NULL; i++)
708340266059SGregory Neil Shapiro 			sm_dprintf(" %s", argv[i]);
708440266059SGregory Neil Shapiro 		sm_dprintf("\n");
7085c2aa98e2SPeter Wemm 	}
708640266059SGregory Neil Shapiro 	(void) sm_blocksignal(SIGCHLD);
7087c2aa98e2SPeter Wemm 	pid = prog_open(argv, &fd, CurEnv);
7088c2aa98e2SPeter Wemm 	if (pid < 0)
7089c2aa98e2SPeter Wemm 	{
7090c2aa98e2SPeter Wemm 		if (!bitset(MF_OPTIONAL, map->map_mflags))
7091c2aa98e2SPeter Wemm 			syserr("prog_map_lookup(%s) failed (%s) -- closing",
709240266059SGregory Neil Shapiro 			       map->map_mname, sm_errstring(errno));
7093c2aa98e2SPeter Wemm 		else if (tTd(38, 9))
709440266059SGregory Neil Shapiro 			sm_dprintf("prog_map_lookup(%s) failed (%s) -- closing",
709540266059SGregory Neil Shapiro 				   map->map_mname, sm_errstring(errno));
7096c2aa98e2SPeter Wemm 		map->map_mflags &= ~(MF_VALID|MF_OPEN);
7097c2aa98e2SPeter Wemm 		*statp = EX_OSFILE;
7098c2aa98e2SPeter Wemm 		return NULL;
7099c2aa98e2SPeter Wemm 	}
7100d0cef73dSGregory Neil Shapiro 	i = read(fd, buf, sizeof(buf) - 1);
7101c2aa98e2SPeter Wemm 	if (i < 0)
7102c2aa98e2SPeter Wemm 	{
710340266059SGregory Neil Shapiro 		syserr("prog_map_lookup(%s): read error %s",
710440266059SGregory Neil Shapiro 		       map->map_mname, sm_errstring(errno));
7105c2aa98e2SPeter Wemm 		rval = NULL;
7106c2aa98e2SPeter Wemm 	}
7107c2aa98e2SPeter Wemm 	else if (i == 0)
7108c2aa98e2SPeter Wemm 	{
7109c2aa98e2SPeter Wemm 		if (tTd(38, 20))
711040266059SGregory Neil Shapiro 			sm_dprintf("prog_map_lookup(%s): empty answer\n",
7111c2aa98e2SPeter Wemm 				   map->map_mname);
7112c2aa98e2SPeter Wemm 		rval = NULL;
7113c2aa98e2SPeter Wemm 	}
7114c2aa98e2SPeter Wemm 	else
7115c2aa98e2SPeter Wemm 	{
7116c2aa98e2SPeter Wemm 		buf[i] = '\0';
7117c2aa98e2SPeter Wemm 		p = strchr(buf, '\n');
7118c2aa98e2SPeter Wemm 		if (p != NULL)
7119c2aa98e2SPeter Wemm 			*p = '\0';
7120c2aa98e2SPeter Wemm 
7121c2aa98e2SPeter Wemm 		/* collect the return value */
7122c2aa98e2SPeter Wemm 		if (bitset(MF_MATCHONLY, map->map_mflags))
7123c2aa98e2SPeter Wemm 			rval = map_rewrite(map, name, strlen(name), NULL);
7124c2aa98e2SPeter Wemm 		else
71258774250cSGregory Neil Shapiro 			rval = map_rewrite(map, buf, strlen(buf), av);
7126c2aa98e2SPeter Wemm 
7127c2aa98e2SPeter Wemm 		/* now flush any additional output */
7128d0cef73dSGregory Neil Shapiro 		while ((i = read(fd, buf, sizeof(buf))) > 0)
7129c2aa98e2SPeter Wemm 			continue;
7130c2aa98e2SPeter Wemm 	}
7131c2aa98e2SPeter Wemm 
7132c2aa98e2SPeter Wemm 	/* wait for the process to terminate */
713306f25ae9SGregory Neil Shapiro 	(void) close(fd);
713406f25ae9SGregory Neil Shapiro 	status = waitfor(pid);
713506f25ae9SGregory Neil Shapiro 	save_errno = errno;
713640266059SGregory Neil Shapiro 	(void) sm_releasesignal(SIGCHLD);
713706f25ae9SGregory Neil Shapiro 	errno = save_errno;
7138c2aa98e2SPeter Wemm 
713906f25ae9SGregory Neil Shapiro 	if (status == -1)
7140c2aa98e2SPeter Wemm 	{
714140266059SGregory Neil Shapiro 		syserr("prog_map_lookup(%s): wait error %s",
714240266059SGregory Neil Shapiro 		       map->map_mname, sm_errstring(errno));
7143c2aa98e2SPeter Wemm 		*statp = EX_SOFTWARE;
7144c2aa98e2SPeter Wemm 		rval = NULL;
7145c2aa98e2SPeter Wemm 	}
714606f25ae9SGregory Neil Shapiro 	else if (WIFEXITED(status))
7147c2aa98e2SPeter Wemm 	{
714806f25ae9SGregory Neil Shapiro 		if ((*statp = WEXITSTATUS(status)) != EX_OK)
7149c2aa98e2SPeter Wemm 			rval = NULL;
7150c2aa98e2SPeter Wemm 	}
7151c2aa98e2SPeter Wemm 	else
7152c2aa98e2SPeter Wemm 	{
7153c2aa98e2SPeter Wemm 		syserr("prog_map_lookup(%s): child died on signal %d",
715406f25ae9SGregory Neil Shapiro 		       map->map_mname, status);
7155c2aa98e2SPeter Wemm 		*statp = EX_UNAVAILABLE;
7156c2aa98e2SPeter Wemm 		rval = NULL;
7157c2aa98e2SPeter Wemm 	}
7158c2aa98e2SPeter Wemm 	return rval;
7159c2aa98e2SPeter Wemm }
716040266059SGregory Neil Shapiro /*
7161c2aa98e2SPeter Wemm **  Sequenced map type.
7162c2aa98e2SPeter Wemm **
7163c2aa98e2SPeter Wemm **	Tries each map in order until something matches, much like
7164c2aa98e2SPeter Wemm **	implicit.  Stores go to the first map in the list that can
7165c2aa98e2SPeter Wemm **	support storing.
7166c2aa98e2SPeter Wemm **
7167c2aa98e2SPeter Wemm **	This is slightly unusual in that there are two interfaces.
7168c2aa98e2SPeter Wemm **	The "sequence" interface lets you stack maps arbitrarily.
7169c2aa98e2SPeter Wemm **	The "switch" interface builds a sequence map by looking
7170c2aa98e2SPeter Wemm **	at a system-dependent configuration file such as
7171c2aa98e2SPeter Wemm **	/etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix.
7172c2aa98e2SPeter Wemm **
7173c2aa98e2SPeter Wemm **	We don't need an explicit open, since all maps are
717440266059SGregory Neil Shapiro **	opened on demand.
7175c2aa98e2SPeter Wemm */
7176c2aa98e2SPeter Wemm 
7177c2aa98e2SPeter Wemm /*
7178c2aa98e2SPeter Wemm **  SEQ_MAP_PARSE -- Sequenced map parsing
7179c2aa98e2SPeter Wemm */
7180c2aa98e2SPeter Wemm 
7181c2aa98e2SPeter Wemm bool
seq_map_parse(map,ap)7182c2aa98e2SPeter Wemm seq_map_parse(map, ap)
7183c2aa98e2SPeter Wemm 	MAP *map;
7184c2aa98e2SPeter Wemm 	char *ap;
7185c2aa98e2SPeter Wemm {
7186c2aa98e2SPeter Wemm 	int maxmap;
7187c2aa98e2SPeter Wemm 
7188c2aa98e2SPeter Wemm 	if (tTd(38, 2))
718940266059SGregory Neil Shapiro 		sm_dprintf("seq_map_parse(%s, %s)\n", map->map_mname, ap);
7190c2aa98e2SPeter Wemm 	maxmap = 0;
7191c2aa98e2SPeter Wemm 	while (*ap != '\0')
7192c2aa98e2SPeter Wemm 	{
7193c2aa98e2SPeter Wemm 		register char *p;
7194c2aa98e2SPeter Wemm 		STAB *s;
7195c2aa98e2SPeter Wemm 
7196c2aa98e2SPeter Wemm 		/* find beginning of map name */
71975b0945b5SGregory Neil Shapiro 		while (SM_ISSPACE(*ap))
7198c2aa98e2SPeter Wemm 			ap++;
719906f25ae9SGregory Neil Shapiro 		for (p = ap;
720006f25ae9SGregory Neil Shapiro 		     (isascii(*p) && isalnum(*p)) || *p == '_' || *p == '.';
720106f25ae9SGregory Neil Shapiro 		     p++)
7202c2aa98e2SPeter Wemm 			continue;
7203c2aa98e2SPeter Wemm 		if (*p != '\0')
7204c2aa98e2SPeter Wemm 			*p++ = '\0';
7205c2aa98e2SPeter Wemm 		while (*p != '\0' && (!isascii(*p) || !isalnum(*p)))
7206c2aa98e2SPeter Wemm 			p++;
7207c2aa98e2SPeter Wemm 		if (*ap == '\0')
7208c2aa98e2SPeter Wemm 		{
7209c2aa98e2SPeter Wemm 			ap = p;
7210c2aa98e2SPeter Wemm 			continue;
7211c2aa98e2SPeter Wemm 		}
7212c2aa98e2SPeter Wemm 		s = stab(ap, ST_MAP, ST_FIND);
7213c2aa98e2SPeter Wemm 		if (s == NULL)
7214c2aa98e2SPeter Wemm 		{
7215c2aa98e2SPeter Wemm 			syserr("Sequence map %s: unknown member map %s",
7216c2aa98e2SPeter Wemm 				map->map_mname, ap);
7217c2aa98e2SPeter Wemm 		}
721840266059SGregory Neil Shapiro 		else if (maxmap >= MAXMAPSTACK)
7219c2aa98e2SPeter Wemm 		{
7220c2aa98e2SPeter Wemm 			syserr("Sequence map %s: too many member maps (%d max)",
7221c2aa98e2SPeter Wemm 				map->map_mname, MAXMAPSTACK);
7222c2aa98e2SPeter Wemm 			maxmap++;
7223c2aa98e2SPeter Wemm 		}
7224c2aa98e2SPeter Wemm 		else if (maxmap < MAXMAPSTACK)
7225c2aa98e2SPeter Wemm 		{
7226c2aa98e2SPeter Wemm 			map->map_stack[maxmap++] = &s->s_map;
7227c2aa98e2SPeter Wemm 		}
7228c2aa98e2SPeter Wemm 		ap = p;
7229c2aa98e2SPeter Wemm 	}
723040266059SGregory Neil Shapiro 	return true;
7231c2aa98e2SPeter Wemm }
7232c2aa98e2SPeter Wemm 
7233c2aa98e2SPeter Wemm /*
7234c2aa98e2SPeter Wemm **  SWITCH_MAP_OPEN -- open a switched map
7235c2aa98e2SPeter Wemm **
7236c2aa98e2SPeter Wemm **	This looks at the system-dependent configuration and builds
7237c2aa98e2SPeter Wemm **	a sequence map that does the same thing.
7238c2aa98e2SPeter Wemm **
7239c2aa98e2SPeter Wemm **	Every system must define a switch_map_find routine in conf.c
7240c2aa98e2SPeter Wemm **	that will return the list of service types associated with a
7241c2aa98e2SPeter Wemm **	given service class.
7242c2aa98e2SPeter Wemm */
7243c2aa98e2SPeter Wemm 
7244c2aa98e2SPeter Wemm bool
switch_map_open(map,mode)7245c2aa98e2SPeter Wemm switch_map_open(map, mode)
7246c2aa98e2SPeter Wemm 	MAP *map;
7247c2aa98e2SPeter Wemm 	int mode;
7248c2aa98e2SPeter Wemm {
7249c2aa98e2SPeter Wemm 	int mapno;
7250c2aa98e2SPeter Wemm 	int nmaps;
7251c2aa98e2SPeter Wemm 	char *maptype[MAXMAPSTACK];
7252c2aa98e2SPeter Wemm 
7253c2aa98e2SPeter Wemm 	if (tTd(38, 2))
725440266059SGregory Neil Shapiro 		sm_dprintf("switch_map_open(%s, %s, %d)\n",
7255c2aa98e2SPeter Wemm 			map->map_mname, map->map_file, mode);
7256c2aa98e2SPeter Wemm 
7257c2aa98e2SPeter Wemm 	mode &= O_ACCMODE;
7258c2aa98e2SPeter Wemm 	nmaps = switch_map_find(map->map_file, maptype, map->map_return);
7259c2aa98e2SPeter Wemm 	if (tTd(38, 19))
7260c2aa98e2SPeter Wemm 	{
726140266059SGregory Neil Shapiro 		sm_dprintf("\tswitch_map_find => %d\n", nmaps);
7262c2aa98e2SPeter Wemm 		for (mapno = 0; mapno < nmaps; mapno++)
726340266059SGregory Neil Shapiro 			sm_dprintf("\t\t%s\n", maptype[mapno]);
7264c2aa98e2SPeter Wemm 	}
7265c2aa98e2SPeter Wemm 	if (nmaps <= 0 || nmaps > MAXMAPSTACK)
726640266059SGregory Neil Shapiro 		return false;
7267c2aa98e2SPeter Wemm 
7268c2aa98e2SPeter Wemm 	for (mapno = 0; mapno < nmaps; mapno++)
7269c2aa98e2SPeter Wemm 	{
7270c2aa98e2SPeter Wemm 		register STAB *s;
72712fb4f839SGregory Neil Shapiro 		char nbuf[MAXNAME + 1];	/* EAI:not relevant (map name) */
7272c2aa98e2SPeter Wemm 
7273c2aa98e2SPeter Wemm 		if (maptype[mapno] == NULL)
7274c2aa98e2SPeter Wemm 			continue;
7275d0cef73dSGregory Neil Shapiro 		(void) sm_strlcpyn(nbuf, sizeof(nbuf), 3,
727640266059SGregory Neil Shapiro 				   map->map_mname, ".", maptype[mapno]);
7277c2aa98e2SPeter Wemm 		s = stab(nbuf, ST_MAP, ST_FIND);
7278c2aa98e2SPeter Wemm 		if (s == NULL)
7279c2aa98e2SPeter Wemm 		{
7280c2aa98e2SPeter Wemm 			syserr("Switch map %s: unknown member map %s",
7281c2aa98e2SPeter Wemm 				map->map_mname, nbuf);
7282c2aa98e2SPeter Wemm 		}
7283c2aa98e2SPeter Wemm 		else
7284c2aa98e2SPeter Wemm 		{
7285c2aa98e2SPeter Wemm 			map->map_stack[mapno] = &s->s_map;
7286c2aa98e2SPeter Wemm 			if (tTd(38, 4))
728740266059SGregory Neil Shapiro 				sm_dprintf("\tmap_stack[%d] = %s:%s\n",
728840266059SGregory Neil Shapiro 					   mapno,
728940266059SGregory Neil Shapiro 					   s->s_map.map_class->map_cname,
7290c2aa98e2SPeter Wemm 					   nbuf);
7291c2aa98e2SPeter Wemm 		}
7292c2aa98e2SPeter Wemm 	}
729340266059SGregory Neil Shapiro 	return true;
7294c2aa98e2SPeter Wemm }
7295c2aa98e2SPeter Wemm 
729640266059SGregory Neil Shapiro #if 0
7297c2aa98e2SPeter Wemm /*
7298c2aa98e2SPeter Wemm **  SEQ_MAP_CLOSE -- close all underlying maps
7299c2aa98e2SPeter Wemm */
7300c2aa98e2SPeter Wemm 
7301c2aa98e2SPeter Wemm void
7302c2aa98e2SPeter Wemm seq_map_close(map)
7303c2aa98e2SPeter Wemm 	MAP *map;
7304c2aa98e2SPeter Wemm {
7305c2aa98e2SPeter Wemm 	int mapno;
7306c2aa98e2SPeter Wemm 
7307c2aa98e2SPeter Wemm 	if (tTd(38, 9))
730840266059SGregory Neil Shapiro 		sm_dprintf("seq_map_close(%s)\n", map->map_mname);
7309c2aa98e2SPeter Wemm 
7310c2aa98e2SPeter Wemm 	for (mapno = 0; mapno < MAXMAPSTACK; mapno++)
7311c2aa98e2SPeter Wemm 	{
7312c2aa98e2SPeter Wemm 		MAP *mm = map->map_stack[mapno];
7313c2aa98e2SPeter Wemm 
7314c2aa98e2SPeter Wemm 		if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags))
7315c2aa98e2SPeter Wemm 			continue;
73168774250cSGregory Neil Shapiro 		mm->map_mflags |= MF_CLOSING;
7317c2aa98e2SPeter Wemm 		mm->map_class->map_close(mm);
73188774250cSGregory Neil Shapiro 		mm->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING);
7319c2aa98e2SPeter Wemm 	}
7320c2aa98e2SPeter Wemm }
732140266059SGregory Neil Shapiro #endif /* 0 */
7322c2aa98e2SPeter Wemm 
7323c2aa98e2SPeter Wemm /*
7324c2aa98e2SPeter Wemm **  SEQ_MAP_LOOKUP -- sequenced map lookup
7325c2aa98e2SPeter Wemm */
7326c2aa98e2SPeter Wemm 
7327c2aa98e2SPeter Wemm char *
seq_map_lookup(map,key,args,pstat)7328c2aa98e2SPeter Wemm seq_map_lookup(map, key, args, pstat)
7329c2aa98e2SPeter Wemm 	MAP *map;
7330c2aa98e2SPeter Wemm 	char *key;
7331c2aa98e2SPeter Wemm 	char **args;
7332c2aa98e2SPeter Wemm 	int *pstat;
7333c2aa98e2SPeter Wemm {
7334c2aa98e2SPeter Wemm 	int mapno;
7335c2aa98e2SPeter Wemm 	int mapbit = 0x01;
733640266059SGregory Neil Shapiro 	bool tempfail = false;
7337c2aa98e2SPeter Wemm 
7338c2aa98e2SPeter Wemm 	if (tTd(38, 20))
733940266059SGregory Neil Shapiro 		sm_dprintf("seq_map_lookup(%s, %s)\n", map->map_mname, key);
7340c2aa98e2SPeter Wemm 
7341c2aa98e2SPeter Wemm 	for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++)
7342c2aa98e2SPeter Wemm 	{
7343c2aa98e2SPeter Wemm 		MAP *mm = map->map_stack[mapno];
7344c2aa98e2SPeter Wemm 		char *rv;
7345c2aa98e2SPeter Wemm 
7346c2aa98e2SPeter Wemm 		if (mm == NULL)
7347c2aa98e2SPeter Wemm 			continue;
734806f25ae9SGregory Neil Shapiro 		if (!bitset(MF_OPEN, mm->map_mflags) &&
734906f25ae9SGregory Neil Shapiro 		    !openmap(mm))
7350c2aa98e2SPeter Wemm 		{
7351c2aa98e2SPeter Wemm 			if (bitset(mapbit, map->map_return[MA_UNAVAIL]))
7352c2aa98e2SPeter Wemm 			{
7353c2aa98e2SPeter Wemm 				*pstat = EX_UNAVAILABLE;
7354c2aa98e2SPeter Wemm 				return NULL;
7355c2aa98e2SPeter Wemm 			}
7356c2aa98e2SPeter Wemm 			continue;
7357c2aa98e2SPeter Wemm 		}
7358c2aa98e2SPeter Wemm 		*pstat = EX_OK;
7359c2aa98e2SPeter Wemm 		rv = mm->map_class->map_lookup(mm, key, args, pstat);
7360c2aa98e2SPeter Wemm 		if (rv != NULL)
7361c2aa98e2SPeter Wemm 			return rv;
7362c2aa98e2SPeter Wemm 		if (*pstat == EX_TEMPFAIL)
7363c2aa98e2SPeter Wemm 		{
7364c2aa98e2SPeter Wemm 			if (bitset(mapbit, map->map_return[MA_TRYAGAIN]))
7365c2aa98e2SPeter Wemm 				return NULL;
736640266059SGregory Neil Shapiro 			tempfail = true;
7367c2aa98e2SPeter Wemm 		}
7368c2aa98e2SPeter Wemm 		else if (bitset(mapbit, map->map_return[MA_NOTFOUND]))
7369c2aa98e2SPeter Wemm 			break;
7370c2aa98e2SPeter Wemm 	}
7371c2aa98e2SPeter Wemm 	if (tempfail)
7372c2aa98e2SPeter Wemm 		*pstat = EX_TEMPFAIL;
7373c2aa98e2SPeter Wemm 	else if (*pstat == EX_OK)
7374c2aa98e2SPeter Wemm 		*pstat = EX_NOTFOUND;
7375c2aa98e2SPeter Wemm 	return NULL;
7376c2aa98e2SPeter Wemm }
7377c2aa98e2SPeter Wemm 
7378c2aa98e2SPeter Wemm /*
7379c2aa98e2SPeter Wemm **  SEQ_MAP_STORE -- sequenced map store
7380c2aa98e2SPeter Wemm */
7381c2aa98e2SPeter Wemm 
7382c2aa98e2SPeter Wemm void
seq_map_store(map,key,val)7383c2aa98e2SPeter Wemm seq_map_store(map, key, val)
7384c2aa98e2SPeter Wemm 	MAP *map;
7385c2aa98e2SPeter Wemm 	char *key;
7386c2aa98e2SPeter Wemm 	char *val;
7387c2aa98e2SPeter Wemm {
7388c2aa98e2SPeter Wemm 	int mapno;
7389c2aa98e2SPeter Wemm 
7390c2aa98e2SPeter Wemm 	if (tTd(38, 12))
739140266059SGregory Neil Shapiro 		sm_dprintf("seq_map_store(%s, %s, %s)\n",
7392c2aa98e2SPeter Wemm 			map->map_mname, key, val);
7393c2aa98e2SPeter Wemm 
7394c2aa98e2SPeter Wemm 	for (mapno = 0; mapno < MAXMAPSTACK; mapno++)
7395c2aa98e2SPeter Wemm 	{
7396c2aa98e2SPeter Wemm 		MAP *mm = map->map_stack[mapno];
7397c2aa98e2SPeter Wemm 
7398c2aa98e2SPeter Wemm 		if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags))
7399c2aa98e2SPeter Wemm 			continue;
7400c2aa98e2SPeter Wemm 
7401c2aa98e2SPeter Wemm 		mm->map_class->map_store(mm, key, val);
7402c2aa98e2SPeter Wemm 		return;
7403c2aa98e2SPeter Wemm 	}
7404c2aa98e2SPeter Wemm 	syserr("seq_map_store(%s, %s, %s): no writable map",
7405c2aa98e2SPeter Wemm 		map->map_mname, key, val);
7406c2aa98e2SPeter Wemm }
740740266059SGregory Neil Shapiro /*
7408c2aa98e2SPeter Wemm **  NULL stubs
7409c2aa98e2SPeter Wemm */
7410c2aa98e2SPeter Wemm 
7411c2aa98e2SPeter Wemm /* ARGSUSED */
7412c2aa98e2SPeter Wemm bool
null_map_open(map,mode)7413c2aa98e2SPeter Wemm null_map_open(map, mode)
7414c2aa98e2SPeter Wemm 	MAP *map;
7415c2aa98e2SPeter Wemm 	int mode;
7416c2aa98e2SPeter Wemm {
741740266059SGregory Neil Shapiro 	return true;
7418c2aa98e2SPeter Wemm }
7419c2aa98e2SPeter Wemm 
7420c2aa98e2SPeter Wemm /* ARGSUSED */
7421c2aa98e2SPeter Wemm void
null_map_close(map)7422c2aa98e2SPeter Wemm null_map_close(map)
7423c2aa98e2SPeter Wemm 	MAP *map;
7424c2aa98e2SPeter Wemm {
7425c2aa98e2SPeter Wemm 	return;
7426c2aa98e2SPeter Wemm }
7427c2aa98e2SPeter Wemm 
7428c2aa98e2SPeter Wemm char *
null_map_lookup(map,key,args,pstat)7429c2aa98e2SPeter Wemm null_map_lookup(map, key, args, pstat)
7430c2aa98e2SPeter Wemm 	MAP *map;
7431c2aa98e2SPeter Wemm 	char *key;
7432c2aa98e2SPeter Wemm 	char **args;
7433c2aa98e2SPeter Wemm 	int *pstat;
7434c2aa98e2SPeter Wemm {
7435c2aa98e2SPeter Wemm 	*pstat = EX_NOTFOUND;
7436c2aa98e2SPeter Wemm 	return NULL;
7437c2aa98e2SPeter Wemm }
7438c2aa98e2SPeter Wemm 
7439c2aa98e2SPeter Wemm /* ARGSUSED */
7440c2aa98e2SPeter Wemm void
null_map_store(map,key,val)7441c2aa98e2SPeter Wemm null_map_store(map, key, val)
7442c2aa98e2SPeter Wemm 	MAP *map;
7443c2aa98e2SPeter Wemm 	char *key;
7444c2aa98e2SPeter Wemm 	char *val;
7445c2aa98e2SPeter Wemm {
7446c2aa98e2SPeter Wemm 	return;
7447c2aa98e2SPeter Wemm }
7448c2aa98e2SPeter Wemm 
74499bd497b8SGregory Neil Shapiro MAPCLASS	NullMapClass =
74509bd497b8SGregory Neil Shapiro {
74519bd497b8SGregory Neil Shapiro 	"null-map",		NULL,			0,
74529bd497b8SGregory Neil Shapiro 	NULL,			null_map_lookup,	null_map_store,
74539bd497b8SGregory Neil Shapiro 	null_map_open,		null_map_close,
74549bd497b8SGregory Neil Shapiro };
74559bd497b8SGregory Neil Shapiro 
7456c2aa98e2SPeter Wemm /*
7457c2aa98e2SPeter Wemm **  BOGUS stubs
7458c2aa98e2SPeter Wemm */
7459c2aa98e2SPeter Wemm 
7460c2aa98e2SPeter Wemm char *
bogus_map_lookup(map,key,args,pstat)7461c2aa98e2SPeter Wemm bogus_map_lookup(map, key, args, pstat)
7462c2aa98e2SPeter Wemm 	MAP *map;
7463c2aa98e2SPeter Wemm 	char *key;
7464c2aa98e2SPeter Wemm 	char **args;
7465c2aa98e2SPeter Wemm 	int *pstat;
7466c2aa98e2SPeter Wemm {
7467c2aa98e2SPeter Wemm 	*pstat = EX_TEMPFAIL;
7468c2aa98e2SPeter Wemm 	return NULL;
7469c2aa98e2SPeter Wemm }
7470c2aa98e2SPeter Wemm 
7471c2aa98e2SPeter Wemm MAPCLASS	BogusMapClass =
7472c2aa98e2SPeter Wemm {
7473c2aa98e2SPeter Wemm 	"bogus-map",		NULL,			0,
7474c2aa98e2SPeter Wemm 	NULL,			bogus_map_lookup,	null_map_store,
7475c2aa98e2SPeter Wemm 	null_map_open,		null_map_close,
7476c2aa98e2SPeter Wemm };
747740266059SGregory Neil Shapiro /*
747806f25ae9SGregory Neil Shapiro **  MACRO modules
747906f25ae9SGregory Neil Shapiro */
748006f25ae9SGregory Neil Shapiro 
748106f25ae9SGregory Neil Shapiro char *
macro_map_lookup(map,name,av,statp)748206f25ae9SGregory Neil Shapiro macro_map_lookup(map, name, av, statp)
748306f25ae9SGregory Neil Shapiro 	MAP *map;
748406f25ae9SGregory Neil Shapiro 	char *name;
748506f25ae9SGregory Neil Shapiro 	char **av;
748606f25ae9SGregory Neil Shapiro 	int *statp;
748706f25ae9SGregory Neil Shapiro {
748806f25ae9SGregory Neil Shapiro 	int mid;
748906f25ae9SGregory Neil Shapiro 
749006f25ae9SGregory Neil Shapiro 	if (tTd(38, 20))
749140266059SGregory Neil Shapiro 		sm_dprintf("macro_map_lookup(%s, %s)\n", map->map_mname,
749206f25ae9SGregory Neil Shapiro 			name == NULL ? "NULL" : name);
749306f25ae9SGregory Neil Shapiro 
749406f25ae9SGregory Neil Shapiro 	if (name == NULL ||
749506f25ae9SGregory Neil Shapiro 	    *name == '\0' ||
749640266059SGregory Neil Shapiro 	    (mid = macid(name)) == 0)
749706f25ae9SGregory Neil Shapiro 	{
749806f25ae9SGregory Neil Shapiro 		*statp = EX_CONFIG;
749906f25ae9SGregory Neil Shapiro 		return NULL;
750006f25ae9SGregory Neil Shapiro 	}
750106f25ae9SGregory Neil Shapiro 
750206f25ae9SGregory Neil Shapiro 	if (av[1] == NULL)
750340266059SGregory Neil Shapiro 		macdefine(&CurEnv->e_macro, A_PERM, mid, NULL);
750406f25ae9SGregory Neil Shapiro 	else
750540266059SGregory Neil Shapiro 		macdefine(&CurEnv->e_macro, A_TEMP, mid, av[1]);
750606f25ae9SGregory Neil Shapiro 
750706f25ae9SGregory Neil Shapiro 	*statp = EX_OK;
750806f25ae9SGregory Neil Shapiro 	return "";
750906f25ae9SGregory Neil Shapiro }
751040266059SGregory Neil Shapiro /*
7511c2aa98e2SPeter Wemm **  REGEX modules
7512c2aa98e2SPeter Wemm */
7513c2aa98e2SPeter Wemm 
751440266059SGregory Neil Shapiro #if MAP_REGEX
7515c2aa98e2SPeter Wemm 
7516c2aa98e2SPeter Wemm # include <regex.h>
7517c2aa98e2SPeter Wemm 
7518c2aa98e2SPeter Wemm # define DEFAULT_DELIM	CONDELSE
7519c2aa98e2SPeter Wemm # define END_OF_FIELDS	-1
7520c2aa98e2SPeter Wemm # define ERRBUF_SIZE	80
7521c2aa98e2SPeter Wemm # define MAX_MATCH	32
7522c2aa98e2SPeter Wemm 
752306f25ae9SGregory Neil Shapiro # define xnalloc(s)	memset(xalloc(s), '\0', s);
7524c2aa98e2SPeter Wemm 
7525c2aa98e2SPeter Wemm struct regex_map
7526c2aa98e2SPeter Wemm {
7527193538b7SGregory Neil Shapiro 	regex_t	*regex_pattern_buf;	/* xalloc it */
7528c2aa98e2SPeter Wemm 	int	*regex_subfields;	/* move to type MAP */
752906f25ae9SGregory Neil Shapiro 	char	*regex_delim;		/* move to type MAP */
7530c2aa98e2SPeter Wemm };
7531c2aa98e2SPeter Wemm 
7532b6bacd31SGregory Neil Shapiro static int	parse_fields __P((char *, int *, int, int));
7533b6bacd31SGregory Neil Shapiro static char	*regex_map_rewrite __P((MAP *, const char*, size_t, char **));
7534b6bacd31SGregory Neil Shapiro 
7535c2aa98e2SPeter Wemm static int
parse_fields(s,ibuf,blen,nr_substrings)7536c2aa98e2SPeter Wemm parse_fields(s, ibuf, blen, nr_substrings)
7537c2aa98e2SPeter Wemm 	char *s;
7538c2aa98e2SPeter Wemm 	int *ibuf;		/* array */
7539c2aa98e2SPeter Wemm 	int blen;		/* number of elements in ibuf */
7540c2aa98e2SPeter Wemm 	int nr_substrings;	/* number of substrings in the pattern */
7541c2aa98e2SPeter Wemm {
7542c2aa98e2SPeter Wemm 	register char *cp;
7543c2aa98e2SPeter Wemm 	int i = 0;
754440266059SGregory Neil Shapiro 	bool lastone = false;
7545c2aa98e2SPeter Wemm 
7546c2aa98e2SPeter Wemm 	blen--;		/* for terminating END_OF_FIELDS */
7547c2aa98e2SPeter Wemm 	cp = s;
7548c2aa98e2SPeter Wemm 	do
7549c2aa98e2SPeter Wemm 	{
7550c2aa98e2SPeter Wemm 		for (;; cp++)
7551c2aa98e2SPeter Wemm 		{
7552c2aa98e2SPeter Wemm 			if (*cp == ',')
7553c2aa98e2SPeter Wemm 			{
7554c2aa98e2SPeter Wemm 				*cp = '\0';
7555c2aa98e2SPeter Wemm 				break;
7556c2aa98e2SPeter Wemm 			}
7557c2aa98e2SPeter Wemm 			if (*cp == '\0')
7558c2aa98e2SPeter Wemm 			{
755940266059SGregory Neil Shapiro 				lastone = true;
7560c2aa98e2SPeter Wemm 				break;
7561c2aa98e2SPeter Wemm 			}
7562c2aa98e2SPeter Wemm 		}
7563c2aa98e2SPeter Wemm 		if (i < blen)
7564c2aa98e2SPeter Wemm 		{
7565c2aa98e2SPeter Wemm 			int val = atoi(s);
7566c2aa98e2SPeter Wemm 
7567c2aa98e2SPeter Wemm 			if (val < 0 || val >= nr_substrings)
7568c2aa98e2SPeter Wemm 			{
7569c2aa98e2SPeter Wemm 				syserr("field (%d) out of range, only %d substrings in pattern",
7570c2aa98e2SPeter Wemm 				       val, nr_substrings);
7571c2aa98e2SPeter Wemm 				return -1;
7572c2aa98e2SPeter Wemm 			}
7573c2aa98e2SPeter Wemm 			ibuf[i++] = val;
7574c2aa98e2SPeter Wemm 		}
7575c2aa98e2SPeter Wemm 		else
7576c2aa98e2SPeter Wemm 		{
757740266059SGregory Neil Shapiro 			syserr("too many fields, %d max", blen);
7578c2aa98e2SPeter Wemm 			return -1;
7579c2aa98e2SPeter Wemm 		}
7580c2aa98e2SPeter Wemm 		s = ++cp;
7581c2aa98e2SPeter Wemm 	} while (!lastone);
7582c2aa98e2SPeter Wemm 	ibuf[i] = END_OF_FIELDS;
7583c2aa98e2SPeter Wemm 	return i;
7584c2aa98e2SPeter Wemm }
7585c2aa98e2SPeter Wemm 
7586c2aa98e2SPeter Wemm bool
regex_map_init(map,ap)7587c2aa98e2SPeter Wemm regex_map_init(map, ap)
7588c2aa98e2SPeter Wemm 	MAP *map;
7589c2aa98e2SPeter Wemm 	char *ap;
7590c2aa98e2SPeter Wemm {
7591c2aa98e2SPeter Wemm 	int regerr;
7592c2aa98e2SPeter Wemm 	struct regex_map *map_p;
7593c2aa98e2SPeter Wemm 	register char *p;
7594c2aa98e2SPeter Wemm 	char *sub_param = NULL;
7595c2aa98e2SPeter Wemm 	int pflags;
7596c2aa98e2SPeter Wemm 	static char defdstr[] = { (char) DEFAULT_DELIM, '\0' };
7597c2aa98e2SPeter Wemm 
7598c2aa98e2SPeter Wemm 	if (tTd(38, 2))
759940266059SGregory Neil Shapiro 		sm_dprintf("regex_map_init: mapname '%s', args '%s'\n",
7600c2aa98e2SPeter Wemm 			map->map_mname, ap);
7601c2aa98e2SPeter Wemm 
7602c2aa98e2SPeter Wemm 	pflags = REG_ICASE | REG_EXTENDED | REG_NOSUB;
7603c2aa98e2SPeter Wemm 	p = ap;
7604d0cef73dSGregory Neil Shapiro 	map_p = (struct regex_map *) xnalloc(sizeof(*map_p));
7605193538b7SGregory Neil Shapiro 	map_p->regex_pattern_buf = (regex_t *)xnalloc(sizeof(regex_t));
7606c2aa98e2SPeter Wemm 
7607c2aa98e2SPeter Wemm 	for (;;)
7608c2aa98e2SPeter Wemm 	{
76095b0945b5SGregory Neil Shapiro 		while (SM_ISSPACE(*p))
7610c2aa98e2SPeter Wemm 			p++;
7611c2aa98e2SPeter Wemm 		if (*p != '-')
7612c2aa98e2SPeter Wemm 			break;
7613c2aa98e2SPeter Wemm 		switch (*++p)
7614c2aa98e2SPeter Wemm 		{
7615c2aa98e2SPeter Wemm 		  case 'n':	/* not */
7616c2aa98e2SPeter Wemm 			map->map_mflags |= MF_REGEX_NOT;
7617c2aa98e2SPeter Wemm 			break;
7618c2aa98e2SPeter Wemm 
7619c2aa98e2SPeter Wemm 		  case 'f':	/* case sensitive */
7620c2aa98e2SPeter Wemm 			map->map_mflags |= MF_NOFOLDCASE;
7621c2aa98e2SPeter Wemm 			pflags &= ~REG_ICASE;
7622c2aa98e2SPeter Wemm 			break;
7623c2aa98e2SPeter Wemm 
7624c2aa98e2SPeter Wemm 		  case 'b':	/* basic regular expressions */
7625c2aa98e2SPeter Wemm 			pflags &= ~REG_EXTENDED;
7626c2aa98e2SPeter Wemm 			break;
7627c2aa98e2SPeter Wemm 
7628c2aa98e2SPeter Wemm 		  case 's':	/* substring match () syntax */
7629c2aa98e2SPeter Wemm 			sub_param = ++p;
7630c2aa98e2SPeter Wemm 			pflags &= ~REG_NOSUB;
7631c2aa98e2SPeter Wemm 			break;
7632c2aa98e2SPeter Wemm 
7633c2aa98e2SPeter Wemm 		  case 'd':	/* delimiter */
763406f25ae9SGregory Neil Shapiro 			map_p->regex_delim = ++p;
7635c2aa98e2SPeter Wemm 			break;
7636c2aa98e2SPeter Wemm 
7637c2aa98e2SPeter Wemm 		  case 'a':	/* map append */
7638c2aa98e2SPeter Wemm 			map->map_app = ++p;
7639c2aa98e2SPeter Wemm 			break;
7640c2aa98e2SPeter Wemm 
7641c2aa98e2SPeter Wemm 		  case 'm':	/* matchonly */
7642c2aa98e2SPeter Wemm 			map->map_mflags |= MF_MATCHONLY;
7643c2aa98e2SPeter Wemm 			break;
7644c2aa98e2SPeter Wemm 
7645a7ec597cSGregory Neil Shapiro 		  case 'q':
7646a7ec597cSGregory Neil Shapiro 			map->map_mflags |= MF_KEEPQUOTES;
7647a7ec597cSGregory Neil Shapiro 			break;
7648a7ec597cSGregory Neil Shapiro 
764906f25ae9SGregory Neil Shapiro 		  case 'S':
765006f25ae9SGregory Neil Shapiro 			map->map_spacesub = *++p;
765106f25ae9SGregory Neil Shapiro 			break;
765206f25ae9SGregory Neil Shapiro 
765306f25ae9SGregory Neil Shapiro 		  case 'D':
765406f25ae9SGregory Neil Shapiro 			map->map_mflags |= MF_DEFER;
765506f25ae9SGregory Neil Shapiro 			break;
765606f25ae9SGregory Neil Shapiro 
7657c2aa98e2SPeter Wemm 		}
76585b0945b5SGregory Neil Shapiro 		while (*p != '\0' && !(SM_ISSPACE(*p)))
7659c2aa98e2SPeter Wemm 			p++;
7660c2aa98e2SPeter Wemm 		if (*p != '\0')
7661c2aa98e2SPeter Wemm 			*p++ = '\0';
7662c2aa98e2SPeter Wemm 	}
76632fb4f839SGregory Neil Shapiro # if _FFR_8BITENVADDR
76642fb4f839SGregory Neil Shapiro 	(void) dequote_internal_chars(p, p, strlen(p) + 1);
76652fb4f839SGregory Neil Shapiro # endif
7666c2aa98e2SPeter Wemm 	if (tTd(38, 3))
766740266059SGregory Neil Shapiro 		sm_dprintf("regex_map_init: compile '%s' 0x%x\n", p, pflags);
7668c2aa98e2SPeter Wemm 
7669193538b7SGregory Neil Shapiro 	if ((regerr = regcomp(map_p->regex_pattern_buf, p, pflags)) != 0)
7670c2aa98e2SPeter Wemm 	{
7671c2aa98e2SPeter Wemm 		/* Errorhandling */
7672c2aa98e2SPeter Wemm 		char errbuf[ERRBUF_SIZE];
7673c2aa98e2SPeter Wemm 
7674193538b7SGregory Neil Shapiro 		(void) regerror(regerr, map_p->regex_pattern_buf,
7675d0cef73dSGregory Neil Shapiro 			 errbuf, sizeof(errbuf));
767640266059SGregory Neil Shapiro 		syserr("pattern-compile-error: %s", errbuf);
767740266059SGregory Neil Shapiro 		sm_free(map_p->regex_pattern_buf); /* XXX */
767840266059SGregory Neil Shapiro 		sm_free(map_p); /* XXX */
767940266059SGregory Neil Shapiro 		return false;
7680c2aa98e2SPeter Wemm 	}
7681c2aa98e2SPeter Wemm 
7682c2aa98e2SPeter Wemm 	if (map->map_app != NULL)
7683c2aa98e2SPeter Wemm 		map->map_app = newstr(map->map_app);
768406f25ae9SGregory Neil Shapiro 	if (map_p->regex_delim != NULL)
768506f25ae9SGregory Neil Shapiro 		map_p->regex_delim = newstr(map_p->regex_delim);
7686c2aa98e2SPeter Wemm 	else
768706f25ae9SGregory Neil Shapiro 		map_p->regex_delim = defdstr;
7688c2aa98e2SPeter Wemm 
7689c2aa98e2SPeter Wemm 	if (!bitset(REG_NOSUB, pflags))
7690c2aa98e2SPeter Wemm 	{
7691c2aa98e2SPeter Wemm 		/* substring matching */
7692c2aa98e2SPeter Wemm 		int substrings;
7693c2aa98e2SPeter Wemm 		int *fields = (int *) xalloc(sizeof(int) * (MAX_MATCH + 1));
7694c2aa98e2SPeter Wemm 
7695193538b7SGregory Neil Shapiro 		substrings = map_p->regex_pattern_buf->re_nsub + 1;
7696c2aa98e2SPeter Wemm 
7697c2aa98e2SPeter Wemm 		if (tTd(38, 3))
769840266059SGregory Neil Shapiro 			sm_dprintf("regex_map_init: nr of substrings %d\n",
769906f25ae9SGregory Neil Shapiro 				substrings);
7700c2aa98e2SPeter Wemm 
7701c2aa98e2SPeter Wemm 		if (substrings >= MAX_MATCH)
7702c2aa98e2SPeter Wemm 		{
770340266059SGregory Neil Shapiro 			syserr("too many substrings, %d max", MAX_MATCH);
77042fb4f839SGregory Neil Shapiro 			SM_FREE(map_p->regex_pattern_buf); /* XXX */
77052fb4f839SGregory Neil Shapiro 			SM_FREE(map_p); /* XXX */
77062fb4f839SGregory Neil Shapiro 			SM_FREE(fields);
770740266059SGregory Neil Shapiro 			return false;
7708c2aa98e2SPeter Wemm 		}
7709c2aa98e2SPeter Wemm 		if (sub_param != NULL && sub_param[0] != '\0')
7710c2aa98e2SPeter Wemm 		{
7711c2aa98e2SPeter Wemm 			/* optional parameter -sfields */
7712c2aa98e2SPeter Wemm 			if (parse_fields(sub_param, fields,
7713c2aa98e2SPeter Wemm 					 MAX_MATCH + 1, substrings) == -1)
77142fb4f839SGregory Neil Shapiro 			{
77152fb4f839SGregory Neil Shapiro 				SM_FREE(map_p->regex_pattern_buf); /* XXX */
77162fb4f839SGregory Neil Shapiro 				SM_FREE(map_p); /* XXX */
77172fb4f839SGregory Neil Shapiro 				SM_FREE(fields);
771840266059SGregory Neil Shapiro 				return false;
7719c2aa98e2SPeter Wemm 			}
77202fb4f839SGregory Neil Shapiro 		}
7721c2aa98e2SPeter Wemm 		else
7722c2aa98e2SPeter Wemm 		{
7723c2aa98e2SPeter Wemm 			int i;
7724c2aa98e2SPeter Wemm 
772540266059SGregory Neil Shapiro 			/* set default fields */
7726c2aa98e2SPeter Wemm 			for (i = 0; i < substrings; i++)
7727c2aa98e2SPeter Wemm 				fields[i] = i;
7728c2aa98e2SPeter Wemm 			fields[i] = END_OF_FIELDS;
7729c2aa98e2SPeter Wemm 		}
7730c2aa98e2SPeter Wemm 		map_p->regex_subfields = fields;
7731c2aa98e2SPeter Wemm 		if (tTd(38, 3))
7732c2aa98e2SPeter Wemm 		{
7733c2aa98e2SPeter Wemm 			int *ip;
7734c2aa98e2SPeter Wemm 
773540266059SGregory Neil Shapiro 			sm_dprintf("regex_map_init: subfields");
7736c2aa98e2SPeter Wemm 			for (ip = fields; *ip != END_OF_FIELDS; ip++)
773740266059SGregory Neil Shapiro 				sm_dprintf(" %d", *ip);
773840266059SGregory Neil Shapiro 			sm_dprintf("\n");
7739c2aa98e2SPeter Wemm 		}
7740c2aa98e2SPeter Wemm 	}
7741c2aa98e2SPeter Wemm 	map->map_db1 = (ARBPTR_T) map_p;	/* dirty hack */
774240266059SGregory Neil Shapiro 	return true;
7743c2aa98e2SPeter Wemm }
7744c2aa98e2SPeter Wemm 
7745c2aa98e2SPeter Wemm static char *
regex_map_rewrite(map,s,slen,av)7746c2aa98e2SPeter Wemm regex_map_rewrite(map, s, slen, av)
7747c2aa98e2SPeter Wemm 	MAP *map;
7748c2aa98e2SPeter Wemm 	const char *s;
7749c2aa98e2SPeter Wemm 	size_t slen;
7750c2aa98e2SPeter Wemm 	char **av;
7751c2aa98e2SPeter Wemm {
7752c2aa98e2SPeter Wemm 	if (bitset(MF_MATCHONLY, map->map_mflags))
7753c2aa98e2SPeter Wemm 		return map_rewrite(map, av[0], strlen(av[0]), NULL);
7754c2aa98e2SPeter Wemm 	else
77558774250cSGregory Neil Shapiro 		return map_rewrite(map, s, slen, av);
7756c2aa98e2SPeter Wemm }
7757c2aa98e2SPeter Wemm 
7758c2aa98e2SPeter Wemm char *
regex_map_lookup(map,name,av,statp)7759c2aa98e2SPeter Wemm regex_map_lookup(map, name, av, statp)
7760c2aa98e2SPeter Wemm 	MAP *map;
7761c2aa98e2SPeter Wemm 	char *name;
7762c2aa98e2SPeter Wemm 	char **av;
7763c2aa98e2SPeter Wemm 	int *statp;
7764c2aa98e2SPeter Wemm {
7765c2aa98e2SPeter Wemm 	int reg_res;
7766c2aa98e2SPeter Wemm 	struct regex_map *map_p;
7767c2aa98e2SPeter Wemm 	regmatch_t pmatch[MAX_MATCH];
7768c2aa98e2SPeter Wemm 
7769c2aa98e2SPeter Wemm 	if (tTd(38, 20))
7770c2aa98e2SPeter Wemm 	{
7771c2aa98e2SPeter Wemm 		char **cpp;
7772c2aa98e2SPeter Wemm 
77732fb4f839SGregory Neil Shapiro 		sm_dprintf("regex_map_lookup: name=%s, key='%s'\n",
77742fb4f839SGregory Neil Shapiro 			map->map_mname, name);
777506f25ae9SGregory Neil Shapiro 		for (cpp = av; cpp != NULL && *cpp != NULL; cpp++)
777640266059SGregory Neil Shapiro 			sm_dprintf("regex_map_lookup: arg '%s'\n", *cpp);
7777c2aa98e2SPeter Wemm 	}
7778c2aa98e2SPeter Wemm 
7779c2aa98e2SPeter Wemm 	map_p = (struct regex_map *)(map->map_db1);
7780193538b7SGregory Neil Shapiro 	reg_res = regexec(map_p->regex_pattern_buf,
778106f25ae9SGregory Neil Shapiro 			  name, MAX_MATCH, pmatch, 0);
7782c2aa98e2SPeter Wemm 
7783c2aa98e2SPeter Wemm 	if (bitset(MF_REGEX_NOT, map->map_mflags))
7784c2aa98e2SPeter Wemm 	{
7785c2aa98e2SPeter Wemm 		/* option -n */
7786c2aa98e2SPeter Wemm 		if (reg_res == REG_NOMATCH)
7787c2aa98e2SPeter Wemm 			return regex_map_rewrite(map, "", (size_t) 0, av);
7788c2aa98e2SPeter Wemm 		else
7789c2aa98e2SPeter Wemm 			return NULL;
7790c2aa98e2SPeter Wemm 	}
7791c2aa98e2SPeter Wemm 	if (reg_res == REG_NOMATCH)
7792c2aa98e2SPeter Wemm 		return NULL;
7793c2aa98e2SPeter Wemm 
7794c2aa98e2SPeter Wemm 	if (map_p->regex_subfields != NULL)
7795c2aa98e2SPeter Wemm 	{
7796c2aa98e2SPeter Wemm 		/* option -s */
77972fb4f839SGregory Neil Shapiro 		static char retbuf[MAXNAME];	/* EAI:not relevant */
7798c2aa98e2SPeter Wemm 		int fields[MAX_MATCH + 1];
779940266059SGregory Neil Shapiro 		bool first = true;
7800c2aa98e2SPeter Wemm 		int anglecnt = 0, cmntcnt = 0, spacecnt = 0;
780140266059SGregory Neil Shapiro 		bool quotemode = false, bslashmode = false;
7802c2aa98e2SPeter Wemm 		register char *dp, *sp;
7803c2aa98e2SPeter Wemm 		char *endp, *ldp;
7804c2aa98e2SPeter Wemm 		int *ip;
7805c2aa98e2SPeter Wemm 
7806c2aa98e2SPeter Wemm 		dp = retbuf;
7807c2aa98e2SPeter Wemm 		ldp = retbuf + sizeof(retbuf) - 1;
7808c2aa98e2SPeter Wemm 
7809c2aa98e2SPeter Wemm 		if (av[1] != NULL)
7810c2aa98e2SPeter Wemm 		{
7811c2aa98e2SPeter Wemm 			if (parse_fields(av[1], fields, MAX_MATCH + 1,
7812193538b7SGregory Neil Shapiro 					 (int) map_p->regex_pattern_buf->re_nsub + 1) == -1)
7813c2aa98e2SPeter Wemm 			{
7814c2aa98e2SPeter Wemm 				*statp = EX_CONFIG;
7815c2aa98e2SPeter Wemm 				return NULL;
7816c2aa98e2SPeter Wemm 			}
7817c2aa98e2SPeter Wemm 			ip = fields;
7818c2aa98e2SPeter Wemm 		}
7819c2aa98e2SPeter Wemm 		else
7820c2aa98e2SPeter Wemm 			ip = map_p->regex_subfields;
7821c2aa98e2SPeter Wemm 
7822c2aa98e2SPeter Wemm 		for ( ; *ip != END_OF_FIELDS; ip++)
7823c2aa98e2SPeter Wemm 		{
7824c2aa98e2SPeter Wemm 			if (!first)
7825c2aa98e2SPeter Wemm 			{
782606f25ae9SGregory Neil Shapiro 				for (sp = map_p->regex_delim; *sp; sp++)
7827c2aa98e2SPeter Wemm 				{
7828c2aa98e2SPeter Wemm 					if (dp < ldp)
7829c2aa98e2SPeter Wemm 						*dp++ = *sp;
7830c2aa98e2SPeter Wemm 				}
7831c2aa98e2SPeter Wemm 			}
7832c2aa98e2SPeter Wemm 			else
783340266059SGregory Neil Shapiro 				first = false;
7834c2aa98e2SPeter Wemm 
7835193538b7SGregory Neil Shapiro 			if (*ip >= MAX_MATCH ||
7836193538b7SGregory Neil Shapiro 			    pmatch[*ip].rm_so < 0 || pmatch[*ip].rm_eo < 0)
7837c2aa98e2SPeter Wemm 				continue;
7838c2aa98e2SPeter Wemm 
7839c2aa98e2SPeter Wemm 			sp = name + pmatch[*ip].rm_so;
7840c2aa98e2SPeter Wemm 			endp = name + pmatch[*ip].rm_eo;
7841c2aa98e2SPeter Wemm 			for (; endp > sp; sp++)
7842c2aa98e2SPeter Wemm 			{
7843c2aa98e2SPeter Wemm 				if (dp < ldp)
7844c2aa98e2SPeter Wemm 				{
7845c2aa98e2SPeter Wemm 					if (bslashmode)
7846c2aa98e2SPeter Wemm 					{
7847c2aa98e2SPeter Wemm 						*dp++ = *sp;
784840266059SGregory Neil Shapiro 						bslashmode = false;
7849c2aa98e2SPeter Wemm 					}
7850c2aa98e2SPeter Wemm 					else if (quotemode && *sp != '"' &&
7851c2aa98e2SPeter Wemm 						*sp != '\\')
7852c2aa98e2SPeter Wemm 					{
7853c2aa98e2SPeter Wemm 						*dp++ = *sp;
7854c2aa98e2SPeter Wemm 					}
7855c2aa98e2SPeter Wemm 					else switch (*dp++ = *sp)
7856c2aa98e2SPeter Wemm 					{
7857c2aa98e2SPeter Wemm 					  case '\\':
785840266059SGregory Neil Shapiro 						bslashmode = true;
7859c2aa98e2SPeter Wemm 						break;
7860c2aa98e2SPeter Wemm 
7861c2aa98e2SPeter Wemm 					  case '(':
7862c2aa98e2SPeter Wemm 						cmntcnt++;
7863c2aa98e2SPeter Wemm 						break;
7864c2aa98e2SPeter Wemm 
7865c2aa98e2SPeter Wemm 					  case ')':
7866c2aa98e2SPeter Wemm 						cmntcnt--;
7867c2aa98e2SPeter Wemm 						break;
7868c2aa98e2SPeter Wemm 
7869c2aa98e2SPeter Wemm 					  case '<':
7870c2aa98e2SPeter Wemm 						anglecnt++;
7871c2aa98e2SPeter Wemm 						break;
7872c2aa98e2SPeter Wemm 
7873c2aa98e2SPeter Wemm 					  case '>':
7874c2aa98e2SPeter Wemm 						anglecnt--;
7875c2aa98e2SPeter Wemm 						break;
7876c2aa98e2SPeter Wemm 
7877c2aa98e2SPeter Wemm 					  case ' ':
7878c2aa98e2SPeter Wemm 						spacecnt++;
7879c2aa98e2SPeter Wemm 						break;
7880c2aa98e2SPeter Wemm 
7881c2aa98e2SPeter Wemm 					  case '"':
7882c2aa98e2SPeter Wemm 						quotemode = !quotemode;
7883c2aa98e2SPeter Wemm 						break;
7884c2aa98e2SPeter Wemm 					}
7885c2aa98e2SPeter Wemm 				}
7886c2aa98e2SPeter Wemm 			}
7887c2aa98e2SPeter Wemm 		}
7888c2aa98e2SPeter Wemm 		if (anglecnt != 0 || cmntcnt != 0 || quotemode ||
7889c2aa98e2SPeter Wemm 		    bslashmode || spacecnt != 0)
7890c2aa98e2SPeter Wemm 		{
7891c2aa98e2SPeter Wemm 			sm_syslog(LOG_WARNING, NOQID,
7892c2aa98e2SPeter Wemm 				  "Warning: regex may cause prescan() failure map=%s lookup=%s",
7893c2aa98e2SPeter Wemm 				  map->map_mname, name);
7894c2aa98e2SPeter Wemm 			return NULL;
7895c2aa98e2SPeter Wemm 		}
7896c2aa98e2SPeter Wemm 		*dp = '\0';
7897c2aa98e2SPeter Wemm 		return regex_map_rewrite(map, retbuf, strlen(retbuf), av);
7898c2aa98e2SPeter Wemm 	}
7899c2aa98e2SPeter Wemm 	return regex_map_rewrite(map, "", (size_t)0, av);
7900c2aa98e2SPeter Wemm }
7901c2aa98e2SPeter Wemm #endif /* MAP_REGEX */
790240266059SGregory Neil Shapiro /*
790306f25ae9SGregory Neil Shapiro **  NSD modules
790406f25ae9SGregory Neil Shapiro */
790540266059SGregory Neil Shapiro #if MAP_NSD
790606f25ae9SGregory Neil Shapiro 
790706f25ae9SGregory Neil Shapiro # include <ndbm.h>
790806f25ae9SGregory Neil Shapiro # define _DATUM_DEFINED
790906f25ae9SGregory Neil Shapiro # include <ns_api.h>
791006f25ae9SGregory Neil Shapiro 
791106f25ae9SGregory Neil Shapiro typedef struct ns_map_list
791206f25ae9SGregory Neil Shapiro {
791340266059SGregory Neil Shapiro 	ns_map_t		*map;		/* XXX ns_ ? */
791406f25ae9SGregory Neil Shapiro 	char			*mapname;
791506f25ae9SGregory Neil Shapiro 	struct ns_map_list	*next;
791606f25ae9SGregory Neil Shapiro } ns_map_list_t;
791706f25ae9SGregory Neil Shapiro 
791806f25ae9SGregory Neil Shapiro static ns_map_t *
ns_map_t_find(mapname)791906f25ae9SGregory Neil Shapiro ns_map_t_find(mapname)
792006f25ae9SGregory Neil Shapiro 	char *mapname;
792106f25ae9SGregory Neil Shapiro {
792206f25ae9SGregory Neil Shapiro 	static ns_map_list_t *ns_maps = NULL;
792306f25ae9SGregory Neil Shapiro 	ns_map_list_t *ns_map;
792406f25ae9SGregory Neil Shapiro 
792506f25ae9SGregory Neil Shapiro 	/* walk the list of maps looking for the correctly named map */
792606f25ae9SGregory Neil Shapiro 	for (ns_map = ns_maps; ns_map != NULL; ns_map = ns_map->next)
792706f25ae9SGregory Neil Shapiro 	{
792806f25ae9SGregory Neil Shapiro 		if (strcmp(ns_map->mapname, mapname) == 0)
792906f25ae9SGregory Neil Shapiro 			break;
793006f25ae9SGregory Neil Shapiro 	}
793106f25ae9SGregory Neil Shapiro 
793206f25ae9SGregory Neil Shapiro 	/* if we are looking at a NULL ns_map_list_t, then create a new one */
793306f25ae9SGregory Neil Shapiro 	if (ns_map == NULL)
793406f25ae9SGregory Neil Shapiro 	{
7935d0cef73dSGregory Neil Shapiro 		ns_map = (ns_map_list_t *) xalloc(sizeof(*ns_map));
793606f25ae9SGregory Neil Shapiro 		ns_map->mapname = newstr(mapname);
7937d0cef73dSGregory Neil Shapiro 		ns_map->map = (ns_map_t *) xalloc(sizeof(*ns_map->map));
7938d0cef73dSGregory Neil Shapiro 		memset(ns_map->map, '\0', sizeof(*ns_map->map));
793906f25ae9SGregory Neil Shapiro 		ns_map->next = ns_maps;
794006f25ae9SGregory Neil Shapiro 		ns_maps = ns_map;
794106f25ae9SGregory Neil Shapiro 	}
794206f25ae9SGregory Neil Shapiro 	return ns_map->map;
794306f25ae9SGregory Neil Shapiro }
794406f25ae9SGregory Neil Shapiro 
794506f25ae9SGregory Neil Shapiro char *
nsd_map_lookup(map,name,av,statp)794606f25ae9SGregory Neil Shapiro nsd_map_lookup(map, name, av, statp)
794706f25ae9SGregory Neil Shapiro 	MAP *map;
794806f25ae9SGregory Neil Shapiro 	char *name;
794906f25ae9SGregory Neil Shapiro 	char **av;
795006f25ae9SGregory Neil Shapiro 	int *statp;
795106f25ae9SGregory Neil Shapiro {
7952193538b7SGregory Neil Shapiro 	int buflen, r;
795306f25ae9SGregory Neil Shapiro 	char *p;
795406f25ae9SGregory Neil Shapiro 	ns_map_t *ns_map;
79552fb4f839SGregory Neil Shapiro 	char keybuf[MAXNAME + 1];	/* EAI:ok */
795606f25ae9SGregory Neil Shapiro 	char buf[MAXLINE];
795706f25ae9SGregory Neil Shapiro 
795806f25ae9SGregory Neil Shapiro 	if (tTd(38, 20))
795940266059SGregory Neil Shapiro 		sm_dprintf("nsd_map_lookup(%s, %s)\n", map->map_mname, name);
796006f25ae9SGregory Neil Shapiro 
796106f25ae9SGregory Neil Shapiro 	buflen = strlen(name);
7962d0cef73dSGregory Neil Shapiro 	if (buflen > sizeof(keybuf) - 1)
7963d0cef73dSGregory Neil Shapiro 		buflen = sizeof(keybuf) - 1;	/* XXX simply cut off? */
796406f25ae9SGregory Neil Shapiro 	memmove(keybuf, name, buflen);
796506f25ae9SGregory Neil Shapiro 	keybuf[buflen] = '\0';
796606f25ae9SGregory Neil Shapiro 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
79672fb4f839SGregory Neil Shapiro 		makelower_buf(keybuf, keybuf, sizeof(keybuf));
796806f25ae9SGregory Neil Shapiro 
796906f25ae9SGregory Neil Shapiro 	ns_map = ns_map_t_find(map->map_file);
797006f25ae9SGregory Neil Shapiro 	if (ns_map == NULL)
797106f25ae9SGregory Neil Shapiro 	{
797206f25ae9SGregory Neil Shapiro 		if (tTd(38, 20))
797340266059SGregory Neil Shapiro 			sm_dprintf("nsd_map_t_find failed\n");
7974193538b7SGregory Neil Shapiro 		*statp = EX_UNAVAILABLE;
7975193538b7SGregory Neil Shapiro 		return NULL;
7976193538b7SGregory Neil Shapiro 	}
797794c01205SGregory Neil Shapiro 	r = ns_lookup(ns_map, NULL, map->map_file, keybuf, NULL,
7978d0cef73dSGregory Neil Shapiro 		      buf, sizeof(buf));
7979193538b7SGregory Neil Shapiro 	if (r == NS_UNAVAIL || r == NS_TRYAGAIN)
7980193538b7SGregory Neil Shapiro 	{
7981193538b7SGregory Neil Shapiro 		*statp = EX_TEMPFAIL;
7982193538b7SGregory Neil Shapiro 		return NULL;
7983193538b7SGregory Neil Shapiro 	}
79848774250cSGregory Neil Shapiro 	if (r == NS_BADREQ
79858774250cSGregory Neil Shapiro # ifdef NS_NOPERM
79868774250cSGregory Neil Shapiro 	    || r == NS_NOPERM
79875b0945b5SGregory Neil Shapiro # endif
79888774250cSGregory Neil Shapiro 	    )
7989193538b7SGregory Neil Shapiro 	{
7990193538b7SGregory Neil Shapiro 		*statp = EX_CONFIG;
7991193538b7SGregory Neil Shapiro 		return NULL;
7992193538b7SGregory Neil Shapiro 	}
7993193538b7SGregory Neil Shapiro 	if (r != NS_SUCCESS)
7994193538b7SGregory Neil Shapiro 	{
7995193538b7SGregory Neil Shapiro 		*statp = EX_NOTFOUND;
799606f25ae9SGregory Neil Shapiro 		return NULL;
799706f25ae9SGregory Neil Shapiro 	}
799806f25ae9SGregory Neil Shapiro 
7999193538b7SGregory Neil Shapiro 	*statp = EX_OK;
800006f25ae9SGregory Neil Shapiro 
800106f25ae9SGregory Neil Shapiro 	/* Null out trailing \n */
800206f25ae9SGregory Neil Shapiro 	if ((p = strchr(buf, '\n')) != NULL)
800306f25ae9SGregory Neil Shapiro 		*p = '\0';
800406f25ae9SGregory Neil Shapiro 
800506f25ae9SGregory Neil Shapiro 	return map_rewrite(map, buf, strlen(buf), av);
800606f25ae9SGregory Neil Shapiro }
800706f25ae9SGregory Neil Shapiro #endif /* MAP_NSD */
800806f25ae9SGregory Neil Shapiro 
800906f25ae9SGregory Neil Shapiro char *
arith_map_lookup(map,name,av,statp)801006f25ae9SGregory Neil Shapiro arith_map_lookup(map, name, av, statp)
801106f25ae9SGregory Neil Shapiro 	MAP *map;
801206f25ae9SGregory Neil Shapiro 	char *name;
801306f25ae9SGregory Neil Shapiro 	char **av;
801406f25ae9SGregory Neil Shapiro 	int *statp;
801506f25ae9SGregory Neil Shapiro {
801606f25ae9SGregory Neil Shapiro 	long r;
801706f25ae9SGregory Neil Shapiro 	long v[2];
801840266059SGregory Neil Shapiro 	bool res = false;
801906f25ae9SGregory Neil Shapiro 	bool boolres;
802006f25ae9SGregory Neil Shapiro 	static char result[16];
802106f25ae9SGregory Neil Shapiro 	char **cpp;
802206f25ae9SGregory Neil Shapiro 
802306f25ae9SGregory Neil Shapiro 	if (tTd(38, 2))
802406f25ae9SGregory Neil Shapiro 	{
802540266059SGregory Neil Shapiro 		sm_dprintf("arith_map_lookup: key '%s'\n", name);
802606f25ae9SGregory Neil Shapiro 		for (cpp = av; cpp != NULL && *cpp != NULL; cpp++)
802740266059SGregory Neil Shapiro 			sm_dprintf("arith_map_lookup: arg '%s'\n", *cpp);
802806f25ae9SGregory Neil Shapiro 	}
802906f25ae9SGregory Neil Shapiro 	r = 0;
803040266059SGregory Neil Shapiro 	boolres = false;
803106f25ae9SGregory Neil Shapiro 	cpp = av;
803206f25ae9SGregory Neil Shapiro 	*statp = EX_OK;
803306f25ae9SGregory Neil Shapiro 
803406f25ae9SGregory Neil Shapiro 	/*
803506f25ae9SGregory Neil Shapiro 	**  read arguments for arith map
803606f25ae9SGregory Neil Shapiro 	**  - no check is made whether they are really numbers
803706f25ae9SGregory Neil Shapiro 	**  - just ignores args after the second
803806f25ae9SGregory Neil Shapiro 	*/
803940266059SGregory Neil Shapiro 
804006f25ae9SGregory Neil Shapiro 	for (++cpp; cpp != NULL && *cpp != NULL && r < 2; cpp++)
804106f25ae9SGregory Neil Shapiro 		v[r++] = strtol(*cpp, NULL, 0);
804206f25ae9SGregory Neil Shapiro 
804306f25ae9SGregory Neil Shapiro 	/* operator and (at least) two operands given? */
804406f25ae9SGregory Neil Shapiro 	if (name != NULL && r == 2)
804506f25ae9SGregory Neil Shapiro 	{
804606f25ae9SGregory Neil Shapiro 		switch (*name)
804706f25ae9SGregory Neil Shapiro 		{
804806f25ae9SGregory Neil Shapiro 		  case '|':
804906f25ae9SGregory Neil Shapiro 			r = v[0] | v[1];
805006f25ae9SGregory Neil Shapiro 			break;
805106f25ae9SGregory Neil Shapiro 
805206f25ae9SGregory Neil Shapiro 		  case '&':
805306f25ae9SGregory Neil Shapiro 			r = v[0] & v[1];
805406f25ae9SGregory Neil Shapiro 			break;
805506f25ae9SGregory Neil Shapiro 
805606f25ae9SGregory Neil Shapiro 		  case '%':
805706f25ae9SGregory Neil Shapiro 			if (v[1] == 0)
805806f25ae9SGregory Neil Shapiro 				return NULL;
805906f25ae9SGregory Neil Shapiro 			r = v[0] % v[1];
806006f25ae9SGregory Neil Shapiro 			break;
806106f25ae9SGregory Neil Shapiro 		  case '+':
806206f25ae9SGregory Neil Shapiro 			r = v[0] + v[1];
806306f25ae9SGregory Neil Shapiro 			break;
806406f25ae9SGregory Neil Shapiro 
806506f25ae9SGregory Neil Shapiro 		  case '-':
806606f25ae9SGregory Neil Shapiro 			r = v[0] - v[1];
806706f25ae9SGregory Neil Shapiro 			break;
806806f25ae9SGregory Neil Shapiro 
806906f25ae9SGregory Neil Shapiro 		  case '*':
807006f25ae9SGregory Neil Shapiro 			r = v[0] * v[1];
807106f25ae9SGregory Neil Shapiro 			break;
807206f25ae9SGregory Neil Shapiro 
807306f25ae9SGregory Neil Shapiro 		  case '/':
807406f25ae9SGregory Neil Shapiro 			if (v[1] == 0)
807506f25ae9SGregory Neil Shapiro 				return NULL;
807606f25ae9SGregory Neil Shapiro 			r = v[0] / v[1];
807706f25ae9SGregory Neil Shapiro 			break;
807806f25ae9SGregory Neil Shapiro 
807906f25ae9SGregory Neil Shapiro 		  case 'l':
808006f25ae9SGregory Neil Shapiro 			res = v[0] < v[1];
808140266059SGregory Neil Shapiro 			boolres = true;
808206f25ae9SGregory Neil Shapiro 			break;
808306f25ae9SGregory Neil Shapiro 
808406f25ae9SGregory Neil Shapiro 		  case '=':
808506f25ae9SGregory Neil Shapiro 			res = v[0] == v[1];
808640266059SGregory Neil Shapiro 			boolres = true;
808706f25ae9SGregory Neil Shapiro 			break;
808806f25ae9SGregory Neil Shapiro 
8089d0cef73dSGregory Neil Shapiro 		  case 'r':
8090d0cef73dSGregory Neil Shapiro 			r = v[1] - v[0] + 1;
8091d0cef73dSGregory Neil Shapiro 			if (r <= 0)
8092d0cef73dSGregory Neil Shapiro 				return NULL;
8093d0cef73dSGregory Neil Shapiro 			r = get_random() % r + v[0];
8094d0cef73dSGregory Neil Shapiro 			break;
8095d0cef73dSGregory Neil Shapiro 
809606f25ae9SGregory Neil Shapiro 		  default:
809706f25ae9SGregory Neil Shapiro 			/* XXX */
809806f25ae9SGregory Neil Shapiro 			*statp = EX_CONFIG;
809906f25ae9SGregory Neil Shapiro 			if (LogLevel > 10)
810006f25ae9SGregory Neil Shapiro 				sm_syslog(LOG_WARNING, NOQID,
810106f25ae9SGregory Neil Shapiro 					  "arith_map: unknown operator %c",
81029bd497b8SGregory Neil Shapiro 					  (isascii(*name) && isprint(*name)) ?
81039bd497b8SGregory Neil Shapiro 					  *name : '?');
810406f25ae9SGregory Neil Shapiro 			return NULL;
810506f25ae9SGregory Neil Shapiro 		}
810606f25ae9SGregory Neil Shapiro 		if (boolres)
8107d0cef73dSGregory Neil Shapiro 			(void) sm_snprintf(result, sizeof(result),
810840266059SGregory Neil Shapiro 				res ? "TRUE" : "FALSE");
810906f25ae9SGregory Neil Shapiro 		else
8110d0cef73dSGregory Neil Shapiro 			(void) sm_snprintf(result, sizeof(result), "%ld", r);
811106f25ae9SGregory Neil Shapiro 		return result;
811206f25ae9SGregory Neil Shapiro 	}
811306f25ae9SGregory Neil Shapiro 	*statp = EX_CONFIG;
811406f25ae9SGregory Neil Shapiro 	return NULL;
811506f25ae9SGregory Neil Shapiro }
8116e92d3f3fSGregory Neil Shapiro 
81175dd76dd0SGregory Neil Shapiro char *
arpa_map_lookup(map,name,av,statp)81185dd76dd0SGregory Neil Shapiro arpa_map_lookup(map, name, av, statp)
81195dd76dd0SGregory Neil Shapiro 	MAP *map;
81205dd76dd0SGregory Neil Shapiro 	char *name;
81215dd76dd0SGregory Neil Shapiro 	char **av;
81225dd76dd0SGregory Neil Shapiro 	int *statp;
81235dd76dd0SGregory Neil Shapiro {
81245dd76dd0SGregory Neil Shapiro 	int r;
81255dd76dd0SGregory Neil Shapiro 	char *rval;
81265dd76dd0SGregory Neil Shapiro 	char result[128];	/* IPv6: 64 + 10 + 1 would be enough */
81275dd76dd0SGregory Neil Shapiro 
81285dd76dd0SGregory Neil Shapiro 	if (tTd(38, 2))
81295dd76dd0SGregory Neil Shapiro 		sm_dprintf("arpa_map_lookup: key '%s'\n", name);
81305dd76dd0SGregory Neil Shapiro 	*statp = EX_DATAERR;
81315dd76dd0SGregory Neil Shapiro 	r = 1;
81325dd76dd0SGregory Neil Shapiro 	memset(result, '\0', sizeof(result));
81335dd76dd0SGregory Neil Shapiro 	rval = NULL;
81345dd76dd0SGregory Neil Shapiro 
81355dd76dd0SGregory Neil Shapiro #if NETINET6
81365dd76dd0SGregory Neil Shapiro 	if (sm_strncasecmp(name, "IPv6:", 5) == 0)
81375dd76dd0SGregory Neil Shapiro 	{
81385dd76dd0SGregory Neil Shapiro 		struct in6_addr in6_addr;
81395dd76dd0SGregory Neil Shapiro 
81405dd76dd0SGregory Neil Shapiro 		r = anynet_pton(AF_INET6, name, &in6_addr);
81415dd76dd0SGregory Neil Shapiro 		if (r == 1)
81425dd76dd0SGregory Neil Shapiro 		{
81435dd76dd0SGregory Neil Shapiro 			static char hex_digits[] =
81445dd76dd0SGregory Neil Shapiro 				{ '0', '1', '2', '3', '4', '5', '6', '7', '8',
81455dd76dd0SGregory Neil Shapiro 				  '9', 'a', 'b', 'c', 'd', 'e', 'f' };
81465dd76dd0SGregory Neil Shapiro 
81475dd76dd0SGregory Neil Shapiro 			unsigned char *src;
81485dd76dd0SGregory Neil Shapiro 			char *dst;
81495dd76dd0SGregory Neil Shapiro 			int i;
81505dd76dd0SGregory Neil Shapiro 
81515dd76dd0SGregory Neil Shapiro 			src = (unsigned char *) &in6_addr;
81525dd76dd0SGregory Neil Shapiro 			dst = result;
81535dd76dd0SGregory Neil Shapiro 			for (i = 15; i >= 0; i--) {
81545dd76dd0SGregory Neil Shapiro 				*dst++ = hex_digits[src[i] & 0x0f];
81555dd76dd0SGregory Neil Shapiro 				*dst++ = '.';
81565dd76dd0SGregory Neil Shapiro 				*dst++ = hex_digits[(src[i] >> 4) & 0x0f];
81575dd76dd0SGregory Neil Shapiro 				if (i > 0)
81585dd76dd0SGregory Neil Shapiro 					*dst++ = '.';
81595dd76dd0SGregory Neil Shapiro 			}
81605dd76dd0SGregory Neil Shapiro 			*statp = EX_OK;
81615dd76dd0SGregory Neil Shapiro 		}
81625dd76dd0SGregory Neil Shapiro 	}
81635dd76dd0SGregory Neil Shapiro 	else
81645dd76dd0SGregory Neil Shapiro #endif /* NETINET6 */
81655dd76dd0SGregory Neil Shapiro #if NETINET
81665dd76dd0SGregory Neil Shapiro 	{
81675dd76dd0SGregory Neil Shapiro 		struct in_addr in_addr;
81685dd76dd0SGregory Neil Shapiro 
8169da7d7b9cSGregory Neil Shapiro 		r = inet_pton(AF_INET, name, &in_addr);
81705dd76dd0SGregory Neil Shapiro 		if (r == 1)
81715dd76dd0SGregory Neil Shapiro 		{
81725dd76dd0SGregory Neil Shapiro 			unsigned char *src;
81735dd76dd0SGregory Neil Shapiro 
81745dd76dd0SGregory Neil Shapiro 			src = (unsigned char *) &in_addr;
81755dd76dd0SGregory Neil Shapiro 			(void) snprintf(result, sizeof(result),
81765dd76dd0SGregory Neil Shapiro 				"%u.%u.%u.%u",
81775dd76dd0SGregory Neil Shapiro 				src[3], src[2], src[1], src[0]);
81785dd76dd0SGregory Neil Shapiro 			*statp = EX_OK;
81795dd76dd0SGregory Neil Shapiro 		}
81805dd76dd0SGregory Neil Shapiro 	}
81815dd76dd0SGregory Neil Shapiro #endif /* NETINET */
81825dd76dd0SGregory Neil Shapiro 	if (r < 0)
81835dd76dd0SGregory Neil Shapiro 		*statp = EX_UNAVAILABLE;
81845dd76dd0SGregory Neil Shapiro 	if (tTd(38, 2))
81855dd76dd0SGregory Neil Shapiro 		sm_dprintf("arpa_map_lookup: r=%d, result='%s'\n", r, result);
81865dd76dd0SGregory Neil Shapiro 	if (*statp == EX_OK)
81875dd76dd0SGregory Neil Shapiro 	{
81885dd76dd0SGregory Neil Shapiro 		if (bitset(MF_MATCHONLY, map->map_mflags))
81895dd76dd0SGregory Neil Shapiro 			rval = map_rewrite(map, name, strlen(name), NULL);
81905dd76dd0SGregory Neil Shapiro 		else
81915dd76dd0SGregory Neil Shapiro 			rval = map_rewrite(map, result, strlen(result), av);
81925dd76dd0SGregory Neil Shapiro 	}
81935dd76dd0SGregory Neil Shapiro 	return rval;
81945dd76dd0SGregory Neil Shapiro }
81955dd76dd0SGregory Neil Shapiro 
81965b0945b5SGregory Neil Shapiro #if _FFR_SETDEBUG_MAP
81975b0945b5SGregory Neil Shapiro char *
setdebug_map_lookup(map,name,av,statp)81985b0945b5SGregory Neil Shapiro setdebug_map_lookup(map, name, av, statp)
81995b0945b5SGregory Neil Shapiro 	MAP *map;
82005b0945b5SGregory Neil Shapiro 	char *name;
82015b0945b5SGregory Neil Shapiro 	char **av;
82025b0945b5SGregory Neil Shapiro 	int *statp;
82035b0945b5SGregory Neil Shapiro {
82045b0945b5SGregory Neil Shapiro 
82055b0945b5SGregory Neil Shapiro 	if (tTd(38, 2))
82065b0945b5SGregory Neil Shapiro 	{
82075b0945b5SGregory Neil Shapiro 		char **cpp;
82085b0945b5SGregory Neil Shapiro 
82095b0945b5SGregory Neil Shapiro 		sm_dprintf("setdebug_map_lookup: key '%s'\n", name);
82105b0945b5SGregory Neil Shapiro 		for (cpp = av; cpp != NULL && *cpp != NULL; cpp++)
82115b0945b5SGregory Neil Shapiro 			sm_dprintf("setdebug_map_lookup: arg '%s'\n", *cpp);
82125b0945b5SGregory Neil Shapiro 	}
82135b0945b5SGregory Neil Shapiro 	*statp = EX_OK;
82145b0945b5SGregory Neil Shapiro 	tTflag(name);
82155b0945b5SGregory Neil Shapiro 	return NULL;
82165b0945b5SGregory Neil Shapiro }
82175b0945b5SGregory Neil Shapiro #endif
82185b0945b5SGregory Neil Shapiro 
82195b0945b5SGregory Neil Shapiro #if _FFR_SETOPT_MAP
82205b0945b5SGregory Neil Shapiro char *
setopt_map_lookup(map,name,av,statp)82215b0945b5SGregory Neil Shapiro setopt_map_lookup(map, name, av, statp)
82225b0945b5SGregory Neil Shapiro 	MAP *map;
82235b0945b5SGregory Neil Shapiro 	char *name;
82245b0945b5SGregory Neil Shapiro 	char **av;
82255b0945b5SGregory Neil Shapiro 	int *statp;
82265b0945b5SGregory Neil Shapiro {
82275b0945b5SGregory Neil Shapiro # if !_FFR_SETANYOPT
82285b0945b5SGregory Neil Shapiro 	int val;
82295b0945b5SGregory Neil Shapiro # endif
82305b0945b5SGregory Neil Shapiro 	char **cpp;
82315b0945b5SGregory Neil Shapiro 
82325b0945b5SGregory Neil Shapiro 	if (tTd(38, 2))
82335b0945b5SGregory Neil Shapiro 	{
82345b0945b5SGregory Neil Shapiro 		sm_dprintf("setopt_map_lookup: key '%s'\n", name);
82355b0945b5SGregory Neil Shapiro 		for (cpp = av; cpp != NULL && *cpp != NULL; cpp++)
82365b0945b5SGregory Neil Shapiro 			sm_dprintf("setopt_map_lookup: arg '%s'\n", *cpp);
82375b0945b5SGregory Neil Shapiro 	}
82385b0945b5SGregory Neil Shapiro # if _FFR_SETANYOPT
82395b0945b5SGregory Neil Shapiro 	/*
82405b0945b5SGregory Neil Shapiro 	**  API screwed up...
82415b0945b5SGregory Neil Shapiro 	**  first arg is the "short" name and second is the entire string...
82425b0945b5SGregory Neil Shapiro 	*/
82435b0945b5SGregory Neil Shapiro 
82445b0945b5SGregory Neil Shapiro 	sm_dprintf("setoption: name=%s\n", name);
82455b0945b5SGregory Neil Shapiro 	setoption(' ', name, true, false, CurEnv);
82465b0945b5SGregory Neil Shapiro 	*statp = EX_OK;
82475b0945b5SGregory Neil Shapiro 	return NULL;
82485b0945b5SGregory Neil Shapiro # else /* _FFR_SETANYOPT */
82495b0945b5SGregory Neil Shapiro 	*statp = EX_CONFIG;
82505b0945b5SGregory Neil Shapiro 
82515b0945b5SGregory Neil Shapiro 	cpp = av;
82525b0945b5SGregory Neil Shapiro 	if (cpp == NULL || ++cpp == NULL || *cpp == NULL)
82535b0945b5SGregory Neil Shapiro 		return NULL;
82545b0945b5SGregory Neil Shapiro 	*statp = EX_OK;
82555b0945b5SGregory Neil Shapiro 	errno = 0;
82565b0945b5SGregory Neil Shapiro 	val = strtol(*cpp, NULL, 0);
82575b0945b5SGregory Neil Shapiro 	/* check for valid number? */
82585b0945b5SGregory Neil Shapiro 
82595b0945b5SGregory Neil Shapiro 	/* use a table? */
82602fb4f839SGregory Neil Shapiro 	if (SM_STRCASEEQ(name, "LogLevel"))
82615b0945b5SGregory Neil Shapiro 	{
82625b0945b5SGregory Neil Shapiro 		LogLevel = val;
82635b0945b5SGregory Neil Shapiro 		sm_dprintf("LogLevel=%d\n", val);
82645b0945b5SGregory Neil Shapiro 		return NULL;
82655b0945b5SGregory Neil Shapiro 	}
82665b0945b5SGregory Neil Shapiro # endif /* _FFR_SETANYOPT */
82675b0945b5SGregory Neil Shapiro 	*statp = EX_CONFIG;
82685b0945b5SGregory Neil Shapiro 	return NULL;
82695b0945b5SGregory Neil Shapiro }
82705b0945b5SGregory Neil Shapiro #endif
82715b0945b5SGregory Neil Shapiro 
82725b0945b5SGregory Neil Shapiro 
8273e92d3f3fSGregory Neil Shapiro #if SOCKETMAP
8274e92d3f3fSGregory Neil Shapiro 
8275e92d3f3fSGregory Neil Shapiro # if NETINET || NETINET6
8276e92d3f3fSGregory Neil Shapiro #  include <arpa/inet.h>
82775b0945b5SGregory Neil Shapiro # endif
8278e92d3f3fSGregory Neil Shapiro 
8279e92d3f3fSGregory Neil Shapiro # define socket_map_next map_stack[0]
8280e92d3f3fSGregory Neil Shapiro 
8281e92d3f3fSGregory Neil Shapiro /*
8282e92d3f3fSGregory Neil Shapiro **  SOCKET_MAP_OPEN -- open socket table
8283e92d3f3fSGregory Neil Shapiro */
8284e92d3f3fSGregory Neil Shapiro 
8285e92d3f3fSGregory Neil Shapiro bool
socket_map_open(map,mode)8286e92d3f3fSGregory Neil Shapiro socket_map_open(map, mode)
8287e92d3f3fSGregory Neil Shapiro 	MAP *map;
8288e92d3f3fSGregory Neil Shapiro 	int mode;
8289e92d3f3fSGregory Neil Shapiro {
8290e92d3f3fSGregory Neil Shapiro 	STAB *s;
8291e92d3f3fSGregory Neil Shapiro 	int sock = 0;
8292da7d7b9cSGregory Neil Shapiro 	int tmo;
8293e92d3f3fSGregory Neil Shapiro 	SOCKADDR_LEN_T addrlen = 0;
8294e92d3f3fSGregory Neil Shapiro 	int addrno = 0;
8295e92d3f3fSGregory Neil Shapiro 	int save_errno;
8296e92d3f3fSGregory Neil Shapiro 	char *p;
8297e92d3f3fSGregory Neil Shapiro 	char *colon;
8298e92d3f3fSGregory Neil Shapiro 	char *at;
8299e92d3f3fSGregory Neil Shapiro 	struct hostent *hp = NULL;
8300e92d3f3fSGregory Neil Shapiro 	SOCKADDR addr;
8301e92d3f3fSGregory Neil Shapiro 
8302e92d3f3fSGregory Neil Shapiro 	if (tTd(38, 2))
8303e92d3f3fSGregory Neil Shapiro 		sm_dprintf("socket_map_open(%s, %s, %d)\n",
8304e92d3f3fSGregory Neil Shapiro 			map->map_mname, map->map_file, mode);
8305e92d3f3fSGregory Neil Shapiro 
8306e92d3f3fSGregory Neil Shapiro 	mode &= O_ACCMODE;
8307e92d3f3fSGregory Neil Shapiro 
8308e92d3f3fSGregory Neil Shapiro 	/* sendmail doesn't have the ability to write to SOCKET (yet) */
8309e92d3f3fSGregory Neil Shapiro 	if (mode != O_RDONLY)
8310e92d3f3fSGregory Neil Shapiro 	{
8311e92d3f3fSGregory Neil Shapiro 		/* issue a pseudo-error message */
8312e92d3f3fSGregory Neil Shapiro 		errno = SM_EMAPCANTWRITE;
8313e92d3f3fSGregory Neil Shapiro 		return false;
8314e92d3f3fSGregory Neil Shapiro 	}
8315e92d3f3fSGregory Neil Shapiro 
8316e92d3f3fSGregory Neil Shapiro 	if (*map->map_file == '\0')
8317e92d3f3fSGregory Neil Shapiro 	{
8318e92d3f3fSGregory Neil Shapiro 		syserr("socket map \"%s\": empty or missing socket information",
8319e92d3f3fSGregory Neil Shapiro 			map->map_mname);
8320e92d3f3fSGregory Neil Shapiro 		return false;
8321e92d3f3fSGregory Neil Shapiro 	}
8322e92d3f3fSGregory Neil Shapiro 
8323e92d3f3fSGregory Neil Shapiro 	s = socket_map_findconn(map->map_file);
8324e92d3f3fSGregory Neil Shapiro 	if (s->s_socketmap != NULL)
8325e92d3f3fSGregory Neil Shapiro 	{
8326e92d3f3fSGregory Neil Shapiro 		/* Copy open connection */
8327e92d3f3fSGregory Neil Shapiro 		map->map_db1 = s->s_socketmap->map_db1;
8328e92d3f3fSGregory Neil Shapiro 
8329e92d3f3fSGregory Neil Shapiro 		/* Add this map as head of linked list */
8330e92d3f3fSGregory Neil Shapiro 		map->socket_map_next = s->s_socketmap;
8331e92d3f3fSGregory Neil Shapiro 		s->s_socketmap = map;
8332e92d3f3fSGregory Neil Shapiro 
8333e92d3f3fSGregory Neil Shapiro 		if (tTd(38, 2))
8334e92d3f3fSGregory Neil Shapiro 			sm_dprintf("using cached connection\n");
8335e92d3f3fSGregory Neil Shapiro 		return true;
8336e92d3f3fSGregory Neil Shapiro 	}
8337e92d3f3fSGregory Neil Shapiro 
8338e92d3f3fSGregory Neil Shapiro 	if (tTd(38, 2))
8339e92d3f3fSGregory Neil Shapiro 		sm_dprintf("opening new connection\n");
8340e92d3f3fSGregory Neil Shapiro 
8341e92d3f3fSGregory Neil Shapiro 	/* following code is ripped from milter.c */
8342e92d3f3fSGregory Neil Shapiro 	/* XXX It should be put in a library... */
8343e92d3f3fSGregory Neil Shapiro 
8344e92d3f3fSGregory Neil Shapiro 	/* protocol:filename or protocol:port@host */
8345d0cef73dSGregory Neil Shapiro 	memset(&addr, '\0', sizeof(addr));
8346e92d3f3fSGregory Neil Shapiro 	p = map->map_file;
8347e92d3f3fSGregory Neil Shapiro 	colon = strchr(p, ':');
8348e92d3f3fSGregory Neil Shapiro 	if (colon != NULL)
8349e92d3f3fSGregory Neil Shapiro 	{
8350e92d3f3fSGregory Neil Shapiro 		*colon = '\0';
8351e92d3f3fSGregory Neil Shapiro 
8352e92d3f3fSGregory Neil Shapiro 		if (*p == '\0')
8353e92d3f3fSGregory Neil Shapiro 		{
8354e92d3f3fSGregory Neil Shapiro # if NETUNIX
8355e92d3f3fSGregory Neil Shapiro 			/* default to AF_UNIX */
8356e92d3f3fSGregory Neil Shapiro 			addr.sa.sa_family = AF_UNIX;
8357e92d3f3fSGregory Neil Shapiro # else /* NETUNIX */
8358e92d3f3fSGregory Neil Shapiro #  if NETINET
8359e92d3f3fSGregory Neil Shapiro 			/* default to AF_INET */
8360e92d3f3fSGregory Neil Shapiro 			addr.sa.sa_family = AF_INET;
8361e92d3f3fSGregory Neil Shapiro #  else /* NETINET */
8362e92d3f3fSGregory Neil Shapiro #   if NETINET6
8363e92d3f3fSGregory Neil Shapiro 			/* default to AF_INET6 */
8364e92d3f3fSGregory Neil Shapiro 			addr.sa.sa_family = AF_INET6;
8365e92d3f3fSGregory Neil Shapiro #   else /* NETINET6 */
8366e92d3f3fSGregory Neil Shapiro 			/* no protocols available */
8367e92d3f3fSGregory Neil Shapiro 			syserr("socket map \"%s\": no valid socket protocols available",
8368e92d3f3fSGregory Neil Shapiro 			map->map_mname);
8369e92d3f3fSGregory Neil Shapiro 			return false;
8370e92d3f3fSGregory Neil Shapiro #   endif /* NETINET6 */
8371e92d3f3fSGregory Neil Shapiro #  endif /* NETINET */
8372e92d3f3fSGregory Neil Shapiro # endif /* NETUNIX */
8373e92d3f3fSGregory Neil Shapiro 		}
8374e92d3f3fSGregory Neil Shapiro # if NETUNIX
83752fb4f839SGregory Neil Shapiro 		else if (SM_STRCASEEQ(p, "unix") ||
83762fb4f839SGregory Neil Shapiro 			 SM_STRCASEEQ(p, "local"))
8377e92d3f3fSGregory Neil Shapiro 			addr.sa.sa_family = AF_UNIX;
8378e92d3f3fSGregory Neil Shapiro # endif /* NETUNIX */
8379e92d3f3fSGregory Neil Shapiro # if NETINET
83802fb4f839SGregory Neil Shapiro 		else if (SM_STRCASEEQ(p, "inet"))
8381e92d3f3fSGregory Neil Shapiro 			addr.sa.sa_family = AF_INET;
8382e92d3f3fSGregory Neil Shapiro # endif /* NETINET */
8383e92d3f3fSGregory Neil Shapiro # if NETINET6
83842fb4f839SGregory Neil Shapiro 		else if (SM_STRCASEEQ(p, "inet6"))
8385e92d3f3fSGregory Neil Shapiro 			addr.sa.sa_family = AF_INET6;
8386e92d3f3fSGregory Neil Shapiro # endif /* NETINET6 */
8387e92d3f3fSGregory Neil Shapiro 		else
8388e92d3f3fSGregory Neil Shapiro 		{
8389e92d3f3fSGregory Neil Shapiro # ifdef EPROTONOSUPPORT
8390e92d3f3fSGregory Neil Shapiro 			errno = EPROTONOSUPPORT;
83915b0945b5SGregory Neil Shapiro # else
8392e92d3f3fSGregory Neil Shapiro 			errno = EINVAL;
8393e92d3f3fSGregory Neil Shapiro # endif /* EPROTONOSUPPORT */
8394e92d3f3fSGregory Neil Shapiro 			syserr("socket map \"%s\": unknown socket type %s",
8395e92d3f3fSGregory Neil Shapiro 			       map->map_mname, p);
8396e92d3f3fSGregory Neil Shapiro 			return false;
8397e92d3f3fSGregory Neil Shapiro 		}
8398e92d3f3fSGregory Neil Shapiro 		*colon++ = ':';
8399e92d3f3fSGregory Neil Shapiro 	}
8400e92d3f3fSGregory Neil Shapiro 	else
8401e92d3f3fSGregory Neil Shapiro 	{
8402e92d3f3fSGregory Neil Shapiro 		colon = p;
8403e92d3f3fSGregory Neil Shapiro # if NETUNIX
8404e92d3f3fSGregory Neil Shapiro 		/* default to AF_UNIX */
8405e92d3f3fSGregory Neil Shapiro 		addr.sa.sa_family = AF_UNIX;
8406e92d3f3fSGregory Neil Shapiro # else /* NETUNIX */
8407e92d3f3fSGregory Neil Shapiro #  if NETINET
8408e92d3f3fSGregory Neil Shapiro 		/* default to AF_INET */
8409e92d3f3fSGregory Neil Shapiro 		addr.sa.sa_family = AF_INET;
8410e92d3f3fSGregory Neil Shapiro #  else /* NETINET */
8411e92d3f3fSGregory Neil Shapiro #   if NETINET6
8412e92d3f3fSGregory Neil Shapiro 		/* default to AF_INET6 */
8413e92d3f3fSGregory Neil Shapiro 		addr.sa.sa_family = AF_INET6;
8414e92d3f3fSGregory Neil Shapiro #   else /* NETINET6 */
8415e92d3f3fSGregory Neil Shapiro 		syserr("socket map \"%s\": unknown socket type %s",
8416e92d3f3fSGregory Neil Shapiro 		       map->map_mname, p);
8417e92d3f3fSGregory Neil Shapiro 		return false;
8418e92d3f3fSGregory Neil Shapiro #   endif /* NETINET6 */
8419e92d3f3fSGregory Neil Shapiro #  endif /* NETINET */
8420e92d3f3fSGregory Neil Shapiro # endif /* NETUNIX */
8421e92d3f3fSGregory Neil Shapiro 	}
8422e92d3f3fSGregory Neil Shapiro 
8423e92d3f3fSGregory Neil Shapiro # if NETUNIX
8424e92d3f3fSGregory Neil Shapiro 	if (addr.sa.sa_family == AF_UNIX)
8425e92d3f3fSGregory Neil Shapiro 	{
8426e92d3f3fSGregory Neil Shapiro 		long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_EXECOK;
8427e92d3f3fSGregory Neil Shapiro 
8428e92d3f3fSGregory Neil Shapiro 		at = colon;
8429d0cef73dSGregory Neil Shapiro 		if (strlen(colon) >= sizeof(addr.sunix.sun_path))
8430e92d3f3fSGregory Neil Shapiro 		{
8431e92d3f3fSGregory Neil Shapiro 			syserr("socket map \"%s\": local socket name %s too long",
8432e92d3f3fSGregory Neil Shapiro 			       map->map_mname, colon);
8433e92d3f3fSGregory Neil Shapiro 			return false;
8434e92d3f3fSGregory Neil Shapiro 		}
8435e92d3f3fSGregory Neil Shapiro 		errno = safefile(colon, RunAsUid, RunAsGid, RunAsUserName, sff,
8436e92d3f3fSGregory Neil Shapiro 				 S_IRUSR|S_IWUSR, NULL);
8437e92d3f3fSGregory Neil Shapiro 
8438e92d3f3fSGregory Neil Shapiro 		if (errno != 0)
8439e92d3f3fSGregory Neil Shapiro 		{
8440e92d3f3fSGregory Neil Shapiro 			/* if not safe, don't create */
8441e92d3f3fSGregory Neil Shapiro 				syserr("socket map \"%s\": local socket name %s unsafe",
8442e92d3f3fSGregory Neil Shapiro 			       map->map_mname, colon);
8443e92d3f3fSGregory Neil Shapiro 			return false;
8444e92d3f3fSGregory Neil Shapiro 		}
8445e92d3f3fSGregory Neil Shapiro 
8446e92d3f3fSGregory Neil Shapiro 		(void) sm_strlcpy(addr.sunix.sun_path, colon,
8447d0cef73dSGregory Neil Shapiro 			       sizeof(addr.sunix.sun_path));
8448e92d3f3fSGregory Neil Shapiro 		addrlen = sizeof(struct sockaddr_un);
8449e92d3f3fSGregory Neil Shapiro 	}
8450e92d3f3fSGregory Neil Shapiro 	else
8451e92d3f3fSGregory Neil Shapiro # endif /* NETUNIX */
8452e92d3f3fSGregory Neil Shapiro # if NETINET || NETINET6
8453e92d3f3fSGregory Neil Shapiro 	if (false
8454e92d3f3fSGregory Neil Shapiro #  if NETINET
8455e92d3f3fSGregory Neil Shapiro 		 || addr.sa.sa_family == AF_INET
84565b0945b5SGregory Neil Shapiro #  endif
8457e92d3f3fSGregory Neil Shapiro #  if NETINET6
8458e92d3f3fSGregory Neil Shapiro 		 || addr.sa.sa_family == AF_INET6
84595b0945b5SGregory Neil Shapiro #  endif
8460e92d3f3fSGregory Neil Shapiro 		 )
8461e92d3f3fSGregory Neil Shapiro 	{
8462e92d3f3fSGregory Neil Shapiro 		unsigned short port;
8463e92d3f3fSGregory Neil Shapiro 
8464e92d3f3fSGregory Neil Shapiro 		/* Parse port@host */
8465e92d3f3fSGregory Neil Shapiro 		at = strchr(colon, '@');
8466e92d3f3fSGregory Neil Shapiro 		if (at == NULL)
8467e92d3f3fSGregory Neil Shapiro 		{
8468e92d3f3fSGregory Neil Shapiro 			syserr("socket map \"%s\": bad address %s (expected port@host)",
8469e92d3f3fSGregory Neil Shapiro 				       map->map_mname, colon);
8470e92d3f3fSGregory Neil Shapiro 			return false;
8471e92d3f3fSGregory Neil Shapiro 		}
8472e92d3f3fSGregory Neil Shapiro 		*at = '\0';
8473e92d3f3fSGregory Neil Shapiro 		if (isascii(*colon) && isdigit(*colon))
8474e92d3f3fSGregory Neil Shapiro 			port = htons((unsigned short) atoi(colon));
8475e92d3f3fSGregory Neil Shapiro 		else
8476e92d3f3fSGregory Neil Shapiro 		{
8477e92d3f3fSGregory Neil Shapiro #  ifdef NO_GETSERVBYNAME
8478e92d3f3fSGregory Neil Shapiro 			syserr("socket map \"%s\": invalid port number %s",
8479e92d3f3fSGregory Neil Shapiro 				       map->map_mname, colon);
8480e92d3f3fSGregory Neil Shapiro 			return false;
8481e92d3f3fSGregory Neil Shapiro #  else /* NO_GETSERVBYNAME */
8482e92d3f3fSGregory Neil Shapiro 			register struct servent *sp;
8483e92d3f3fSGregory Neil Shapiro 
8484e92d3f3fSGregory Neil Shapiro 			sp = getservbyname(colon, "tcp");
8485e92d3f3fSGregory Neil Shapiro 			if (sp == NULL)
8486e92d3f3fSGregory Neil Shapiro 			{
8487e92d3f3fSGregory Neil Shapiro 				syserr("socket map \"%s\": unknown port name %s",
8488e92d3f3fSGregory Neil Shapiro 					       map->map_mname, colon);
8489e92d3f3fSGregory Neil Shapiro 				return false;
8490e92d3f3fSGregory Neil Shapiro 			}
8491e92d3f3fSGregory Neil Shapiro 			port = sp->s_port;
8492e92d3f3fSGregory Neil Shapiro #  endif /* NO_GETSERVBYNAME */
8493e92d3f3fSGregory Neil Shapiro 		}
8494e92d3f3fSGregory Neil Shapiro 		*at++ = '@';
8495e92d3f3fSGregory Neil Shapiro 		if (*at == '[')
8496e92d3f3fSGregory Neil Shapiro 		{
8497e92d3f3fSGregory Neil Shapiro 			char *end;
8498e92d3f3fSGregory Neil Shapiro 
8499e92d3f3fSGregory Neil Shapiro 			end = strchr(at, ']');
8500e92d3f3fSGregory Neil Shapiro 			if (end != NULL)
8501e92d3f3fSGregory Neil Shapiro 			{
8502e92d3f3fSGregory Neil Shapiro 				bool found = false;
8503e92d3f3fSGregory Neil Shapiro #  if NETINET
8504e92d3f3fSGregory Neil Shapiro 				unsigned long hid = INADDR_NONE;
85055b0945b5SGregory Neil Shapiro #  endif
8506e92d3f3fSGregory Neil Shapiro #  if NETINET6
8507e92d3f3fSGregory Neil Shapiro 				struct sockaddr_in6 hid6;
85085b0945b5SGregory Neil Shapiro #  endif
8509e92d3f3fSGregory Neil Shapiro 
8510e92d3f3fSGregory Neil Shapiro 				*end = '\0';
8511e92d3f3fSGregory Neil Shapiro #  if NETINET
8512e92d3f3fSGregory Neil Shapiro 				if (addr.sa.sa_family == AF_INET &&
8513e92d3f3fSGregory Neil Shapiro 				    (hid = inet_addr(&at[1])) != INADDR_NONE)
8514e92d3f3fSGregory Neil Shapiro 				{
8515e92d3f3fSGregory Neil Shapiro 					addr.sin.sin_addr.s_addr = hid;
8516e92d3f3fSGregory Neil Shapiro 					addr.sin.sin_port = port;
8517e92d3f3fSGregory Neil Shapiro 					found = true;
8518e92d3f3fSGregory Neil Shapiro 				}
8519e92d3f3fSGregory Neil Shapiro #  endif /* NETINET */
8520e92d3f3fSGregory Neil Shapiro #  if NETINET6
8521d0cef73dSGregory Neil Shapiro 				(void) memset(&hid6, '\0', sizeof(hid6));
8522e92d3f3fSGregory Neil Shapiro 				if (addr.sa.sa_family == AF_INET6 &&
8523e92d3f3fSGregory Neil Shapiro 				    anynet_pton(AF_INET6, &at[1],
8524e92d3f3fSGregory Neil Shapiro 						&hid6.sin6_addr) == 1)
8525e92d3f3fSGregory Neil Shapiro 				{
8526e92d3f3fSGregory Neil Shapiro 					addr.sin6.sin6_addr = hid6.sin6_addr;
8527e92d3f3fSGregory Neil Shapiro 					addr.sin6.sin6_port = port;
8528e92d3f3fSGregory Neil Shapiro 					found = true;
8529e92d3f3fSGregory Neil Shapiro 				}
8530e92d3f3fSGregory Neil Shapiro #  endif /* NETINET6 */
8531e92d3f3fSGregory Neil Shapiro 				*end = ']';
8532e92d3f3fSGregory Neil Shapiro 				if (!found)
8533e92d3f3fSGregory Neil Shapiro 				{
8534e92d3f3fSGregory Neil Shapiro 					syserr("socket map \"%s\": Invalid numeric domain spec \"%s\"",
8535e92d3f3fSGregory Neil Shapiro 					       map->map_mname, at);
8536e92d3f3fSGregory Neil Shapiro 					return false;
8537e92d3f3fSGregory Neil Shapiro 				}
8538e92d3f3fSGregory Neil Shapiro 			}
8539e92d3f3fSGregory Neil Shapiro 			else
8540e92d3f3fSGregory Neil Shapiro 			{
8541e92d3f3fSGregory Neil Shapiro 				syserr("socket map \"%s\": Invalid numeric domain spec \"%s\"",
8542e92d3f3fSGregory Neil Shapiro 				       map->map_mname, at);
8543e92d3f3fSGregory Neil Shapiro 				return false;
8544e92d3f3fSGregory Neil Shapiro 			}
8545e92d3f3fSGregory Neil Shapiro 		}
8546e92d3f3fSGregory Neil Shapiro 		else
8547e92d3f3fSGregory Neil Shapiro 		{
8548e92d3f3fSGregory Neil Shapiro 			hp = sm_gethostbyname(at, addr.sa.sa_family);
8549e92d3f3fSGregory Neil Shapiro 			if (hp == NULL)
8550e92d3f3fSGregory Neil Shapiro 			{
8551e92d3f3fSGregory Neil Shapiro 				syserr("socket map \"%s\": Unknown host name %s",
8552e92d3f3fSGregory Neil Shapiro 					map->map_mname, at);
8553e92d3f3fSGregory Neil Shapiro 				return false;
8554e92d3f3fSGregory Neil Shapiro 			}
8555e92d3f3fSGregory Neil Shapiro 			addr.sa.sa_family = hp->h_addrtype;
8556e92d3f3fSGregory Neil Shapiro 			switch (hp->h_addrtype)
8557e92d3f3fSGregory Neil Shapiro 			{
8558e92d3f3fSGregory Neil Shapiro #  if NETINET
8559e92d3f3fSGregory Neil Shapiro 			  case AF_INET:
8560e92d3f3fSGregory Neil Shapiro 				memmove(&addr.sin.sin_addr,
8561e92d3f3fSGregory Neil Shapiro 					hp->h_addr, INADDRSZ);
8562e92d3f3fSGregory Neil Shapiro 				addr.sin.sin_port = port;
8563e92d3f3fSGregory Neil Shapiro 				addrlen = sizeof(struct sockaddr_in);
8564e92d3f3fSGregory Neil Shapiro 				addrno = 1;
8565e92d3f3fSGregory Neil Shapiro 				break;
8566e92d3f3fSGregory Neil Shapiro #  endif /* NETINET */
8567e92d3f3fSGregory Neil Shapiro 
8568e92d3f3fSGregory Neil Shapiro #  if NETINET6
8569e92d3f3fSGregory Neil Shapiro 			  case AF_INET6:
8570e92d3f3fSGregory Neil Shapiro 				memmove(&addr.sin6.sin6_addr,
8571e92d3f3fSGregory Neil Shapiro 					hp->h_addr, IN6ADDRSZ);
8572e92d3f3fSGregory Neil Shapiro 				addr.sin6.sin6_port = port;
8573e92d3f3fSGregory Neil Shapiro 				addrlen = sizeof(struct sockaddr_in6);
8574e92d3f3fSGregory Neil Shapiro 				addrno = 1;
8575e92d3f3fSGregory Neil Shapiro 				break;
8576e92d3f3fSGregory Neil Shapiro #  endif /* NETINET6 */
8577e92d3f3fSGregory Neil Shapiro 
8578e92d3f3fSGregory Neil Shapiro 			  default:
8579e92d3f3fSGregory Neil Shapiro 				syserr("socket map \"%s\": Unknown protocol for %s (%d)",
8580e92d3f3fSGregory Neil Shapiro 					map->map_mname, at, hp->h_addrtype);
8581e92d3f3fSGregory Neil Shapiro #  if NETINET6
8582e92d3f3fSGregory Neil Shapiro 				freehostent(hp);
85835b0945b5SGregory Neil Shapiro #  endif
8584e92d3f3fSGregory Neil Shapiro 				return false;
8585e92d3f3fSGregory Neil Shapiro 			}
8586e92d3f3fSGregory Neil Shapiro 		}
8587e92d3f3fSGregory Neil Shapiro 	}
8588e92d3f3fSGregory Neil Shapiro 	else
8589e92d3f3fSGregory Neil Shapiro # endif /* NETINET || NETINET6 */
8590e92d3f3fSGregory Neil Shapiro 	{
8591e92d3f3fSGregory Neil Shapiro 		syserr("socket map \"%s\": unknown socket protocol",
8592e92d3f3fSGregory Neil Shapiro 			map->map_mname);
8593e92d3f3fSGregory Neil Shapiro 		return false;
8594e92d3f3fSGregory Neil Shapiro 	}
8595e92d3f3fSGregory Neil Shapiro 
8596e92d3f3fSGregory Neil Shapiro 	/* nope, actually connecting */
8597e92d3f3fSGregory Neil Shapiro 	for (;;)
8598e92d3f3fSGregory Neil Shapiro 	{
8599e92d3f3fSGregory Neil Shapiro 		sock = socket(addr.sa.sa_family, SOCK_STREAM, 0);
8600e92d3f3fSGregory Neil Shapiro 		if (sock < 0)
8601e92d3f3fSGregory Neil Shapiro 		{
8602e92d3f3fSGregory Neil Shapiro 			save_errno = errno;
8603e92d3f3fSGregory Neil Shapiro 			if (tTd(38, 5))
8604e92d3f3fSGregory Neil Shapiro 				sm_dprintf("socket map \"%s\": error creating socket: %s\n",
8605e92d3f3fSGregory Neil Shapiro 					   map->map_mname,
8606e92d3f3fSGregory Neil Shapiro 					   sm_errstring(save_errno));
8607e92d3f3fSGregory Neil Shapiro # if NETINET6
8608e92d3f3fSGregory Neil Shapiro 			if (hp != NULL)
8609e92d3f3fSGregory Neil Shapiro 				freehostent(hp);
8610e92d3f3fSGregory Neil Shapiro # endif /* NETINET6 */
8611e92d3f3fSGregory Neil Shapiro 			return false;
8612e92d3f3fSGregory Neil Shapiro 		}
8613e92d3f3fSGregory Neil Shapiro 
8614e92d3f3fSGregory Neil Shapiro 		if (connect(sock, (struct sockaddr *) &addr, addrlen) >= 0)
8615e92d3f3fSGregory Neil Shapiro 			break;
8616e92d3f3fSGregory Neil Shapiro 
8617e92d3f3fSGregory Neil Shapiro 		/* couldn't connect.... try next address */
8618e92d3f3fSGregory Neil Shapiro 		save_errno = errno;
8619e92d3f3fSGregory Neil Shapiro 		p = CurHostName;
8620e92d3f3fSGregory Neil Shapiro 		CurHostName = at;
8621e92d3f3fSGregory Neil Shapiro 		if (tTd(38, 5))
8622e92d3f3fSGregory Neil Shapiro 			sm_dprintf("socket_open (%s): open %s failed: %s\n",
8623e92d3f3fSGregory Neil Shapiro 				map->map_mname, at, sm_errstring(save_errno));
8624e92d3f3fSGregory Neil Shapiro 		CurHostName = p;
8625e92d3f3fSGregory Neil Shapiro 		(void) close(sock);
8626e92d3f3fSGregory Neil Shapiro 
8627e92d3f3fSGregory Neil Shapiro 		/* try next address */
8628e92d3f3fSGregory Neil Shapiro 		if (hp != NULL && hp->h_addr_list[addrno] != NULL)
8629e92d3f3fSGregory Neil Shapiro 		{
8630e92d3f3fSGregory Neil Shapiro 			switch (addr.sa.sa_family)
8631e92d3f3fSGregory Neil Shapiro 			{
8632e92d3f3fSGregory Neil Shapiro # if NETINET
8633e92d3f3fSGregory Neil Shapiro 			  case AF_INET:
8634e92d3f3fSGregory Neil Shapiro 				memmove(&addr.sin.sin_addr,
8635e92d3f3fSGregory Neil Shapiro 					hp->h_addr_list[addrno++],
8636e92d3f3fSGregory Neil Shapiro 					INADDRSZ);
8637e92d3f3fSGregory Neil Shapiro 				break;
8638e92d3f3fSGregory Neil Shapiro # endif /* NETINET */
8639e92d3f3fSGregory Neil Shapiro 
8640e92d3f3fSGregory Neil Shapiro # if NETINET6
8641e92d3f3fSGregory Neil Shapiro 			  case AF_INET6:
8642e92d3f3fSGregory Neil Shapiro 				memmove(&addr.sin6.sin6_addr,
8643e92d3f3fSGregory Neil Shapiro 					hp->h_addr_list[addrno++],
8644e92d3f3fSGregory Neil Shapiro 					IN6ADDRSZ);
8645e92d3f3fSGregory Neil Shapiro 				break;
8646e92d3f3fSGregory Neil Shapiro # endif /* NETINET6 */
8647e92d3f3fSGregory Neil Shapiro 
8648e92d3f3fSGregory Neil Shapiro 			  default:
8649e92d3f3fSGregory Neil Shapiro 				if (tTd(38, 5))
8650e92d3f3fSGregory Neil Shapiro 					sm_dprintf("socket map \"%s\": Unknown protocol for %s (%d)\n",
8651e92d3f3fSGregory Neil Shapiro 						   map->map_mname, at,
8652e92d3f3fSGregory Neil Shapiro 						   hp->h_addrtype);
8653e92d3f3fSGregory Neil Shapiro # if NETINET6
8654e92d3f3fSGregory Neil Shapiro 				freehostent(hp);
86555b0945b5SGregory Neil Shapiro # endif
8656e92d3f3fSGregory Neil Shapiro 				return false;
8657e92d3f3fSGregory Neil Shapiro 			}
8658e92d3f3fSGregory Neil Shapiro 			continue;
8659e92d3f3fSGregory Neil Shapiro 		}
8660e92d3f3fSGregory Neil Shapiro 		p = CurHostName;
8661e92d3f3fSGregory Neil Shapiro 		CurHostName = at;
8662e92d3f3fSGregory Neil Shapiro 		if (tTd(38, 5))
8663e92d3f3fSGregory Neil Shapiro 			sm_dprintf("socket map \"%s\": error connecting to socket map: %s\n",
8664e92d3f3fSGregory Neil Shapiro 				   map->map_mname, sm_errstring(save_errno));
8665e92d3f3fSGregory Neil Shapiro 		CurHostName = p;
8666e92d3f3fSGregory Neil Shapiro # if NETINET6
8667e92d3f3fSGregory Neil Shapiro 		if (hp != NULL)
8668e92d3f3fSGregory Neil Shapiro 			freehostent(hp);
86695b0945b5SGregory Neil Shapiro # endif
8670e92d3f3fSGregory Neil Shapiro 		return false;
8671e92d3f3fSGregory Neil Shapiro 	}
8672e92d3f3fSGregory Neil Shapiro # if NETINET6
8673e92d3f3fSGregory Neil Shapiro 	if (hp != NULL)
8674e92d3f3fSGregory Neil Shapiro 	{
8675e92d3f3fSGregory Neil Shapiro 		freehostent(hp);
8676e92d3f3fSGregory Neil Shapiro 		hp = NULL;
8677e92d3f3fSGregory Neil Shapiro 	}
8678e92d3f3fSGregory Neil Shapiro # endif /* NETINET6 */
8679e92d3f3fSGregory Neil Shapiro 	if ((map->map_db1 = (ARBPTR_T) sm_io_open(SmFtStdiofd,
8680e92d3f3fSGregory Neil Shapiro 						  SM_TIME_DEFAULT,
8681e92d3f3fSGregory Neil Shapiro 						  (void *) &sock,
8682e92d3f3fSGregory Neil Shapiro 						  SM_IO_RDWR,
8683e92d3f3fSGregory Neil Shapiro 						  NULL)) == NULL)
8684e92d3f3fSGregory Neil Shapiro 	{
8685e92d3f3fSGregory Neil Shapiro 		close(sock);
8686e92d3f3fSGregory Neil Shapiro 		if (tTd(38, 2))
8687e92d3f3fSGregory Neil Shapiro 		    sm_dprintf("socket_open (%s): failed to create stream: %s\n",
8688e92d3f3fSGregory Neil Shapiro 			       map->map_mname, sm_errstring(errno));
8689e92d3f3fSGregory Neil Shapiro 		return false;
8690e92d3f3fSGregory Neil Shapiro 	}
8691e92d3f3fSGregory Neil Shapiro 
8692da7d7b9cSGregory Neil Shapiro 	tmo = map->map_timeout;
8693da7d7b9cSGregory Neil Shapiro 	if (tmo == 0)
8694da7d7b9cSGregory Neil Shapiro 		tmo = 30000;	/* default: 30s */
8695da7d7b9cSGregory Neil Shapiro 	else
8696da7d7b9cSGregory Neil Shapiro 		tmo *= 1000;	/* s -> ms */
8697da7d7b9cSGregory Neil Shapiro 	sm_io_setinfo(map->map_db1, SM_IO_WHAT_TIMEOUT, &tmo);
8698da7d7b9cSGregory Neil Shapiro 
8699e92d3f3fSGregory Neil Shapiro 	/* Save connection for reuse */
8700e92d3f3fSGregory Neil Shapiro 	s->s_socketmap = map;
8701e92d3f3fSGregory Neil Shapiro 	return true;
8702e92d3f3fSGregory Neil Shapiro }
8703e92d3f3fSGregory Neil Shapiro 
8704e92d3f3fSGregory Neil Shapiro /*
8705e92d3f3fSGregory Neil Shapiro **  SOCKET_MAP_FINDCONN -- find a SOCKET connection to the server
8706e92d3f3fSGregory Neil Shapiro **
8707e92d3f3fSGregory Neil Shapiro **	Cache SOCKET connections based on the connection specifier
8708e92d3f3fSGregory Neil Shapiro **	and PID so we don't have multiple connections open to
8709e92d3f3fSGregory Neil Shapiro **	the same server for different maps.  Need a separate connection
8710e92d3f3fSGregory Neil Shapiro **	per PID since a parent process may close the map before the
8711e92d3f3fSGregory Neil Shapiro **	child is done with it.
8712e92d3f3fSGregory Neil Shapiro **
8713e92d3f3fSGregory Neil Shapiro **	Parameters:
8714e92d3f3fSGregory Neil Shapiro **		conn -- SOCKET map connection specifier
8715e92d3f3fSGregory Neil Shapiro **
8716e92d3f3fSGregory Neil Shapiro **	Returns:
8717e92d3f3fSGregory Neil Shapiro **		Symbol table entry for the SOCKET connection.
8718e92d3f3fSGregory Neil Shapiro */
8719e92d3f3fSGregory Neil Shapiro 
8720e92d3f3fSGregory Neil Shapiro static STAB *
socket_map_findconn(conn)8721e92d3f3fSGregory Neil Shapiro socket_map_findconn(conn)
8722e92d3f3fSGregory Neil Shapiro 	const char *conn;
8723e92d3f3fSGregory Neil Shapiro {
8724e92d3f3fSGregory Neil Shapiro 	char *nbuf;
8725e92d3f3fSGregory Neil Shapiro 	STAB *SM_NONVOLATILE s = NULL;
8726e92d3f3fSGregory Neil Shapiro 
8727e92d3f3fSGregory Neil Shapiro 	nbuf = sm_stringf_x("%s%c%d", conn, CONDELSE, (int) CurrentPid);
8728e92d3f3fSGregory Neil Shapiro 	SM_TRY
8729e92d3f3fSGregory Neil Shapiro 		s = stab(nbuf, ST_SOCKETMAP, ST_ENTER);
8730e92d3f3fSGregory Neil Shapiro 	SM_FINALLY
8731e92d3f3fSGregory Neil Shapiro 		sm_free(nbuf);
8732e92d3f3fSGregory Neil Shapiro 	SM_END_TRY
8733e92d3f3fSGregory Neil Shapiro 	return s;
8734e92d3f3fSGregory Neil Shapiro }
8735e92d3f3fSGregory Neil Shapiro 
8736e92d3f3fSGregory Neil Shapiro /*
8737e92d3f3fSGregory Neil Shapiro **  SOCKET_MAP_CLOSE -- close the socket
8738e92d3f3fSGregory Neil Shapiro */
8739e92d3f3fSGregory Neil Shapiro 
8740e92d3f3fSGregory Neil Shapiro void
socket_map_close(map)8741e92d3f3fSGregory Neil Shapiro socket_map_close(map)
8742e92d3f3fSGregory Neil Shapiro 	MAP *map;
8743e92d3f3fSGregory Neil Shapiro {
8744e92d3f3fSGregory Neil Shapiro 	STAB *s;
8745e92d3f3fSGregory Neil Shapiro 	MAP *smap;
8746e92d3f3fSGregory Neil Shapiro 
8747e92d3f3fSGregory Neil Shapiro 	if (tTd(38, 20))
8748e92d3f3fSGregory Neil Shapiro 		sm_dprintf("socket_map_close(%s), pid=%ld\n", map->map_file,
8749e92d3f3fSGregory Neil Shapiro 			(long) CurrentPid);
8750e92d3f3fSGregory Neil Shapiro 
8751e92d3f3fSGregory Neil Shapiro 	/* Check if already closed */
8752e92d3f3fSGregory Neil Shapiro 	if (map->map_db1 == NULL)
8753e92d3f3fSGregory Neil Shapiro 	{
8754e92d3f3fSGregory Neil Shapiro 		if (tTd(38, 20))
8755e92d3f3fSGregory Neil Shapiro 			sm_dprintf("socket_map_close(%s) already closed\n",
8756e92d3f3fSGregory Neil Shapiro 				map->map_file);
8757e92d3f3fSGregory Neil Shapiro 		return;
8758e92d3f3fSGregory Neil Shapiro 	}
8759e92d3f3fSGregory Neil Shapiro 	sm_io_close((SM_FILE_T *)map->map_db1, SM_TIME_DEFAULT);
8760e92d3f3fSGregory Neil Shapiro 
8761e92d3f3fSGregory Neil Shapiro 	/* Mark all the maps that share the connection as closed */
8762e92d3f3fSGregory Neil Shapiro 	s = socket_map_findconn(map->map_file);
8763e92d3f3fSGregory Neil Shapiro 	smap = s->s_socketmap;
8764e92d3f3fSGregory Neil Shapiro 	while (smap != NULL)
8765e92d3f3fSGregory Neil Shapiro 	{
8766e92d3f3fSGregory Neil Shapiro 		MAP *next;
8767e92d3f3fSGregory Neil Shapiro 
8768e92d3f3fSGregory Neil Shapiro 		if (tTd(38, 2) && smap != map)
8769e92d3f3fSGregory Neil Shapiro 			sm_dprintf("socket_map_close(%s): closed %s (shared SOCKET connection)\n",
8770e92d3f3fSGregory Neil Shapiro 				map->map_mname, smap->map_mname);
8771e92d3f3fSGregory Neil Shapiro 
8772e92d3f3fSGregory Neil Shapiro 		smap->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
8773e92d3f3fSGregory Neil Shapiro 		smap->map_db1 = NULL;
8774e92d3f3fSGregory Neil Shapiro 		next = smap->socket_map_next;
8775e92d3f3fSGregory Neil Shapiro 		smap->socket_map_next = NULL;
8776e92d3f3fSGregory Neil Shapiro 		smap = next;
8777e92d3f3fSGregory Neil Shapiro 	}
8778e92d3f3fSGregory Neil Shapiro 	s->s_socketmap = NULL;
8779e92d3f3fSGregory Neil Shapiro }
8780e92d3f3fSGregory Neil Shapiro 
8781e92d3f3fSGregory Neil Shapiro /*
8782e92d3f3fSGregory Neil Shapiro **  SOCKET_MAP_LOOKUP -- look up a datum in a SOCKET table
8783e92d3f3fSGregory Neil Shapiro */
8784e92d3f3fSGregory Neil Shapiro 
8785e92d3f3fSGregory Neil Shapiro char *
socket_map_lookup(map,name,av,statp)8786e92d3f3fSGregory Neil Shapiro socket_map_lookup(map, name, av, statp)
8787e92d3f3fSGregory Neil Shapiro 	MAP *map;
8788e92d3f3fSGregory Neil Shapiro 	char *name;
8789e92d3f3fSGregory Neil Shapiro 	char **av;
8790e92d3f3fSGregory Neil Shapiro 	int *statp;
8791e92d3f3fSGregory Neil Shapiro {
8792e92d3f3fSGregory Neil Shapiro 	unsigned int nettolen, replylen, recvlen;
87935b0945b5SGregory Neil Shapiro 	int ret;
879413d88268SGregory Neil Shapiro 	char *replybuf, *rval, *value, *status, *key;
8795e92d3f3fSGregory Neil Shapiro 	SM_FILE_T *f;
87962fb4f839SGregory Neil Shapiro 	char keybuf[MAXNAME + 1];	/* EAI:ok */
8797e92d3f3fSGregory Neil Shapiro 
8798e92d3f3fSGregory Neil Shapiro 	replybuf = NULL;
8799e92d3f3fSGregory Neil Shapiro 	rval = NULL;
8800e92d3f3fSGregory Neil Shapiro 	f = (SM_FILE_T *)map->map_db1;
8801e92d3f3fSGregory Neil Shapiro 	if (tTd(38, 20))
8802e92d3f3fSGregory Neil Shapiro 		sm_dprintf("socket_map_lookup(%s, %s) %s\n",
8803e92d3f3fSGregory Neil Shapiro 			map->map_mname, name, map->map_file);
8804e92d3f3fSGregory Neil Shapiro 
880513d88268SGregory Neil Shapiro 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
880613d88268SGregory Neil Shapiro 	{
880713d88268SGregory Neil Shapiro 		nettolen = strlen(name);
8808d0cef73dSGregory Neil Shapiro 		if (nettolen > sizeof(keybuf) - 1)
8809d0cef73dSGregory Neil Shapiro 			nettolen = sizeof(keybuf) - 1;
881013d88268SGregory Neil Shapiro 		memmove(keybuf, name, nettolen);
881113d88268SGregory Neil Shapiro 		keybuf[nettolen] = '\0';
88122fb4f839SGregory Neil Shapiro 		makelower_buf(keybuf, keybuf, sizeof(keybuf));
881313d88268SGregory Neil Shapiro 		key = keybuf;
881413d88268SGregory Neil Shapiro 	}
881513d88268SGregory Neil Shapiro 	else
881613d88268SGregory Neil Shapiro 		key = name;
881713d88268SGregory Neil Shapiro 
881813d88268SGregory Neil Shapiro 	nettolen = strlen(map->map_mname) + 1 + strlen(key);
8819e92d3f3fSGregory Neil Shapiro 	SM_ASSERT(nettolen > strlen(map->map_mname));
882013d88268SGregory Neil Shapiro 	SM_ASSERT(nettolen > strlen(key));
8821e92d3f3fSGregory Neil Shapiro 	if ((sm_io_fprintf(f, SM_TIME_DEFAULT, "%u:%s %s,",
882213d88268SGregory Neil Shapiro 			   nettolen, map->map_mname, key) == SM_IO_EOF) ||
8823e92d3f3fSGregory Neil Shapiro 	    (sm_io_flush(f, SM_TIME_DEFAULT) != 0) ||
8824e92d3f3fSGregory Neil Shapiro 	    (sm_io_error(f)))
8825e92d3f3fSGregory Neil Shapiro 	{
8826e92d3f3fSGregory Neil Shapiro 		syserr("451 4.3.0 socket_map_lookup(%s): failed to send lookup request",
8827e92d3f3fSGregory Neil Shapiro 			map->map_mname);
8828e92d3f3fSGregory Neil Shapiro 		*statp = EX_TEMPFAIL;
8829e92d3f3fSGregory Neil Shapiro 		goto errcl;
8830e92d3f3fSGregory Neil Shapiro 	}
8831e92d3f3fSGregory Neil Shapiro 
88325b0945b5SGregory Neil Shapiro 	if ((ret = sm_io_fscanf(f, SM_TIME_DEFAULT, "%9u", &replylen)) != 1)
8833e92d3f3fSGregory Neil Shapiro 	{
8834da7d7b9cSGregory Neil Shapiro 		if (errno == EAGAIN)
8835da7d7b9cSGregory Neil Shapiro 		{
8836da7d7b9cSGregory Neil Shapiro 			syserr("451 4.3.0 socket_map_lookup(%s): read timeout",
8837e92d3f3fSGregory Neil Shapiro 				map->map_mname);
8838da7d7b9cSGregory Neil Shapiro 		}
88395b0945b5SGregory Neil Shapiro 		else if (SM_IO_EOF == ret)
88405b0945b5SGregory Neil Shapiro 		{
88415b0945b5SGregory Neil Shapiro 			if (LogLevel > 9)
88425b0945b5SGregory Neil Shapiro 				sm_syslog(LOG_INFO, CurEnv->e_id,
88435b0945b5SGregory Neil Shapiro 					"socket_map_lookup(%s): EOF",
88445b0945b5SGregory Neil Shapiro 					map->map_mname);
88455b0945b5SGregory Neil Shapiro 		}
8846da7d7b9cSGregory Neil Shapiro 		else
8847da7d7b9cSGregory Neil Shapiro 		{
8848da7d7b9cSGregory Neil Shapiro 			syserr("451 4.3.0 socket_map_lookup(%s): failed to read length parameter of reply %d",
8849da7d7b9cSGregory Neil Shapiro 				map->map_mname, errno);
8850da7d7b9cSGregory Neil Shapiro 		}
8851e92d3f3fSGregory Neil Shapiro 		*statp = EX_TEMPFAIL;
8852e92d3f3fSGregory Neil Shapiro 		goto errcl;
8853e92d3f3fSGregory Neil Shapiro 	}
8854e92d3f3fSGregory Neil Shapiro 	if (replylen > SOCKETMAP_MAXL)
8855e92d3f3fSGregory Neil Shapiro 	{
8856e92d3f3fSGregory Neil Shapiro 		syserr("451 4.3.0 socket_map_lookup(%s): reply too long: %u",
8857e92d3f3fSGregory Neil Shapiro 			   map->map_mname, replylen);
8858e92d3f3fSGregory Neil Shapiro 		*statp = EX_TEMPFAIL;
8859e92d3f3fSGregory Neil Shapiro 		goto errcl;
8860e92d3f3fSGregory Neil Shapiro 	}
8861e92d3f3fSGregory Neil Shapiro 	if (sm_io_getc(f, SM_TIME_DEFAULT) != ':')
8862e92d3f3fSGregory Neil Shapiro 	{
8863e92d3f3fSGregory Neil Shapiro 		syserr("451 4.3.0 socket_map_lookup(%s): missing ':' in reply",
8864e92d3f3fSGregory Neil Shapiro 			map->map_mname);
8865e92d3f3fSGregory Neil Shapiro 		*statp = EX_TEMPFAIL;
8866e92d3f3fSGregory Neil Shapiro 		goto error;
8867e92d3f3fSGregory Neil Shapiro 	}
8868e92d3f3fSGregory Neil Shapiro 
8869e92d3f3fSGregory Neil Shapiro 	replybuf = (char *) sm_malloc(replylen + 1);
8870e92d3f3fSGregory Neil Shapiro 	if (replybuf == NULL)
8871e92d3f3fSGregory Neil Shapiro 	{
8872e92d3f3fSGregory Neil Shapiro 		syserr("451 4.3.0 socket_map_lookup(%s): can't allocate %u bytes",
8873e92d3f3fSGregory Neil Shapiro 			map->map_mname, replylen + 1);
8874e92d3f3fSGregory Neil Shapiro 		*statp = EX_OSERR;
8875e92d3f3fSGregory Neil Shapiro 		goto error;
8876e92d3f3fSGregory Neil Shapiro 	}
8877e92d3f3fSGregory Neil Shapiro 
8878e92d3f3fSGregory Neil Shapiro 	recvlen = sm_io_read(f, SM_TIME_DEFAULT, replybuf, replylen);
8879e92d3f3fSGregory Neil Shapiro 	if (recvlen < replylen)
8880e92d3f3fSGregory Neil Shapiro 	{
8881e92d3f3fSGregory Neil Shapiro 		syserr("451 4.3.0 socket_map_lookup(%s): received only %u of %u reply characters",
8882e92d3f3fSGregory Neil Shapiro 			   map->map_mname, recvlen, replylen);
8883e92d3f3fSGregory Neil Shapiro 		*statp = EX_TEMPFAIL;
8884e92d3f3fSGregory Neil Shapiro 		goto errcl;
8885e92d3f3fSGregory Neil Shapiro 	}
8886e92d3f3fSGregory Neil Shapiro 	if (sm_io_getc(f, SM_TIME_DEFAULT) != ',')
8887e92d3f3fSGregory Neil Shapiro 	{
8888e92d3f3fSGregory Neil Shapiro 		syserr("451 4.3.0 socket_map_lookup(%s): missing ',' in reply",
8889e92d3f3fSGregory Neil Shapiro 			map->map_mname);
8890e92d3f3fSGregory Neil Shapiro 		*statp = EX_TEMPFAIL;
8891e92d3f3fSGregory Neil Shapiro 		goto errcl;
8892e92d3f3fSGregory Neil Shapiro 	}
8893e92d3f3fSGregory Neil Shapiro 	status = replybuf;
8894e92d3f3fSGregory Neil Shapiro 	replybuf[recvlen] = '\0';
8895e92d3f3fSGregory Neil Shapiro 	value = strchr(replybuf, ' ');
8896e92d3f3fSGregory Neil Shapiro 	if (value != NULL)
8897e92d3f3fSGregory Neil Shapiro 	{
8898e92d3f3fSGregory Neil Shapiro 		*value = '\0';
8899e92d3f3fSGregory Neil Shapiro 		value++;
8900e92d3f3fSGregory Neil Shapiro 	}
8901e92d3f3fSGregory Neil Shapiro 	if (strcmp(status, "OK") == 0)
8902e92d3f3fSGregory Neil Shapiro 	{
8903e92d3f3fSGregory Neil Shapiro 		*statp = EX_OK;
8904e92d3f3fSGregory Neil Shapiro 
8905e92d3f3fSGregory Neil Shapiro 		/* collect the return value */
8906e92d3f3fSGregory Neil Shapiro 		if (bitset(MF_MATCHONLY, map->map_mflags))
890713d88268SGregory Neil Shapiro 			rval = map_rewrite(map, key, strlen(key), NULL);
8908e92d3f3fSGregory Neil Shapiro 		else
8909e92d3f3fSGregory Neil Shapiro 			rval = map_rewrite(map, value, strlen(value), av);
8910e92d3f3fSGregory Neil Shapiro 	}
8911e92d3f3fSGregory Neil Shapiro 	else if (strcmp(status, "NOTFOUND") == 0)
8912e92d3f3fSGregory Neil Shapiro 	{
8913e92d3f3fSGregory Neil Shapiro 		*statp = EX_NOTFOUND;
8914e92d3f3fSGregory Neil Shapiro 		if (tTd(38, 20))
8915e92d3f3fSGregory Neil Shapiro 			sm_dprintf("socket_map_lookup(%s): %s not found\n",
891613d88268SGregory Neil Shapiro 				map->map_mname, key);
8917e92d3f3fSGregory Neil Shapiro 	}
8918e92d3f3fSGregory Neil Shapiro 	else
8919e92d3f3fSGregory Neil Shapiro 	{
8920e92d3f3fSGregory Neil Shapiro 		if (tTd(38, 5))
8921e92d3f3fSGregory Neil Shapiro 			sm_dprintf("socket_map_lookup(%s, %s): server returned error: type=%s, reason=%s\n",
892213d88268SGregory Neil Shapiro 				map->map_mname, key, status,
8923e92d3f3fSGregory Neil Shapiro 				value ? value : "");
8924e92d3f3fSGregory Neil Shapiro 		if ((strcmp(status, "TEMP") == 0) ||
8925e92d3f3fSGregory Neil Shapiro 		    (strcmp(status, "TIMEOUT") == 0))
8926e92d3f3fSGregory Neil Shapiro 			*statp = EX_TEMPFAIL;
8927e92d3f3fSGregory Neil Shapiro 		else if(strcmp(status, "PERM") == 0)
8928e92d3f3fSGregory Neil Shapiro 			*statp = EX_UNAVAILABLE;
8929e92d3f3fSGregory Neil Shapiro 		else
8930e92d3f3fSGregory Neil Shapiro 			*statp = EX_PROTOCOL;
8931e92d3f3fSGregory Neil Shapiro 	}
8932e92d3f3fSGregory Neil Shapiro 
89332fb4f839SGregory Neil Shapiro 	SM_FREE(replybuf);
8934e92d3f3fSGregory Neil Shapiro 	return rval;
8935e92d3f3fSGregory Neil Shapiro 
8936e92d3f3fSGregory Neil Shapiro   errcl:
8937e92d3f3fSGregory Neil Shapiro 	socket_map_close(map);
8938e92d3f3fSGregory Neil Shapiro   error:
89392fb4f839SGregory Neil Shapiro 	SM_FREE(replybuf);
8940e92d3f3fSGregory Neil Shapiro 	return rval;
8941e92d3f3fSGregory Neil Shapiro }
8942e92d3f3fSGregory Neil Shapiro #endif /* SOCKETMAP */
8943