xref: /illumos-gate/usr/src/cmd/sendmail/src/map.c (revision 3ee0e492)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * Copyright (c) 1998-2005 Sendmail, Inc. and its suppliers.
37c478bd9Sstevel@tonic-gate  *	All rights reserved.
47c478bd9Sstevel@tonic-gate  * Copyright (c) 1992, 1995-1997 Eric P. Allman.  All rights reserved.
57c478bd9Sstevel@tonic-gate  * Copyright (c) 1992, 1993
67c478bd9Sstevel@tonic-gate  *	The Regents of the University of California.  All rights reserved.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * By using this file, you agree to the terms and conditions set
97c478bd9Sstevel@tonic-gate  * forth in the LICENSE file which can be found at the top level of
107c478bd9Sstevel@tonic-gate  * the sendmail distribution.
117c478bd9Sstevel@tonic-gate  *
127c478bd9Sstevel@tonic-gate  */
137c478bd9Sstevel@tonic-gate 
147c478bd9Sstevel@tonic-gate /*
157c478bd9Sstevel@tonic-gate  * Copyright 1996-2004 Sun Microsystems, Inc.  All rights reserved.
167c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
177c478bd9Sstevel@tonic-gate  */
187c478bd9Sstevel@tonic-gate 
197c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
207c478bd9Sstevel@tonic-gate 
217c478bd9Sstevel@tonic-gate #include <sendmail.h>
227c478bd9Sstevel@tonic-gate 
23*3ee0e492Sjbeck SM_RCSID("@(#)$Id: map.c,v 8.672 2006/04/18 01:26:41 ca Exp $")
247c478bd9Sstevel@tonic-gate SM_IDSTR(i2, "%W% (Sun) %G%")
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #if LDAPMAP
277c478bd9Sstevel@tonic-gate # include <sm/ldap.h>
287c478bd9Sstevel@tonic-gate #endif /* LDAPMAP */
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #if NDBM
317c478bd9Sstevel@tonic-gate # include <ndbm.h>
327c478bd9Sstevel@tonic-gate # ifdef R_FIRST
337c478bd9Sstevel@tonic-gate   ERROR README:	You are running the Berkeley DB version of ndbm.h.  See
347c478bd9Sstevel@tonic-gate   ERROR README:	the README file about tweaking Berkeley DB so it can
357c478bd9Sstevel@tonic-gate   ERROR README:	coexist with NDBM, or delete -DNDBM from the Makefile
367c478bd9Sstevel@tonic-gate   ERROR README: and use -DNEWDB instead.
377c478bd9Sstevel@tonic-gate # endif /* R_FIRST */
387c478bd9Sstevel@tonic-gate #endif /* NDBM */
397c478bd9Sstevel@tonic-gate #if NEWDB
407c478bd9Sstevel@tonic-gate # include "sm/bdb.h"
417c478bd9Sstevel@tonic-gate #endif /* NEWDB */
427c478bd9Sstevel@tonic-gate #if NIS
437c478bd9Sstevel@tonic-gate   struct dom_binding;	/* forward reference needed on IRIX */
447c478bd9Sstevel@tonic-gate # include <rpcsvc/ypclnt.h>
457c478bd9Sstevel@tonic-gate # if NDBM
467c478bd9Sstevel@tonic-gate #  define NDBM_YP_COMPAT	/* create YP-compatible NDBM files */
477c478bd9Sstevel@tonic-gate # endif /* NDBM */
487c478bd9Sstevel@tonic-gate #endif /* NIS */
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate #if NEWDB
517c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2
527c478bd9Sstevel@tonic-gate static bool	db_map_open __P((MAP *, int, char *, DBTYPE, const void *));
537c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */
547c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR == 2
557c478bd9Sstevel@tonic-gate static bool	db_map_open __P((MAP *, int, char *, DBTYPE, DB_INFO *));
567c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR == 2 */
577c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR > 2
587c478bd9Sstevel@tonic-gate static bool	db_map_open __P((MAP *, int, char *, DBTYPE, void **));
597c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR > 2 */
607c478bd9Sstevel@tonic-gate #endif /* NEWDB */
617c478bd9Sstevel@tonic-gate static bool	extract_canonname __P((char *, char *, char *, char[], int));
627c478bd9Sstevel@tonic-gate static void	map_close __P((STAB *, int));
637c478bd9Sstevel@tonic-gate static void	map_init __P((STAB *, int));
647c478bd9Sstevel@tonic-gate #ifdef LDAPMAP
657c478bd9Sstevel@tonic-gate static STAB *	ldapmap_findconn __P((SM_LDAP_STRUCT *));
667c478bd9Sstevel@tonic-gate #endif /* LDAPMAP */
677c478bd9Sstevel@tonic-gate #if NISPLUS
687c478bd9Sstevel@tonic-gate static bool	nisplus_getcanonname __P((char *, int, int *));
697c478bd9Sstevel@tonic-gate #endif /* NISPLUS */
707c478bd9Sstevel@tonic-gate #if NIS
717c478bd9Sstevel@tonic-gate static bool	nis_getcanonname __P((char *, int, int *));
727c478bd9Sstevel@tonic-gate #endif /* NIS */
737c478bd9Sstevel@tonic-gate #if NETINFO
747c478bd9Sstevel@tonic-gate static bool	ni_getcanonname __P((char *, int, int *));
757c478bd9Sstevel@tonic-gate #endif /* NETINFO */
767c478bd9Sstevel@tonic-gate static bool	text_getcanonname __P((char *, int, int *));
777c478bd9Sstevel@tonic-gate #if SOCKETMAP
787c478bd9Sstevel@tonic-gate static STAB	*socket_map_findconn __P((const char*));
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate /* XXX arbitrary limit for sanity */
817c478bd9Sstevel@tonic-gate # define SOCKETMAP_MAXL 1000000
827c478bd9Sstevel@tonic-gate #endif /* SOCKETMAP */
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate /* default error message for trying to open a map in write mode */
857c478bd9Sstevel@tonic-gate #ifdef ENOSYS
867c478bd9Sstevel@tonic-gate # define SM_EMAPCANTWRITE	ENOSYS
877c478bd9Sstevel@tonic-gate #else /* ENOSYS */
887c478bd9Sstevel@tonic-gate # ifdef EFTYPE
897c478bd9Sstevel@tonic-gate #  define SM_EMAPCANTWRITE	EFTYPE
907c478bd9Sstevel@tonic-gate # else /* EFTYPE */
917c478bd9Sstevel@tonic-gate #  define SM_EMAPCANTWRITE	ENXIO
927c478bd9Sstevel@tonic-gate # endif /* EFTYPE */
937c478bd9Sstevel@tonic-gate #endif /* ENOSYS */
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate /*
967c478bd9Sstevel@tonic-gate **  MAP.C -- implementations for various map classes.
977c478bd9Sstevel@tonic-gate **
987c478bd9Sstevel@tonic-gate **	Each map class implements a series of functions:
997c478bd9Sstevel@tonic-gate **
1007c478bd9Sstevel@tonic-gate **	bool map_parse(MAP *map, char *args)
1017c478bd9Sstevel@tonic-gate **		Parse the arguments from the config file.  Return true
1027c478bd9Sstevel@tonic-gate **		if they were ok, false otherwise.  Fill in map with the
1037c478bd9Sstevel@tonic-gate **		values.
1047c478bd9Sstevel@tonic-gate **
1057c478bd9Sstevel@tonic-gate **	char *map_lookup(MAP *map, char *key, char **args, int *pstat)
1067c478bd9Sstevel@tonic-gate **		Look up the key in the given map.  If found, do any
1077c478bd9Sstevel@tonic-gate **		rewriting the map wants (including "args" if desired)
1087c478bd9Sstevel@tonic-gate **		and return the value.  Set *pstat to the appropriate status
1097c478bd9Sstevel@tonic-gate **		on error and return NULL.  Args will be NULL if called
1107c478bd9Sstevel@tonic-gate **		from the alias routines, although this should probably
1117c478bd9Sstevel@tonic-gate **		not be relied upon.  It is suggested you call map_rewrite
1127c478bd9Sstevel@tonic-gate **		to return the results -- it takes care of null termination
1137c478bd9Sstevel@tonic-gate **		and uses a dynamically expanded buffer as needed.
1147c478bd9Sstevel@tonic-gate **
1157c478bd9Sstevel@tonic-gate **	void map_store(MAP *map, char *key, char *value)
1167c478bd9Sstevel@tonic-gate **		Store the key:value pair in the map.
1177c478bd9Sstevel@tonic-gate **
1187c478bd9Sstevel@tonic-gate **	bool map_open(MAP *map, int mode)
1197c478bd9Sstevel@tonic-gate **		Open the map for the indicated mode.  Mode should
1207c478bd9Sstevel@tonic-gate **		be either O_RDONLY or O_RDWR.  Return true if it
1217c478bd9Sstevel@tonic-gate **		was opened successfully, false otherwise.  If the open
1227c478bd9Sstevel@tonic-gate **		failed and the MF_OPTIONAL flag is not set, it should
1237c478bd9Sstevel@tonic-gate **		also print an error.  If the MF_ALIAS bit is set
1247c478bd9Sstevel@tonic-gate **		and this map class understands the @:@ convention, it
1257c478bd9Sstevel@tonic-gate **		should call aliaswait() before returning.
1267c478bd9Sstevel@tonic-gate **
1277c478bd9Sstevel@tonic-gate **	void map_close(MAP *map)
1287c478bd9Sstevel@tonic-gate **		Close the map.
1297c478bd9Sstevel@tonic-gate **
1307c478bd9Sstevel@tonic-gate **	This file also includes the implementation for getcanonname.
1317c478bd9Sstevel@tonic-gate **	It is currently implemented in a pretty ad-hoc manner; it ought
1327c478bd9Sstevel@tonic-gate **	to be more properly integrated into the map structure.
1337c478bd9Sstevel@tonic-gate */
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate #if O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL
1367c478bd9Sstevel@tonic-gate # define LOCK_ON_OPEN	1	/* we can open/create a locked file */
1377c478bd9Sstevel@tonic-gate #else /* O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL */
1387c478bd9Sstevel@tonic-gate # define LOCK_ON_OPEN	0	/* no such luck -- bend over backwards */
1397c478bd9Sstevel@tonic-gate #endif /* O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL */
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate /*
1427c478bd9Sstevel@tonic-gate **  MAP_PARSEARGS -- parse config line arguments for database lookup
1437c478bd9Sstevel@tonic-gate **
1447c478bd9Sstevel@tonic-gate **	This is a generic version of the map_parse method.
1457c478bd9Sstevel@tonic-gate **
1467c478bd9Sstevel@tonic-gate **	Parameters:
1477c478bd9Sstevel@tonic-gate **		map -- the map being initialized.
1487c478bd9Sstevel@tonic-gate **		ap -- a pointer to the args on the config line.
1497c478bd9Sstevel@tonic-gate **
1507c478bd9Sstevel@tonic-gate **	Returns:
1517c478bd9Sstevel@tonic-gate **		true -- if everything parsed OK.
1527c478bd9Sstevel@tonic-gate **		false -- otherwise.
1537c478bd9Sstevel@tonic-gate **
1547c478bd9Sstevel@tonic-gate **	Side Effects:
1557c478bd9Sstevel@tonic-gate **		null terminates the filename; stores it in map
1567c478bd9Sstevel@tonic-gate */
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate bool
1597c478bd9Sstevel@tonic-gate map_parseargs(map, ap)
1607c478bd9Sstevel@tonic-gate 	MAP *map;
1617c478bd9Sstevel@tonic-gate 	char *ap;
1627c478bd9Sstevel@tonic-gate {
1637c478bd9Sstevel@tonic-gate 	register char *p = ap;
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate 	/*
1667c478bd9Sstevel@tonic-gate 	**  There is no check whether there is really an argument,
1677c478bd9Sstevel@tonic-gate 	**  but that's not important enough to warrant extra code.
1687c478bd9Sstevel@tonic-gate 	*/
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate 	map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL;
1717c478bd9Sstevel@tonic-gate 	map->map_spacesub = SpaceSub;	/* default value */
1727c478bd9Sstevel@tonic-gate 	for (;;)
1737c478bd9Sstevel@tonic-gate 	{
1747c478bd9Sstevel@tonic-gate 		while (isascii(*p) && isspace(*p))
1757c478bd9Sstevel@tonic-gate 			p++;
1767c478bd9Sstevel@tonic-gate 		if (*p != '-')
1777c478bd9Sstevel@tonic-gate 			break;
1787c478bd9Sstevel@tonic-gate 		switch (*++p)
1797c478bd9Sstevel@tonic-gate 		{
1807c478bd9Sstevel@tonic-gate 		  case 'N':
1817c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_INCLNULL;
1827c478bd9Sstevel@tonic-gate 			map->map_mflags &= ~MF_TRY0NULL;
1837c478bd9Sstevel@tonic-gate 			break;
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate 		  case 'O':
1867c478bd9Sstevel@tonic-gate 			map->map_mflags &= ~MF_TRY1NULL;
1877c478bd9Sstevel@tonic-gate 			break;
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate 		  case 'o':
1907c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_OPTIONAL;
1917c478bd9Sstevel@tonic-gate 			break;
1927c478bd9Sstevel@tonic-gate 
1937c478bd9Sstevel@tonic-gate 		  case 'f':
1947c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_NOFOLDCASE;
1957c478bd9Sstevel@tonic-gate 			break;
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 		  case 'm':
1987c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_MATCHONLY;
1997c478bd9Sstevel@tonic-gate 			break;
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate 		  case 'A':
2027c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_APPEND;
2037c478bd9Sstevel@tonic-gate 			break;
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate 		  case 'q':
2067c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_KEEPQUOTES;
2077c478bd9Sstevel@tonic-gate 			break;
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate 		  case 'a':
2107c478bd9Sstevel@tonic-gate 			map->map_app = ++p;
2117c478bd9Sstevel@tonic-gate 			break;
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate 		  case 'T':
2147c478bd9Sstevel@tonic-gate 			map->map_tapp = ++p;
2157c478bd9Sstevel@tonic-gate 			break;
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate 		  case 'k':
2187c478bd9Sstevel@tonic-gate 			while (isascii(*++p) && isspace(*p))
2197c478bd9Sstevel@tonic-gate 				continue;
2207c478bd9Sstevel@tonic-gate 			map->map_keycolnm = p;
2217c478bd9Sstevel@tonic-gate 			break;
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate 		  case 'v':
2247c478bd9Sstevel@tonic-gate 			while (isascii(*++p) && isspace(*p))
2257c478bd9Sstevel@tonic-gate 				continue;
2267c478bd9Sstevel@tonic-gate 			map->map_valcolnm = p;
2277c478bd9Sstevel@tonic-gate 			break;
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate 		  case 'z':
2307c478bd9Sstevel@tonic-gate 			if (*++p != '\\')
2317c478bd9Sstevel@tonic-gate 				map->map_coldelim = *p;
2327c478bd9Sstevel@tonic-gate 			else
2337c478bd9Sstevel@tonic-gate 			{
2347c478bd9Sstevel@tonic-gate 				switch (*++p)
2357c478bd9Sstevel@tonic-gate 				{
2367c478bd9Sstevel@tonic-gate 				  case 'n':
2377c478bd9Sstevel@tonic-gate 					map->map_coldelim = '\n';
2387c478bd9Sstevel@tonic-gate 					break;
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate 				  case 't':
2417c478bd9Sstevel@tonic-gate 					map->map_coldelim = '\t';
2427c478bd9Sstevel@tonic-gate 					break;
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate 				  default:
2457c478bd9Sstevel@tonic-gate 					map->map_coldelim = '\\';
2467c478bd9Sstevel@tonic-gate 				}
2477c478bd9Sstevel@tonic-gate 			}
2487c478bd9Sstevel@tonic-gate 			break;
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate 		  case 't':
2517c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_NODEFER;
2527c478bd9Sstevel@tonic-gate 			break;
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate 		  case 'S':
2567c478bd9Sstevel@tonic-gate 			map->map_spacesub = *++p;
2577c478bd9Sstevel@tonic-gate 			break;
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate 		  case 'D':
2607c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_DEFER;
2617c478bd9Sstevel@tonic-gate 			break;
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate 		  default:
2647c478bd9Sstevel@tonic-gate 			syserr("Illegal option %c map %s", *p, map->map_mname);
2657c478bd9Sstevel@tonic-gate 			break;
2667c478bd9Sstevel@tonic-gate 		}
2677c478bd9Sstevel@tonic-gate 		while (*p != '\0' && !(isascii(*p) && isspace(*p)))
2687c478bd9Sstevel@tonic-gate 			p++;
2697c478bd9Sstevel@tonic-gate 		if (*p != '\0')
2707c478bd9Sstevel@tonic-gate 			*p++ = '\0';
2717c478bd9Sstevel@tonic-gate 	}
2727c478bd9Sstevel@tonic-gate 	if (map->map_app != NULL)
2737c478bd9Sstevel@tonic-gate 		map->map_app = newstr(map->map_app);
2747c478bd9Sstevel@tonic-gate 	if (map->map_tapp != NULL)
2757c478bd9Sstevel@tonic-gate 		map->map_tapp = newstr(map->map_tapp);
2767c478bd9Sstevel@tonic-gate 	if (map->map_keycolnm != NULL)
2777c478bd9Sstevel@tonic-gate 		map->map_keycolnm = newstr(map->map_keycolnm);
2787c478bd9Sstevel@tonic-gate 	if (map->map_valcolnm != NULL)
2797c478bd9Sstevel@tonic-gate 		map->map_valcolnm = newstr(map->map_valcolnm);
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate 	if (*p != '\0')
2827c478bd9Sstevel@tonic-gate 	{
2837c478bd9Sstevel@tonic-gate 		map->map_file = p;
2847c478bd9Sstevel@tonic-gate 		while (*p != '\0' && !(isascii(*p) && isspace(*p)))
2857c478bd9Sstevel@tonic-gate 			p++;
2867c478bd9Sstevel@tonic-gate 		if (*p != '\0')
2877c478bd9Sstevel@tonic-gate 			*p++ = '\0';
2887c478bd9Sstevel@tonic-gate 		map->map_file = newstr(map->map_file);
2897c478bd9Sstevel@tonic-gate 	}
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate 	while (*p != '\0' && isascii(*p) && isspace(*p))
2927c478bd9Sstevel@tonic-gate 		p++;
2937c478bd9Sstevel@tonic-gate 	if (*p != '\0')
2947c478bd9Sstevel@tonic-gate 		map->map_rebuild = newstr(p);
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate 	if (map->map_file == NULL &&
2977c478bd9Sstevel@tonic-gate 	    !bitset(MCF_OPTFILE, map->map_class->map_cflags))
2987c478bd9Sstevel@tonic-gate 	{
2997c478bd9Sstevel@tonic-gate 		syserr("No file name for %s map %s",
3007c478bd9Sstevel@tonic-gate 			map->map_class->map_cname, map->map_mname);
3017c478bd9Sstevel@tonic-gate 		return false;
3027c478bd9Sstevel@tonic-gate 	}
3037c478bd9Sstevel@tonic-gate 	return true;
3047c478bd9Sstevel@tonic-gate }
3057c478bd9Sstevel@tonic-gate /*
3067c478bd9Sstevel@tonic-gate **  MAP_REWRITE -- rewrite a database key, interpolating %n indications.
3077c478bd9Sstevel@tonic-gate **
3087c478bd9Sstevel@tonic-gate **	It also adds the map_app string.  It can be used as a utility
3097c478bd9Sstevel@tonic-gate **	in the map_lookup method.
3107c478bd9Sstevel@tonic-gate **
3117c478bd9Sstevel@tonic-gate **	Parameters:
3127c478bd9Sstevel@tonic-gate **		map -- the map that causes this.
3137c478bd9Sstevel@tonic-gate **		s -- the string to rewrite, NOT necessarily null terminated.
3147c478bd9Sstevel@tonic-gate **		slen -- the length of s.
3157c478bd9Sstevel@tonic-gate **		av -- arguments to interpolate into buf.
3167c478bd9Sstevel@tonic-gate **
3177c478bd9Sstevel@tonic-gate **	Returns:
3187c478bd9Sstevel@tonic-gate **		Pointer to rewritten result.  This is static data that
3197c478bd9Sstevel@tonic-gate **		should be copied if it is to be saved!
3207c478bd9Sstevel@tonic-gate */
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate char *
3237c478bd9Sstevel@tonic-gate map_rewrite(map, s, slen, av)
3247c478bd9Sstevel@tonic-gate 	register MAP *map;
3257c478bd9Sstevel@tonic-gate 	register const char *s;
3267c478bd9Sstevel@tonic-gate 	size_t slen;
3277c478bd9Sstevel@tonic-gate 	char **av;
3287c478bd9Sstevel@tonic-gate {
3297c478bd9Sstevel@tonic-gate 	register char *bp;
3307c478bd9Sstevel@tonic-gate 	register char c;
3317c478bd9Sstevel@tonic-gate 	char **avp;
3327c478bd9Sstevel@tonic-gate 	register char *ap;
3337c478bd9Sstevel@tonic-gate 	size_t l;
3347c478bd9Sstevel@tonic-gate 	size_t len;
3357c478bd9Sstevel@tonic-gate 	static size_t buflen = 0;
3367c478bd9Sstevel@tonic-gate 	static char *buf = NULL;
3377c478bd9Sstevel@tonic-gate 
3387c478bd9Sstevel@tonic-gate 	if (tTd(39, 1))
3397c478bd9Sstevel@tonic-gate 	{
3407c478bd9Sstevel@tonic-gate 		sm_dprintf("map_rewrite(%.*s), av =", (int) slen, s);
3417c478bd9Sstevel@tonic-gate 		if (av == NULL)
3427c478bd9Sstevel@tonic-gate 			sm_dprintf(" (nullv)");
3437c478bd9Sstevel@tonic-gate 		else
3447c478bd9Sstevel@tonic-gate 		{
3457c478bd9Sstevel@tonic-gate 			for (avp = av; *avp != NULL; avp++)
3467c478bd9Sstevel@tonic-gate 				sm_dprintf("\n\t%s", *avp);
3477c478bd9Sstevel@tonic-gate 		}
3487c478bd9Sstevel@tonic-gate 		sm_dprintf("\n");
3497c478bd9Sstevel@tonic-gate 	}
3507c478bd9Sstevel@tonic-gate 
3517c478bd9Sstevel@tonic-gate 	/* count expected size of output (can safely overestimate) */
3527c478bd9Sstevel@tonic-gate 	l = len = slen;
3537c478bd9Sstevel@tonic-gate 	if (av != NULL)
3547c478bd9Sstevel@tonic-gate 	{
3557c478bd9Sstevel@tonic-gate 		const char *sp = s;
3567c478bd9Sstevel@tonic-gate 
3577c478bd9Sstevel@tonic-gate 		while (l-- > 0 && (c = *sp++) != '\0')
3587c478bd9Sstevel@tonic-gate 		{
3597c478bd9Sstevel@tonic-gate 			if (c != '%')
3607c478bd9Sstevel@tonic-gate 				continue;
3617c478bd9Sstevel@tonic-gate 			if (l-- <= 0)
3627c478bd9Sstevel@tonic-gate 				break;
3637c478bd9Sstevel@tonic-gate 			c = *sp++;
3647c478bd9Sstevel@tonic-gate 			if (!(isascii(c) && isdigit(c)))
3657c478bd9Sstevel@tonic-gate 				continue;
3667c478bd9Sstevel@tonic-gate 			for (avp = av; --c >= '0' && *avp != NULL; avp++)
3677c478bd9Sstevel@tonic-gate 				continue;
3687c478bd9Sstevel@tonic-gate 			if (*avp == NULL)
3697c478bd9Sstevel@tonic-gate 				continue;
3707c478bd9Sstevel@tonic-gate 			len += strlen(*avp);
3717c478bd9Sstevel@tonic-gate 		}
3727c478bd9Sstevel@tonic-gate 	}
3737c478bd9Sstevel@tonic-gate 	if (map->map_app != NULL)
3747c478bd9Sstevel@tonic-gate 		len += strlen(map->map_app);
3757c478bd9Sstevel@tonic-gate 	if (buflen < ++len)
3767c478bd9Sstevel@tonic-gate 	{
3777c478bd9Sstevel@tonic-gate 		/* need to malloc additional space */
3787c478bd9Sstevel@tonic-gate 		buflen = len;
3797c478bd9Sstevel@tonic-gate 		if (buf != NULL)
3807c478bd9Sstevel@tonic-gate 			sm_free(buf);
3817c478bd9Sstevel@tonic-gate 		buf = sm_pmalloc_x(buflen);
3827c478bd9Sstevel@tonic-gate 	}
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate 	bp = buf;
3857c478bd9Sstevel@tonic-gate 	if (av == NULL)
3867c478bd9Sstevel@tonic-gate 	{
3877c478bd9Sstevel@tonic-gate 		memmove(bp, s, slen);
3887c478bd9Sstevel@tonic-gate 		bp += slen;
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate 		/* assert(len > slen); */
3917c478bd9Sstevel@tonic-gate 		len -= slen;
3927c478bd9Sstevel@tonic-gate 	}
3937c478bd9Sstevel@tonic-gate 	else
3947c478bd9Sstevel@tonic-gate 	{
3957c478bd9Sstevel@tonic-gate 		while (slen-- > 0 && (c = *s++) != '\0')
3967c478bd9Sstevel@tonic-gate 		{
3977c478bd9Sstevel@tonic-gate 			if (c != '%')
3987c478bd9Sstevel@tonic-gate 			{
3997c478bd9Sstevel@tonic-gate   pushc:
4007c478bd9Sstevel@tonic-gate 				if (len-- <= 1)
4017c478bd9Sstevel@tonic-gate 				     break;
4027c478bd9Sstevel@tonic-gate 				*bp++ = c;
4037c478bd9Sstevel@tonic-gate 				continue;
4047c478bd9Sstevel@tonic-gate 			}
4057c478bd9Sstevel@tonic-gate 			if (slen-- <= 0 || (c = *s++) == '\0')
4067c478bd9Sstevel@tonic-gate 				c = '%';
4077c478bd9Sstevel@tonic-gate 			if (c == '%')
4087c478bd9Sstevel@tonic-gate 				goto pushc;
4097c478bd9Sstevel@tonic-gate 			if (!(isascii(c) && isdigit(c)))
4107c478bd9Sstevel@tonic-gate 			{
4117c478bd9Sstevel@tonic-gate 				if (len-- <= 1)
4127c478bd9Sstevel@tonic-gate 				     break;
4137c478bd9Sstevel@tonic-gate 				*bp++ = '%';
4147c478bd9Sstevel@tonic-gate 				goto pushc;
4157c478bd9Sstevel@tonic-gate 			}
4167c478bd9Sstevel@tonic-gate 			for (avp = av; --c >= '0' && *avp != NULL; avp++)
4177c478bd9Sstevel@tonic-gate 				continue;
4187c478bd9Sstevel@tonic-gate 			if (*avp == NULL)
4197c478bd9Sstevel@tonic-gate 				continue;
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate 			/* transliterate argument into output string */
4227c478bd9Sstevel@tonic-gate 			for (ap = *avp; (c = *ap++) != '\0' && len > 0; --len)
4237c478bd9Sstevel@tonic-gate 				*bp++ = c;
4247c478bd9Sstevel@tonic-gate 		}
4257c478bd9Sstevel@tonic-gate 	}
4267c478bd9Sstevel@tonic-gate 	if (map->map_app != NULL && len > 0)
4277c478bd9Sstevel@tonic-gate 		(void) sm_strlcpy(bp, map->map_app, len);
4287c478bd9Sstevel@tonic-gate 	else
4297c478bd9Sstevel@tonic-gate 		*bp = '\0';
4307c478bd9Sstevel@tonic-gate 	if (tTd(39, 1))
4317c478bd9Sstevel@tonic-gate 		sm_dprintf("map_rewrite => %s\n", buf);
4327c478bd9Sstevel@tonic-gate 	return buf;
4337c478bd9Sstevel@tonic-gate }
4347c478bd9Sstevel@tonic-gate /*
4357c478bd9Sstevel@tonic-gate **  INITMAPS -- rebuild alias maps
4367c478bd9Sstevel@tonic-gate **
4377c478bd9Sstevel@tonic-gate **	Parameters:
4387c478bd9Sstevel@tonic-gate **		none.
4397c478bd9Sstevel@tonic-gate **
4407c478bd9Sstevel@tonic-gate **	Returns:
4417c478bd9Sstevel@tonic-gate **		none.
4427c478bd9Sstevel@tonic-gate */
4437c478bd9Sstevel@tonic-gate 
4447c478bd9Sstevel@tonic-gate void
4457c478bd9Sstevel@tonic-gate initmaps()
4467c478bd9Sstevel@tonic-gate {
4477c478bd9Sstevel@tonic-gate #if XDEBUG
4487c478bd9Sstevel@tonic-gate 	checkfd012("entering initmaps");
4497c478bd9Sstevel@tonic-gate #endif /* XDEBUG */
4507c478bd9Sstevel@tonic-gate 	stabapply(map_init, 0);
4517c478bd9Sstevel@tonic-gate #if XDEBUG
4527c478bd9Sstevel@tonic-gate 	checkfd012("exiting initmaps");
4537c478bd9Sstevel@tonic-gate #endif /* XDEBUG */
4547c478bd9Sstevel@tonic-gate }
4557c478bd9Sstevel@tonic-gate /*
4567c478bd9Sstevel@tonic-gate **  MAP_INIT -- rebuild a map
4577c478bd9Sstevel@tonic-gate **
4587c478bd9Sstevel@tonic-gate **	Parameters:
4597c478bd9Sstevel@tonic-gate **		s -- STAB entry: if map: try to rebuild
4607c478bd9Sstevel@tonic-gate **		unused -- unused variable
4617c478bd9Sstevel@tonic-gate **
4627c478bd9Sstevel@tonic-gate **	Returns:
4637c478bd9Sstevel@tonic-gate **		none.
4647c478bd9Sstevel@tonic-gate **
4657c478bd9Sstevel@tonic-gate **	Side Effects:
4667c478bd9Sstevel@tonic-gate **		will close already open rebuildable map.
4677c478bd9Sstevel@tonic-gate */
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate /* ARGSUSED1 */
4707c478bd9Sstevel@tonic-gate static void
4717c478bd9Sstevel@tonic-gate map_init(s, unused)
4727c478bd9Sstevel@tonic-gate 	register STAB *s;
4737c478bd9Sstevel@tonic-gate 	int unused;
4747c478bd9Sstevel@tonic-gate {
4757c478bd9Sstevel@tonic-gate 	register MAP *map;
4767c478bd9Sstevel@tonic-gate 
4777c478bd9Sstevel@tonic-gate 	/* has to be a map */
4787c478bd9Sstevel@tonic-gate 	if (s->s_symtype != ST_MAP)
4797c478bd9Sstevel@tonic-gate 		return;
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 	map = &s->s_map;
4827c478bd9Sstevel@tonic-gate 	if (!bitset(MF_VALID, map->map_mflags))
4837c478bd9Sstevel@tonic-gate 		return;
4847c478bd9Sstevel@tonic-gate 
4857c478bd9Sstevel@tonic-gate 	if (tTd(38, 2))
4867c478bd9Sstevel@tonic-gate 		sm_dprintf("map_init(%s:%s, %s)\n",
4877c478bd9Sstevel@tonic-gate 			map->map_class->map_cname == NULL ? "NULL" :
4887c478bd9Sstevel@tonic-gate 				map->map_class->map_cname,
4897c478bd9Sstevel@tonic-gate 			map->map_mname == NULL ? "NULL" : map->map_mname,
4907c478bd9Sstevel@tonic-gate 			map->map_file == NULL ? "NULL" : map->map_file);
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate 	if (!bitset(MF_ALIAS, map->map_mflags) ||
4937c478bd9Sstevel@tonic-gate 	    !bitset(MCF_REBUILDABLE, map->map_class->map_cflags))
4947c478bd9Sstevel@tonic-gate 	{
4957c478bd9Sstevel@tonic-gate 		if (tTd(38, 3))
4967c478bd9Sstevel@tonic-gate 			sm_dprintf("\tnot rebuildable\n");
4977c478bd9Sstevel@tonic-gate 		return;
4987c478bd9Sstevel@tonic-gate 	}
4997c478bd9Sstevel@tonic-gate 
5007c478bd9Sstevel@tonic-gate 	/* if already open, close it (for nested open) */
5017c478bd9Sstevel@tonic-gate 	if (bitset(MF_OPEN, map->map_mflags))
5027c478bd9Sstevel@tonic-gate 	{
5037c478bd9Sstevel@tonic-gate 		map->map_mflags |= MF_CLOSING;
5047c478bd9Sstevel@tonic-gate 		map->map_class->map_close(map);
5057c478bd9Sstevel@tonic-gate 		map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING);
5067c478bd9Sstevel@tonic-gate 	}
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate 	(void) rebuildaliases(map, false);
5097c478bd9Sstevel@tonic-gate 	return;
5107c478bd9Sstevel@tonic-gate }
5117c478bd9Sstevel@tonic-gate /*
5127c478bd9Sstevel@tonic-gate **  OPENMAP -- open a map
5137c478bd9Sstevel@tonic-gate **
5147c478bd9Sstevel@tonic-gate **	Parameters:
5157c478bd9Sstevel@tonic-gate **		map -- map to open (it must not be open).
5167c478bd9Sstevel@tonic-gate **
5177c478bd9Sstevel@tonic-gate **	Returns:
5187c478bd9Sstevel@tonic-gate **		whether open succeeded.
5197c478bd9Sstevel@tonic-gate */
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate bool
5227c478bd9Sstevel@tonic-gate openmap(map)
5237c478bd9Sstevel@tonic-gate 	MAP *map;
5247c478bd9Sstevel@tonic-gate {
5257c478bd9Sstevel@tonic-gate 	bool restore = false;
5267c478bd9Sstevel@tonic-gate 	bool savehold = HoldErrs;
5277c478bd9Sstevel@tonic-gate 	bool savequick = QuickAbort;
5287c478bd9Sstevel@tonic-gate 	int saveerrors = Errors;
5297c478bd9Sstevel@tonic-gate 
5307c478bd9Sstevel@tonic-gate 	if (!bitset(MF_VALID, map->map_mflags))
5317c478bd9Sstevel@tonic-gate 		return false;
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate 	/* better safe than sorry... */
5347c478bd9Sstevel@tonic-gate 	if (bitset(MF_OPEN, map->map_mflags))
5357c478bd9Sstevel@tonic-gate 		return true;
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate 	/* Don't send a map open error out via SMTP */
5387c478bd9Sstevel@tonic-gate 	if ((OnlyOneError || QuickAbort) &&
5397c478bd9Sstevel@tonic-gate 	    (OpMode == MD_SMTP || OpMode == MD_DAEMON))
5407c478bd9Sstevel@tonic-gate 	{
5417c478bd9Sstevel@tonic-gate 		restore = true;
5427c478bd9Sstevel@tonic-gate 		HoldErrs = true;
5437c478bd9Sstevel@tonic-gate 		QuickAbort = false;
5447c478bd9Sstevel@tonic-gate 	}
5457c478bd9Sstevel@tonic-gate 
5467c478bd9Sstevel@tonic-gate 	errno = 0;
5477c478bd9Sstevel@tonic-gate 	if (map->map_class->map_open(map, O_RDONLY))
5487c478bd9Sstevel@tonic-gate 	{
5497c478bd9Sstevel@tonic-gate 		if (tTd(38, 4))
5507c478bd9Sstevel@tonic-gate 			sm_dprintf("openmap()\t%s:%s %s: valid\n",
5517c478bd9Sstevel@tonic-gate 				map->map_class->map_cname == NULL ? "NULL" :
5527c478bd9Sstevel@tonic-gate 					map->map_class->map_cname,
5537c478bd9Sstevel@tonic-gate 				map->map_mname == NULL ? "NULL" :
5547c478bd9Sstevel@tonic-gate 					map->map_mname,
5557c478bd9Sstevel@tonic-gate 				map->map_file == NULL ? "NULL" :
5567c478bd9Sstevel@tonic-gate 					map->map_file);
5577c478bd9Sstevel@tonic-gate 		map->map_mflags |= MF_OPEN;
5587c478bd9Sstevel@tonic-gate 		map->map_pid = CurrentPid;
5597c478bd9Sstevel@tonic-gate 	}
5607c478bd9Sstevel@tonic-gate 	else
5617c478bd9Sstevel@tonic-gate 	{
5627c478bd9Sstevel@tonic-gate 		if (tTd(38, 4))
5637c478bd9Sstevel@tonic-gate 			sm_dprintf("openmap()\t%s:%s %s: invalid%s%s\n",
5647c478bd9Sstevel@tonic-gate 				map->map_class->map_cname == NULL ? "NULL" :
5657c478bd9Sstevel@tonic-gate 					map->map_class->map_cname,
5667c478bd9Sstevel@tonic-gate 				map->map_mname == NULL ? "NULL" :
5677c478bd9Sstevel@tonic-gate 					map->map_mname,
5687c478bd9Sstevel@tonic-gate 				map->map_file == NULL ? "NULL" :
5697c478bd9Sstevel@tonic-gate 					map->map_file,
5707c478bd9Sstevel@tonic-gate 				errno == 0 ? "" : ": ",
5717c478bd9Sstevel@tonic-gate 				errno == 0 ? "" : sm_errstring(errno));
5727c478bd9Sstevel@tonic-gate 		if (!bitset(MF_OPTIONAL, map->map_mflags))
5737c478bd9Sstevel@tonic-gate 		{
5747c478bd9Sstevel@tonic-gate 			extern MAPCLASS BogusMapClass;
5757c478bd9Sstevel@tonic-gate 
5767c478bd9Sstevel@tonic-gate 			map->map_orgclass = map->map_class;
5777c478bd9Sstevel@tonic-gate 			map->map_class = &BogusMapClass;
5787c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_OPEN|MF_OPENBOGUS;
5797c478bd9Sstevel@tonic-gate 			map->map_pid = CurrentPid;
5807c478bd9Sstevel@tonic-gate 		}
5817c478bd9Sstevel@tonic-gate 		else
5827c478bd9Sstevel@tonic-gate 		{
5837c478bd9Sstevel@tonic-gate 			/* don't try again */
5847c478bd9Sstevel@tonic-gate 			map->map_mflags &= ~MF_VALID;
5857c478bd9Sstevel@tonic-gate 		}
5867c478bd9Sstevel@tonic-gate 	}
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate 	if (restore)
5897c478bd9Sstevel@tonic-gate 	{
5907c478bd9Sstevel@tonic-gate 		Errors = saveerrors;
5917c478bd9Sstevel@tonic-gate 		HoldErrs = savehold;
5927c478bd9Sstevel@tonic-gate 		QuickAbort = savequick;
5937c478bd9Sstevel@tonic-gate 	}
5947c478bd9Sstevel@tonic-gate 
5957c478bd9Sstevel@tonic-gate 	return bitset(MF_OPEN, map->map_mflags);
5967c478bd9Sstevel@tonic-gate }
5977c478bd9Sstevel@tonic-gate /*
5987c478bd9Sstevel@tonic-gate **  CLOSEMAPS -- close all open maps opened by the current pid.
5997c478bd9Sstevel@tonic-gate **
6007c478bd9Sstevel@tonic-gate **	Parameters:
6017c478bd9Sstevel@tonic-gate **		bogus -- only close bogus maps.
6027c478bd9Sstevel@tonic-gate **
6037c478bd9Sstevel@tonic-gate **	Returns:
6047c478bd9Sstevel@tonic-gate **		none.
6057c478bd9Sstevel@tonic-gate */
6067c478bd9Sstevel@tonic-gate 
6077c478bd9Sstevel@tonic-gate void
6087c478bd9Sstevel@tonic-gate closemaps(bogus)
6097c478bd9Sstevel@tonic-gate 	bool bogus;
6107c478bd9Sstevel@tonic-gate {
6117c478bd9Sstevel@tonic-gate 	stabapply(map_close, bogus);
6127c478bd9Sstevel@tonic-gate }
6137c478bd9Sstevel@tonic-gate /*
6147c478bd9Sstevel@tonic-gate **  MAP_CLOSE -- close a map opened by the current pid.
6157c478bd9Sstevel@tonic-gate **
6167c478bd9Sstevel@tonic-gate **	Parameters:
6177c478bd9Sstevel@tonic-gate **		s -- STAB entry: if map: try to close
6187c478bd9Sstevel@tonic-gate **		bogus -- only close bogus maps or MCF_NOTPERSIST maps.
6197c478bd9Sstevel@tonic-gate **
6207c478bd9Sstevel@tonic-gate **	Returns:
6217c478bd9Sstevel@tonic-gate **		none.
6227c478bd9Sstevel@tonic-gate */
6237c478bd9Sstevel@tonic-gate 
6247c478bd9Sstevel@tonic-gate /* ARGSUSED1 */
6257c478bd9Sstevel@tonic-gate static void
6267c478bd9Sstevel@tonic-gate map_close(s, bogus)
6277c478bd9Sstevel@tonic-gate 	register STAB *s;
6287c478bd9Sstevel@tonic-gate 	int bogus;	/* int because of stabapply(), used as bool */
6297c478bd9Sstevel@tonic-gate {
6307c478bd9Sstevel@tonic-gate 	MAP *map;
6317c478bd9Sstevel@tonic-gate 	extern MAPCLASS BogusMapClass;
6327c478bd9Sstevel@tonic-gate 
6337c478bd9Sstevel@tonic-gate 	if (s->s_symtype != ST_MAP)
6347c478bd9Sstevel@tonic-gate 		return;
6357c478bd9Sstevel@tonic-gate 
6367c478bd9Sstevel@tonic-gate 	map = &s->s_map;
6377c478bd9Sstevel@tonic-gate 
6387c478bd9Sstevel@tonic-gate 	/*
6397c478bd9Sstevel@tonic-gate 	**  close the map iff:
6407c478bd9Sstevel@tonic-gate 	**  it is valid and open and opened by this process
6417c478bd9Sstevel@tonic-gate 	**  and (!bogus or it's a bogus map or it is not persistent)
6427c478bd9Sstevel@tonic-gate 	**  negate this: return iff
6437c478bd9Sstevel@tonic-gate 	**  it is not valid or it is not open or not opened by this process
6447c478bd9Sstevel@tonic-gate 	**  or (bogus and it's not a bogus map and it's not not-persistent)
6457c478bd9Sstevel@tonic-gate 	*/
6467c478bd9Sstevel@tonic-gate 
6477c478bd9Sstevel@tonic-gate 	if (!bitset(MF_VALID, map->map_mflags) ||
6487c478bd9Sstevel@tonic-gate 	    !bitset(MF_OPEN, map->map_mflags) ||
6497c478bd9Sstevel@tonic-gate 	    bitset(MF_CLOSING, map->map_mflags) ||
6507c478bd9Sstevel@tonic-gate 	    map->map_pid != CurrentPid ||
6517c478bd9Sstevel@tonic-gate 	    (bogus && map->map_class != &BogusMapClass &&
6527c478bd9Sstevel@tonic-gate 	     !bitset(MCF_NOTPERSIST, map->map_class->map_cflags)))
6537c478bd9Sstevel@tonic-gate 		return;
6547c478bd9Sstevel@tonic-gate 
6557c478bd9Sstevel@tonic-gate 	if (map->map_class == &BogusMapClass && map->map_orgclass != NULL &&
6567c478bd9Sstevel@tonic-gate 	    map->map_orgclass != &BogusMapClass)
6577c478bd9Sstevel@tonic-gate 		map->map_class = map->map_orgclass;
6587c478bd9Sstevel@tonic-gate 	if (tTd(38, 5))
6597c478bd9Sstevel@tonic-gate 		sm_dprintf("closemaps: closing %s (%s)\n",
6607c478bd9Sstevel@tonic-gate 			map->map_mname == NULL ? "NULL" : map->map_mname,
6617c478bd9Sstevel@tonic-gate 			map->map_file == NULL ? "NULL" : map->map_file);
6627c478bd9Sstevel@tonic-gate 
6637c478bd9Sstevel@tonic-gate 	if (!bitset(MF_OPENBOGUS, map->map_mflags))
6647c478bd9Sstevel@tonic-gate 	{
6657c478bd9Sstevel@tonic-gate 		map->map_mflags |= MF_CLOSING;
6667c478bd9Sstevel@tonic-gate 		map->map_class->map_close(map);
6677c478bd9Sstevel@tonic-gate 	}
6687c478bd9Sstevel@tonic-gate 	map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_OPENBOGUS|MF_CLOSING);
6697c478bd9Sstevel@tonic-gate }
6707c478bd9Sstevel@tonic-gate /*
6717c478bd9Sstevel@tonic-gate **  GETCANONNAME -- look up name using service switch
6727c478bd9Sstevel@tonic-gate **
6737c478bd9Sstevel@tonic-gate **	Parameters:
6747c478bd9Sstevel@tonic-gate **		host -- the host name to look up.
6757c478bd9Sstevel@tonic-gate **		hbsize -- the size of the host buffer.
6767c478bd9Sstevel@tonic-gate **		trymx -- if set, try MX records.
6777c478bd9Sstevel@tonic-gate **		pttl -- pointer to return TTL (can be NULL).
6787c478bd9Sstevel@tonic-gate **
6797c478bd9Sstevel@tonic-gate **	Returns:
6807c478bd9Sstevel@tonic-gate **		true -- if the host was found.
6817c478bd9Sstevel@tonic-gate **		false -- otherwise.
6827c478bd9Sstevel@tonic-gate */
6837c478bd9Sstevel@tonic-gate 
6847c478bd9Sstevel@tonic-gate bool
6857c478bd9Sstevel@tonic-gate getcanonname(host, hbsize, trymx, pttl)
6867c478bd9Sstevel@tonic-gate 	char *host;
6877c478bd9Sstevel@tonic-gate 	int hbsize;
6887c478bd9Sstevel@tonic-gate 	bool trymx;
6897c478bd9Sstevel@tonic-gate 	int *pttl;
6907c478bd9Sstevel@tonic-gate {
6917c478bd9Sstevel@tonic-gate 	int nmaps;
6927c478bd9Sstevel@tonic-gate 	int mapno;
6937c478bd9Sstevel@tonic-gate 	bool found = false;
6947c478bd9Sstevel@tonic-gate 	bool got_tempfail = false;
6957c478bd9Sstevel@tonic-gate 	auto int status;
6967c478bd9Sstevel@tonic-gate 	char *maptype[MAXMAPSTACK];
6977c478bd9Sstevel@tonic-gate 	short mapreturn[MAXMAPACTIONS];
6987c478bd9Sstevel@tonic-gate #if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN)
6997c478bd9Sstevel@tonic-gate 	bool should_try_nis_domain = false;
7007c478bd9Sstevel@tonic-gate 	static char *nis_domain = NULL;
7017c478bd9Sstevel@tonic-gate 	extern char *sun_init_domain();
7027c478bd9Sstevel@tonic-gate #endif
7037c478bd9Sstevel@tonic-gate 
7047c478bd9Sstevel@tonic-gate 	nmaps = switch_map_find("hosts", maptype, mapreturn);
7057c478bd9Sstevel@tonic-gate 	if (pttl != 0)
7067c478bd9Sstevel@tonic-gate 		*pttl = SM_DEFAULT_TTL;
7077c478bd9Sstevel@tonic-gate 	for (mapno = 0; mapno < nmaps; mapno++)
7087c478bd9Sstevel@tonic-gate 	{
7097c478bd9Sstevel@tonic-gate 		int i;
7107c478bd9Sstevel@tonic-gate 
7117c478bd9Sstevel@tonic-gate 		if (tTd(38, 20))
7127c478bd9Sstevel@tonic-gate 			sm_dprintf("getcanonname(%s), trying %s\n",
7137c478bd9Sstevel@tonic-gate 				host, maptype[mapno]);
7147c478bd9Sstevel@tonic-gate 		if (strcmp("files", maptype[mapno]) == 0)
7157c478bd9Sstevel@tonic-gate 		{
7167c478bd9Sstevel@tonic-gate 			found = text_getcanonname(host, hbsize, &status);
7177c478bd9Sstevel@tonic-gate 		}
7187c478bd9Sstevel@tonic-gate #if NIS
7197c478bd9Sstevel@tonic-gate 		else if (strcmp("nis", maptype[mapno]) == 0)
7207c478bd9Sstevel@tonic-gate 		{
7217c478bd9Sstevel@tonic-gate 			found = nis_getcanonname(host, hbsize, &status);
7227c478bd9Sstevel@tonic-gate # if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN)
7237c478bd9Sstevel@tonic-gate 			if (nis_domain == NULL)
7247c478bd9Sstevel@tonic-gate 				nis_domain = sun_init_domain();
7257c478bd9Sstevel@tonic-gate # endif
7267c478bd9Sstevel@tonic-gate 		}
7277c478bd9Sstevel@tonic-gate #endif /* NIS */
7287c478bd9Sstevel@tonic-gate #if NISPLUS
7297c478bd9Sstevel@tonic-gate 		else if (strcmp("nisplus", maptype[mapno]) == 0)
7307c478bd9Sstevel@tonic-gate 		{
7317c478bd9Sstevel@tonic-gate 			found = nisplus_getcanonname(host, hbsize, &status);
7327c478bd9Sstevel@tonic-gate # if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN)
7337c478bd9Sstevel@tonic-gate 			if (nis_domain == NULL)
7347c478bd9Sstevel@tonic-gate 				nis_domain = sun_init_domain();
7357c478bd9Sstevel@tonic-gate # endif
7367c478bd9Sstevel@tonic-gate 		}
7377c478bd9Sstevel@tonic-gate #endif /* NISPLUS */
7387c478bd9Sstevel@tonic-gate #if NAMED_BIND
7397c478bd9Sstevel@tonic-gate 		else if (strcmp("dns", maptype[mapno]) == 0)
7407c478bd9Sstevel@tonic-gate 		{
7417c478bd9Sstevel@tonic-gate 			found = dns_getcanonname(host, hbsize, trymx, &status,							 pttl);
7427c478bd9Sstevel@tonic-gate 		}
7437c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */
7447c478bd9Sstevel@tonic-gate #if NETINFO
7457c478bd9Sstevel@tonic-gate 		else if (strcmp("netinfo", maptype[mapno]) == 0)
7467c478bd9Sstevel@tonic-gate 		{
7477c478bd9Sstevel@tonic-gate 			found = ni_getcanonname(host, hbsize, &status);
7487c478bd9Sstevel@tonic-gate 		}
7497c478bd9Sstevel@tonic-gate #endif /* NETINFO */
7507c478bd9Sstevel@tonic-gate 		else
7517c478bd9Sstevel@tonic-gate 		{
7527c478bd9Sstevel@tonic-gate 			found = false;
7537c478bd9Sstevel@tonic-gate 			status = EX_UNAVAILABLE;
7547c478bd9Sstevel@tonic-gate 		}
7557c478bd9Sstevel@tonic-gate 
7567c478bd9Sstevel@tonic-gate 		/*
7577c478bd9Sstevel@tonic-gate 		**  Heuristic: if $m is not set, we are running during system
7587c478bd9Sstevel@tonic-gate 		**  startup.  In this case, when a name is apparently found
7597c478bd9Sstevel@tonic-gate 		**  but has no dot, treat is as not found.  This avoids
7607c478bd9Sstevel@tonic-gate 		**  problems if /etc/hosts has no FQDN but is listed first
7617c478bd9Sstevel@tonic-gate 		**  in the service switch.
7627c478bd9Sstevel@tonic-gate 		*/
7637c478bd9Sstevel@tonic-gate 
7647c478bd9Sstevel@tonic-gate 		if (found &&
7657c478bd9Sstevel@tonic-gate 		    (macvalue('m', CurEnv) != NULL || strchr(host, '.') != NULL))
7667c478bd9Sstevel@tonic-gate 			break;
7677c478bd9Sstevel@tonic-gate 
7687c478bd9Sstevel@tonic-gate #if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN)
7697c478bd9Sstevel@tonic-gate 		if (found)
7707c478bd9Sstevel@tonic-gate 			should_try_nis_domain = true;
7717c478bd9Sstevel@tonic-gate 		/* but don't break, as we need to try all methods first */
7727c478bd9Sstevel@tonic-gate #endif
7737c478bd9Sstevel@tonic-gate 
7747c478bd9Sstevel@tonic-gate 		/* see if we should continue */
7757c478bd9Sstevel@tonic-gate 		if (status == EX_TEMPFAIL)
7767c478bd9Sstevel@tonic-gate 		{
7777c478bd9Sstevel@tonic-gate 			i = MA_TRYAGAIN;
7787c478bd9Sstevel@tonic-gate 			got_tempfail = true;
7797c478bd9Sstevel@tonic-gate 		}
7807c478bd9Sstevel@tonic-gate 		else if (status == EX_NOTFOUND)
7817c478bd9Sstevel@tonic-gate 			i = MA_NOTFOUND;
7827c478bd9Sstevel@tonic-gate 		else
7837c478bd9Sstevel@tonic-gate 			i = MA_UNAVAIL;
7847c478bd9Sstevel@tonic-gate 		if (bitset(1 << mapno, mapreturn[i]))
7857c478bd9Sstevel@tonic-gate 			break;
7867c478bd9Sstevel@tonic-gate 	}
7877c478bd9Sstevel@tonic-gate 
7887c478bd9Sstevel@tonic-gate 	if (found)
7897c478bd9Sstevel@tonic-gate 	{
7907c478bd9Sstevel@tonic-gate 		char *d;
7917c478bd9Sstevel@tonic-gate 
7927c478bd9Sstevel@tonic-gate 		if (tTd(38, 20))
7937c478bd9Sstevel@tonic-gate 			sm_dprintf("getcanonname(%s), found\n", host);
7947c478bd9Sstevel@tonic-gate 
7957c478bd9Sstevel@tonic-gate 		/*
7967c478bd9Sstevel@tonic-gate 		**  If returned name is still single token, compensate
7977c478bd9Sstevel@tonic-gate 		**  by tagging on $m.  This is because some sites set
7987c478bd9Sstevel@tonic-gate 		**  up their DNS or NIS databases wrong.
7997c478bd9Sstevel@tonic-gate 		*/
8007c478bd9Sstevel@tonic-gate 
8017c478bd9Sstevel@tonic-gate 		if ((d = strchr(host, '.')) == NULL || d[1] == '\0')
8027c478bd9Sstevel@tonic-gate 		{
8037c478bd9Sstevel@tonic-gate 			d = macvalue('m', CurEnv);
8047c478bd9Sstevel@tonic-gate 			if (d != NULL &&
8057c478bd9Sstevel@tonic-gate 			    hbsize > (int) (strlen(host) + strlen(d) + 1))
8067c478bd9Sstevel@tonic-gate 			{
8077c478bd9Sstevel@tonic-gate 				if (host[strlen(host) - 1] != '.')
8087c478bd9Sstevel@tonic-gate 					(void) sm_strlcat2(host, ".", d,
8097c478bd9Sstevel@tonic-gate 							   hbsize);
8107c478bd9Sstevel@tonic-gate 				else
8117c478bd9Sstevel@tonic-gate 					(void) sm_strlcat(host, d, hbsize);
8127c478bd9Sstevel@tonic-gate 			}
8137c478bd9Sstevel@tonic-gate 			else
8147c478bd9Sstevel@tonic-gate 			{
8157c478bd9Sstevel@tonic-gate #if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN)
8167c478bd9Sstevel@tonic-gate 				if (VendorCode == VENDOR_SUN &&
8177c478bd9Sstevel@tonic-gate 					should_try_nis_domain)
8187c478bd9Sstevel@tonic-gate 				{
8197c478bd9Sstevel@tonic-gate 					goto try_nis_domain;
8207c478bd9Sstevel@tonic-gate 				}
8217c478bd9Sstevel@tonic-gate #endif
8227c478bd9Sstevel@tonic-gate 				return false;
8237c478bd9Sstevel@tonic-gate 			}
8247c478bd9Sstevel@tonic-gate 		}
8257c478bd9Sstevel@tonic-gate 		return true;
8267c478bd9Sstevel@tonic-gate 	}
8277c478bd9Sstevel@tonic-gate 
8287c478bd9Sstevel@tonic-gate #if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN)
8297c478bd9Sstevel@tonic-gate 	if (VendorCode == VENDOR_SUN && should_try_nis_domain)
8307c478bd9Sstevel@tonic-gate 	{
8317c478bd9Sstevel@tonic-gate try_nis_domain:
8327c478bd9Sstevel@tonic-gate 		if (nis_domain != NULL &&
8337c478bd9Sstevel@tonic-gate 			strlen(nis_domain) + strlen(host) + 1 < hbsize)
8347c478bd9Sstevel@tonic-gate 		{
8357c478bd9Sstevel@tonic-gate 			(void) sm_strlcat2(host, ".", nis_domain, hbsize);
8367c478bd9Sstevel@tonic-gate 			return true;
8377c478bd9Sstevel@tonic-gate 		}
8387c478bd9Sstevel@tonic-gate 	}
8397c478bd9Sstevel@tonic-gate #endif
8407c478bd9Sstevel@tonic-gate 
8417c478bd9Sstevel@tonic-gate 	if (tTd(38, 20))
8427c478bd9Sstevel@tonic-gate 		sm_dprintf("getcanonname(%s), failed, status=%d\n", host,
8437c478bd9Sstevel@tonic-gate 			status);
8447c478bd9Sstevel@tonic-gate 
8457c478bd9Sstevel@tonic-gate 	if (got_tempfail)
8467c478bd9Sstevel@tonic-gate 		SM_SET_H_ERRNO(TRY_AGAIN);
8477c478bd9Sstevel@tonic-gate 	else
8487c478bd9Sstevel@tonic-gate 		SM_SET_H_ERRNO(HOST_NOT_FOUND);
8497c478bd9Sstevel@tonic-gate 
8507c478bd9Sstevel@tonic-gate 	return false;
8517c478bd9Sstevel@tonic-gate }
8527c478bd9Sstevel@tonic-gate /*
8537c478bd9Sstevel@tonic-gate **  EXTRACT_CANONNAME -- extract canonical name from /etc/hosts entry
8547c478bd9Sstevel@tonic-gate **
8557c478bd9Sstevel@tonic-gate **	Parameters:
8567c478bd9Sstevel@tonic-gate **		name -- the name against which to match.
8577c478bd9Sstevel@tonic-gate **		dot -- where to reinsert '.' to get FQDN
8587c478bd9Sstevel@tonic-gate **		line -- the /etc/hosts line.
8597c478bd9Sstevel@tonic-gate **		cbuf -- the location to store the result.
8607c478bd9Sstevel@tonic-gate **		cbuflen -- the size of cbuf.
8617c478bd9Sstevel@tonic-gate **
8627c478bd9Sstevel@tonic-gate **	Returns:
8637c478bd9Sstevel@tonic-gate **		true -- if the line matched the desired name.
8647c478bd9Sstevel@tonic-gate **		false -- otherwise.
8657c478bd9Sstevel@tonic-gate */
8667c478bd9Sstevel@tonic-gate 
8677c478bd9Sstevel@tonic-gate static bool
8687c478bd9Sstevel@tonic-gate extract_canonname(name, dot, line, cbuf, cbuflen)
8697c478bd9Sstevel@tonic-gate 	char *name;
8707c478bd9Sstevel@tonic-gate 	char *dot;
8717c478bd9Sstevel@tonic-gate 	char *line;
8727c478bd9Sstevel@tonic-gate 	char cbuf[];
8737c478bd9Sstevel@tonic-gate 	int cbuflen;
8747c478bd9Sstevel@tonic-gate {
8757c478bd9Sstevel@tonic-gate 	int i;
8767c478bd9Sstevel@tonic-gate 	char *p;
8777c478bd9Sstevel@tonic-gate 	bool found = false;
8787c478bd9Sstevel@tonic-gate 
8797c478bd9Sstevel@tonic-gate 	cbuf[0] = '\0';
8807c478bd9Sstevel@tonic-gate 	if (line[0] == '#')
8817c478bd9Sstevel@tonic-gate 		return false;
8827c478bd9Sstevel@tonic-gate 
8837c478bd9Sstevel@tonic-gate 	for (i = 1; ; i++)
8847c478bd9Sstevel@tonic-gate 	{
8857c478bd9Sstevel@tonic-gate 		char nbuf[MAXNAME + 1];
8867c478bd9Sstevel@tonic-gate 
8877c478bd9Sstevel@tonic-gate 		p = get_column(line, i, '\0', nbuf, sizeof nbuf);
8887c478bd9Sstevel@tonic-gate 		if (p == NULL)
8897c478bd9Sstevel@tonic-gate 			break;
8907c478bd9Sstevel@tonic-gate 		if (*p == '\0')
8917c478bd9Sstevel@tonic-gate 			continue;
8927c478bd9Sstevel@tonic-gate 		if (cbuf[0] == '\0' ||
8937c478bd9Sstevel@tonic-gate 		    (strchr(cbuf, '.') == NULL && strchr(p, '.') != NULL))
8947c478bd9Sstevel@tonic-gate 		{
8957c478bd9Sstevel@tonic-gate 			(void) sm_strlcpy(cbuf, p, cbuflen);
8967c478bd9Sstevel@tonic-gate 		}
8977c478bd9Sstevel@tonic-gate 		if (sm_strcasecmp(name, p) == 0)
8987c478bd9Sstevel@tonic-gate 			found = true;
8997c478bd9Sstevel@tonic-gate 		else if (dot != NULL)
9007c478bd9Sstevel@tonic-gate 		{
9017c478bd9Sstevel@tonic-gate 			/* try looking for the FQDN as well */
9027c478bd9Sstevel@tonic-gate 			*dot = '.';
9037c478bd9Sstevel@tonic-gate 			if (sm_strcasecmp(name, p) == 0)
9047c478bd9Sstevel@tonic-gate 				found = true;
9057c478bd9Sstevel@tonic-gate 			*dot = '\0';
9067c478bd9Sstevel@tonic-gate 		}
9077c478bd9Sstevel@tonic-gate 	}
9087c478bd9Sstevel@tonic-gate 	if (found && strchr(cbuf, '.') == NULL)
9097c478bd9Sstevel@tonic-gate 	{
9107c478bd9Sstevel@tonic-gate 		/* try to add a domain on the end of the name */
9117c478bd9Sstevel@tonic-gate 		char *domain = macvalue('m', CurEnv);
9127c478bd9Sstevel@tonic-gate 
9137c478bd9Sstevel@tonic-gate 		if (domain != NULL &&
9147c478bd9Sstevel@tonic-gate 		    strlen(domain) + (i = strlen(cbuf)) + 1 < (size_t) cbuflen)
9157c478bd9Sstevel@tonic-gate 		{
9167c478bd9Sstevel@tonic-gate 			p = &cbuf[i];
9177c478bd9Sstevel@tonic-gate 			*p++ = '.';
9187c478bd9Sstevel@tonic-gate 			(void) sm_strlcpy(p, domain, cbuflen - i - 1);
9197c478bd9Sstevel@tonic-gate 		}
9207c478bd9Sstevel@tonic-gate 	}
9217c478bd9Sstevel@tonic-gate 	return found;
9227c478bd9Sstevel@tonic-gate }
9237c478bd9Sstevel@tonic-gate 
9247c478bd9Sstevel@tonic-gate /*
9257c478bd9Sstevel@tonic-gate **  DNS modules
9267c478bd9Sstevel@tonic-gate */
9277c478bd9Sstevel@tonic-gate 
9287c478bd9Sstevel@tonic-gate #if NAMED_BIND
9297c478bd9Sstevel@tonic-gate # if DNSMAP
9307c478bd9Sstevel@tonic-gate 
9317c478bd9Sstevel@tonic-gate #  include "sm_resolve.h"
9327c478bd9Sstevel@tonic-gate #  if NETINET || NETINET6
9337c478bd9Sstevel@tonic-gate #   include <arpa/inet.h>
9347c478bd9Sstevel@tonic-gate #  endif /* NETINET || NETINET6 */
9357c478bd9Sstevel@tonic-gate 
9367c478bd9Sstevel@tonic-gate /*
9377c478bd9Sstevel@tonic-gate **  DNS_MAP_OPEN -- stub to check proper value for dns map type
9387c478bd9Sstevel@tonic-gate */
9397c478bd9Sstevel@tonic-gate 
9407c478bd9Sstevel@tonic-gate bool
9417c478bd9Sstevel@tonic-gate dns_map_open(map, mode)
9427c478bd9Sstevel@tonic-gate 	MAP *map;
9437c478bd9Sstevel@tonic-gate 	int mode;
9447c478bd9Sstevel@tonic-gate {
9457c478bd9Sstevel@tonic-gate 	if (tTd(38,2))
9467c478bd9Sstevel@tonic-gate 		sm_dprintf("dns_map_open(%s, %d)\n", map->map_mname, mode);
9477c478bd9Sstevel@tonic-gate 
9487c478bd9Sstevel@tonic-gate 	mode &= O_ACCMODE;
9497c478bd9Sstevel@tonic-gate 	if (mode != O_RDONLY)
9507c478bd9Sstevel@tonic-gate 	{
9517c478bd9Sstevel@tonic-gate 		/* issue a pseudo-error message */
9527c478bd9Sstevel@tonic-gate 		errno = SM_EMAPCANTWRITE;
9537c478bd9Sstevel@tonic-gate 		return false;
9547c478bd9Sstevel@tonic-gate 	}
9557c478bd9Sstevel@tonic-gate 	return true;
9567c478bd9Sstevel@tonic-gate }
9577c478bd9Sstevel@tonic-gate 
9587c478bd9Sstevel@tonic-gate /*
9597c478bd9Sstevel@tonic-gate **  DNS_MAP_PARSEARGS -- parse dns map definition args.
9607c478bd9Sstevel@tonic-gate **
9617c478bd9Sstevel@tonic-gate **	Parameters:
9627c478bd9Sstevel@tonic-gate **		map -- pointer to MAP
9637c478bd9Sstevel@tonic-gate **		args -- pointer to the args on the config line.
9647c478bd9Sstevel@tonic-gate **
9657c478bd9Sstevel@tonic-gate **	Returns:
9667c478bd9Sstevel@tonic-gate **		true -- if everything parsed OK.
9677c478bd9Sstevel@tonic-gate **		false -- otherwise.
9687c478bd9Sstevel@tonic-gate */
9697c478bd9Sstevel@tonic-gate 
9707c478bd9Sstevel@tonic-gate #  if _FFR_DNSMAP_MULTILIMIT
9717c478bd9Sstevel@tonic-gate #   if !_FFR_DNSMAP_MULTI
9727c478bd9Sstevel@tonic-gate   ERROR README:	You must define _FFR_DNSMAP_MULTI to use _FFR_DNSMAP_MULTILIMIT
9737c478bd9Sstevel@tonic-gate #   endif /* ! _FFR_DNSMAP_MULTI */
9747c478bd9Sstevel@tonic-gate #  endif /* _FFR_DNSMAP_MULTILIMIT */
9757c478bd9Sstevel@tonic-gate 
9767c478bd9Sstevel@tonic-gate #  if _FFR_DNSMAP_MULTI
9777c478bd9Sstevel@tonic-gate #   if _FFR_DNSMAP_MULTILIMIT
9787c478bd9Sstevel@tonic-gate #    define map_sizelimit	map_lockfd	/* overload field */
9797c478bd9Sstevel@tonic-gate #   endif /* _FFR_DNSMAP_MULTILIMIT */
9807c478bd9Sstevel@tonic-gate #  endif /* _FFR_DNSMAP_MULTI */
9817c478bd9Sstevel@tonic-gate 
9827c478bd9Sstevel@tonic-gate struct dns_map
9837c478bd9Sstevel@tonic-gate {
9847c478bd9Sstevel@tonic-gate 	int dns_m_type;
9857c478bd9Sstevel@tonic-gate };
9867c478bd9Sstevel@tonic-gate 
9877c478bd9Sstevel@tonic-gate bool
9887c478bd9Sstevel@tonic-gate dns_map_parseargs(map,args)
9897c478bd9Sstevel@tonic-gate 	MAP *map;
9907c478bd9Sstevel@tonic-gate 	char *args;
9917c478bd9Sstevel@tonic-gate {
9927c478bd9Sstevel@tonic-gate 	register char *p = args;
9937c478bd9Sstevel@tonic-gate 	struct dns_map *map_p;
9947c478bd9Sstevel@tonic-gate 
9957c478bd9Sstevel@tonic-gate 	map_p = (struct dns_map *) xalloc(sizeof *map_p);
9967c478bd9Sstevel@tonic-gate 	map_p->dns_m_type = -1;
9977c478bd9Sstevel@tonic-gate 	map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL;
9987c478bd9Sstevel@tonic-gate 
9997c478bd9Sstevel@tonic-gate 	for (;;)
10007c478bd9Sstevel@tonic-gate 	{
10017c478bd9Sstevel@tonic-gate 		while (isascii(*p) && isspace(*p))
10027c478bd9Sstevel@tonic-gate 			p++;
10037c478bd9Sstevel@tonic-gate 		if (*p != '-')
10047c478bd9Sstevel@tonic-gate 			break;
10057c478bd9Sstevel@tonic-gate 		switch (*++p)
10067c478bd9Sstevel@tonic-gate 		{
10077c478bd9Sstevel@tonic-gate 		  case 'N':
10087c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_INCLNULL;
10097c478bd9Sstevel@tonic-gate 			map->map_mflags &= ~MF_TRY0NULL;
10107c478bd9Sstevel@tonic-gate 			break;
10117c478bd9Sstevel@tonic-gate 
10127c478bd9Sstevel@tonic-gate 		  case 'O':
10137c478bd9Sstevel@tonic-gate 			map->map_mflags &= ~MF_TRY1NULL;
10147c478bd9Sstevel@tonic-gate 			break;
10157c478bd9Sstevel@tonic-gate 
10167c478bd9Sstevel@tonic-gate 		  case 'o':
10177c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_OPTIONAL;
10187c478bd9Sstevel@tonic-gate 			break;
10197c478bd9Sstevel@tonic-gate 
10207c478bd9Sstevel@tonic-gate 		  case 'f':
10217c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_NOFOLDCASE;
10227c478bd9Sstevel@tonic-gate 			break;
10237c478bd9Sstevel@tonic-gate 
10247c478bd9Sstevel@tonic-gate 		  case 'm':
10257c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_MATCHONLY;
10267c478bd9Sstevel@tonic-gate 			break;
10277c478bd9Sstevel@tonic-gate 
10287c478bd9Sstevel@tonic-gate 		  case 'A':
10297c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_APPEND;
10307c478bd9Sstevel@tonic-gate 			break;
10317c478bd9Sstevel@tonic-gate 
10327c478bd9Sstevel@tonic-gate 		  case 'q':
10337c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_KEEPQUOTES;
10347c478bd9Sstevel@tonic-gate 			break;
10357c478bd9Sstevel@tonic-gate 
10367c478bd9Sstevel@tonic-gate 		  case 't':
10377c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_NODEFER;
10387c478bd9Sstevel@tonic-gate 			break;
10397c478bd9Sstevel@tonic-gate 
10407c478bd9Sstevel@tonic-gate 		  case 'a':
10417c478bd9Sstevel@tonic-gate 			map->map_app = ++p;
10427c478bd9Sstevel@tonic-gate 			break;
10437c478bd9Sstevel@tonic-gate 
10447c478bd9Sstevel@tonic-gate 		  case 'T':
10457c478bd9Sstevel@tonic-gate 			map->map_tapp = ++p;
10467c478bd9Sstevel@tonic-gate 			break;
10477c478bd9Sstevel@tonic-gate 
10487c478bd9Sstevel@tonic-gate 		  case 'd':
10497c478bd9Sstevel@tonic-gate 			{
10507c478bd9Sstevel@tonic-gate 				char *h;
10517c478bd9Sstevel@tonic-gate 
10527c478bd9Sstevel@tonic-gate 				++p;
10537c478bd9Sstevel@tonic-gate 				h = strchr(p, ' ');
10547c478bd9Sstevel@tonic-gate 				if (h != NULL)
10557c478bd9Sstevel@tonic-gate 					*h = '\0';
10567c478bd9Sstevel@tonic-gate 				map->map_timeout = convtime(p, 's');
10577c478bd9Sstevel@tonic-gate 				if (h != NULL)
10587c478bd9Sstevel@tonic-gate 					*h = ' ';
10597c478bd9Sstevel@tonic-gate 			}
10607c478bd9Sstevel@tonic-gate 			break;
10617c478bd9Sstevel@tonic-gate 
10627c478bd9Sstevel@tonic-gate 		  case 'r':
10637c478bd9Sstevel@tonic-gate 			while (isascii(*++p) && isspace(*p))
10647c478bd9Sstevel@tonic-gate 				continue;
10657c478bd9Sstevel@tonic-gate 			map->map_retry = atoi(p);
10667c478bd9Sstevel@tonic-gate 			break;
10677c478bd9Sstevel@tonic-gate 
10687c478bd9Sstevel@tonic-gate #  if _FFR_DNSMAP_MULTI
10697c478bd9Sstevel@tonic-gate 		  case 'z':
10707c478bd9Sstevel@tonic-gate 			if (*++p != '\\')
10717c478bd9Sstevel@tonic-gate 				map->map_coldelim = *p;
10727c478bd9Sstevel@tonic-gate 			else
10737c478bd9Sstevel@tonic-gate 			{
10747c478bd9Sstevel@tonic-gate 				switch (*++p)
10757c478bd9Sstevel@tonic-gate 				{
10767c478bd9Sstevel@tonic-gate 				  case 'n':
10777c478bd9Sstevel@tonic-gate 					map->map_coldelim = '\n';
10787c478bd9Sstevel@tonic-gate 					break;
10797c478bd9Sstevel@tonic-gate 
10807c478bd9Sstevel@tonic-gate 				  case 't':
10817c478bd9Sstevel@tonic-gate 					map->map_coldelim = '\t';
10827c478bd9Sstevel@tonic-gate 					break;
10837c478bd9Sstevel@tonic-gate 
10847c478bd9Sstevel@tonic-gate 				  default:
10857c478bd9Sstevel@tonic-gate 					map->map_coldelim = '\\';
10867c478bd9Sstevel@tonic-gate 				}
10877c478bd9Sstevel@tonic-gate 			}
10887c478bd9Sstevel@tonic-gate 			break;
10897c478bd9Sstevel@tonic-gate 
10907c478bd9Sstevel@tonic-gate #   if _FFR_DNSMAP_MULTILIMIT
10917c478bd9Sstevel@tonic-gate 		  case 'Z':
10927c478bd9Sstevel@tonic-gate 			while (isascii(*++p) && isspace(*p))
10937c478bd9Sstevel@tonic-gate 				continue;
10947c478bd9Sstevel@tonic-gate 			map->map_sizelimit = atoi(p);
10957c478bd9Sstevel@tonic-gate 			break;
10967c478bd9Sstevel@tonic-gate #   endif /* _FFR_DNSMAP_MULTILIMIT */
10977c478bd9Sstevel@tonic-gate #  endif /* _FFR_DNSMAP_MULTI */
10987c478bd9Sstevel@tonic-gate 
10997c478bd9Sstevel@tonic-gate 			/* Start of dns_map specific args */
11007c478bd9Sstevel@tonic-gate 		  case 'R':		/* search field */
11017c478bd9Sstevel@tonic-gate 			{
11027c478bd9Sstevel@tonic-gate 				char *h;
11037c478bd9Sstevel@tonic-gate 
11047c478bd9Sstevel@tonic-gate 				while (isascii(*++p) && isspace(*p))
11057c478bd9Sstevel@tonic-gate 					continue;
11067c478bd9Sstevel@tonic-gate 				h = strchr(p, ' ');
11077c478bd9Sstevel@tonic-gate 				if (h != NULL)
11087c478bd9Sstevel@tonic-gate 					*h = '\0';
11097c478bd9Sstevel@tonic-gate 				map_p->dns_m_type = dns_string_to_type(p);
11107c478bd9Sstevel@tonic-gate 				if (h != NULL)
11117c478bd9Sstevel@tonic-gate 					*h = ' ';
11127c478bd9Sstevel@tonic-gate 				if (map_p->dns_m_type < 0)
11137c478bd9Sstevel@tonic-gate 					syserr("dns map %s: wrong type %s",
11147c478bd9Sstevel@tonic-gate 						map->map_mname, p);
11157c478bd9Sstevel@tonic-gate 			}
11167c478bd9Sstevel@tonic-gate 			break;
11177c478bd9Sstevel@tonic-gate 
11187c478bd9Sstevel@tonic-gate #  if _FFR_DNSMAP_BASE
11197c478bd9Sstevel@tonic-gate 		  case 'B':		/* base domain */
11207c478bd9Sstevel@tonic-gate 			{
11217c478bd9Sstevel@tonic-gate 				char *h;
11227c478bd9Sstevel@tonic-gate 
11237c478bd9Sstevel@tonic-gate 				while (isascii(*++p) && isspace(*p))
11247c478bd9Sstevel@tonic-gate 					continue;
11257c478bd9Sstevel@tonic-gate 				h = strchr(p, ' ');
11267c478bd9Sstevel@tonic-gate 				if (h != NULL)
11277c478bd9Sstevel@tonic-gate 					*h = '\0';
11287c478bd9Sstevel@tonic-gate 
11297c478bd9Sstevel@tonic-gate 				/*
11307c478bd9Sstevel@tonic-gate 				**  slight abuse of map->map_file; it isn't
11317c478bd9Sstevel@tonic-gate 				**	used otherwise in this map type.
11327c478bd9Sstevel@tonic-gate 				*/
11337c478bd9Sstevel@tonic-gate 
11347c478bd9Sstevel@tonic-gate 				map->map_file = newstr(p);
11357c478bd9Sstevel@tonic-gate 				if (h != NULL)
11367c478bd9Sstevel@tonic-gate 					*h = ' ';
11377c478bd9Sstevel@tonic-gate 			}
11387c478bd9Sstevel@tonic-gate 			break;
11397c478bd9Sstevel@tonic-gate #  endif /* _FFR_DNSMAP_BASE */
11407c478bd9Sstevel@tonic-gate 
11417c478bd9Sstevel@tonic-gate 		}
11427c478bd9Sstevel@tonic-gate 		while (*p != '\0' && !(isascii(*p) && isspace(*p)))
11437c478bd9Sstevel@tonic-gate 			p++;
11447c478bd9Sstevel@tonic-gate 		if (*p != '\0')
11457c478bd9Sstevel@tonic-gate 			*p++ = '\0';
11467c478bd9Sstevel@tonic-gate 	}
11477c478bd9Sstevel@tonic-gate 	if (map_p->dns_m_type < 0)
11487c478bd9Sstevel@tonic-gate 		syserr("dns map %s: missing -R type", map->map_mname);
11497c478bd9Sstevel@tonic-gate 	if (map->map_app != NULL)
11507c478bd9Sstevel@tonic-gate 		map->map_app = newstr(map->map_app);
11517c478bd9Sstevel@tonic-gate 	if (map->map_tapp != NULL)
11527c478bd9Sstevel@tonic-gate 		map->map_tapp = newstr(map->map_tapp);
11537c478bd9Sstevel@tonic-gate 
11547c478bd9Sstevel@tonic-gate 	/*
11557c478bd9Sstevel@tonic-gate 	**  Assumption: assert(sizeof int <= sizeof(ARBPTR_T));
11567c478bd9Sstevel@tonic-gate 	**  Even if this assumption is wrong, we use only one byte,
11577c478bd9Sstevel@tonic-gate 	**  so it doesn't really matter.
11587c478bd9Sstevel@tonic-gate 	*/
11597c478bd9Sstevel@tonic-gate 
11607c478bd9Sstevel@tonic-gate 	map->map_db1 = (ARBPTR_T) map_p;
11617c478bd9Sstevel@tonic-gate 	return true;
11627c478bd9Sstevel@tonic-gate }
11637c478bd9Sstevel@tonic-gate 
11647c478bd9Sstevel@tonic-gate /*
11657c478bd9Sstevel@tonic-gate **  DNS_MAP_LOOKUP -- perform dns map lookup.
11667c478bd9Sstevel@tonic-gate **
11677c478bd9Sstevel@tonic-gate **	Parameters:
11687c478bd9Sstevel@tonic-gate **		map -- pointer to MAP
11697c478bd9Sstevel@tonic-gate **		name -- name to lookup
11707c478bd9Sstevel@tonic-gate **		av -- arguments to interpolate into buf.
11717c478bd9Sstevel@tonic-gate **		statp -- pointer to status (EX_)
11727c478bd9Sstevel@tonic-gate **
11737c478bd9Sstevel@tonic-gate **	Returns:
11747c478bd9Sstevel@tonic-gate **		result of lookup if succeeded.
11757c478bd9Sstevel@tonic-gate **		NULL -- otherwise.
11767c478bd9Sstevel@tonic-gate */
11777c478bd9Sstevel@tonic-gate 
11787c478bd9Sstevel@tonic-gate char *
11797c478bd9Sstevel@tonic-gate dns_map_lookup(map, name, av, statp)
11807c478bd9Sstevel@tonic-gate 	MAP *map;
11817c478bd9Sstevel@tonic-gate 	char *name;
11827c478bd9Sstevel@tonic-gate 	char **av;
11837c478bd9Sstevel@tonic-gate 	int *statp;
11847c478bd9Sstevel@tonic-gate {
11857c478bd9Sstevel@tonic-gate #  if _FFR_DNSMAP_MULTI
11867c478bd9Sstevel@tonic-gate #   if _FFR_DNSMAP_MULTILIMIT
11877c478bd9Sstevel@tonic-gate 	int resnum = 0;
11887c478bd9Sstevel@tonic-gate #   endif /* _FFR_DNSMAP_MULTILIMIT */
11897c478bd9Sstevel@tonic-gate #  endif /* _FFR_DNSMAP_MULTI */
11907c478bd9Sstevel@tonic-gate 	char *vp = NULL, *result = NULL;
11917c478bd9Sstevel@tonic-gate 	size_t vsize;
11927c478bd9Sstevel@tonic-gate 	struct dns_map *map_p;
11937c478bd9Sstevel@tonic-gate 	RESOURCE_RECORD_T *rr = NULL;
11947c478bd9Sstevel@tonic-gate 	DNS_REPLY_T *r = NULL;
11957c478bd9Sstevel@tonic-gate #  if NETINET6
11967c478bd9Sstevel@tonic-gate 	static char buf6[INET6_ADDRSTRLEN];
11977c478bd9Sstevel@tonic-gate #  endif /* NETINET6 */
11987c478bd9Sstevel@tonic-gate 
11997c478bd9Sstevel@tonic-gate 	if (tTd(38, 20))
12007c478bd9Sstevel@tonic-gate 		sm_dprintf("dns_map_lookup(%s, %s)\n",
12017c478bd9Sstevel@tonic-gate 			   map->map_mname, name);
12027c478bd9Sstevel@tonic-gate 
12037c478bd9Sstevel@tonic-gate 	map_p = (struct dns_map *)(map->map_db1);
12047c478bd9Sstevel@tonic-gate #  if _FFR_DNSMAP_BASE
12057c478bd9Sstevel@tonic-gate 	if (map->map_file != NULL && *map->map_file != '\0')
12067c478bd9Sstevel@tonic-gate 	{
12077c478bd9Sstevel@tonic-gate 		size_t len;
12087c478bd9Sstevel@tonic-gate 		char *appdomain;
12097c478bd9Sstevel@tonic-gate 
12107c478bd9Sstevel@tonic-gate 		len = strlen(map->map_file) + strlen(name) + 2;
12117c478bd9Sstevel@tonic-gate 		appdomain = (char *) sm_malloc(len);
12127c478bd9Sstevel@tonic-gate 		if (appdomain == NULL)
12137c478bd9Sstevel@tonic-gate 		{
12147c478bd9Sstevel@tonic-gate 			*statp = EX_UNAVAILABLE;
12157c478bd9Sstevel@tonic-gate 			return NULL;
12167c478bd9Sstevel@tonic-gate 		}
12177c478bd9Sstevel@tonic-gate 		(void) sm_strlcpyn(appdomain, len, 3, name, ".", map->map_file);
12187c478bd9Sstevel@tonic-gate 		r = dns_lookup_int(appdomain, C_IN, map_p->dns_m_type,
12197c478bd9Sstevel@tonic-gate 				   map->map_timeout, map->map_retry);
12207c478bd9Sstevel@tonic-gate 		sm_free(appdomain);
12217c478bd9Sstevel@tonic-gate 	}
12227c478bd9Sstevel@tonic-gate 	else
12237c478bd9Sstevel@tonic-gate #  endif /* _FFR_DNSMAP_BASE */
12247c478bd9Sstevel@tonic-gate 	{
12257c478bd9Sstevel@tonic-gate 		r = dns_lookup_int(name, C_IN, map_p->dns_m_type,
12267c478bd9Sstevel@tonic-gate 				   map->map_timeout, map->map_retry);
12277c478bd9Sstevel@tonic-gate 	}
12287c478bd9Sstevel@tonic-gate 
12297c478bd9Sstevel@tonic-gate 	if (r == NULL)
12307c478bd9Sstevel@tonic-gate 	{
12317c478bd9Sstevel@tonic-gate 		result = NULL;
12327c478bd9Sstevel@tonic-gate 		if (h_errno == TRY_AGAIN || transienterror(errno))
12337c478bd9Sstevel@tonic-gate 			*statp = EX_TEMPFAIL;
12347c478bd9Sstevel@tonic-gate 		else
12357c478bd9Sstevel@tonic-gate 			*statp = EX_NOTFOUND;
12367c478bd9Sstevel@tonic-gate 		goto cleanup;
12377c478bd9Sstevel@tonic-gate 	}
12387c478bd9Sstevel@tonic-gate 	*statp = EX_OK;
12397c478bd9Sstevel@tonic-gate 	for (rr = r->dns_r_head; rr != NULL; rr = rr->rr_next)
12407c478bd9Sstevel@tonic-gate 	{
12417c478bd9Sstevel@tonic-gate 		char *type = NULL;
12427c478bd9Sstevel@tonic-gate 		char *value = NULL;
12437c478bd9Sstevel@tonic-gate 
12447c478bd9Sstevel@tonic-gate 		switch (rr->rr_type)
12457c478bd9Sstevel@tonic-gate 		{
12467c478bd9Sstevel@tonic-gate 		  case T_NS:
12477c478bd9Sstevel@tonic-gate 			type = "T_NS";
12487c478bd9Sstevel@tonic-gate 			value = rr->rr_u.rr_txt;
12497c478bd9Sstevel@tonic-gate 			break;
12507c478bd9Sstevel@tonic-gate 		  case T_CNAME:
12517c478bd9Sstevel@tonic-gate 			type = "T_CNAME";
12527c478bd9Sstevel@tonic-gate 			value = rr->rr_u.rr_txt;
12537c478bd9Sstevel@tonic-gate 			break;
12547c478bd9Sstevel@tonic-gate 		  case T_AFSDB:
12557c478bd9Sstevel@tonic-gate 			type = "T_AFSDB";
12567c478bd9Sstevel@tonic-gate 			value = rr->rr_u.rr_mx->mx_r_domain;
12577c478bd9Sstevel@tonic-gate 			break;
12587c478bd9Sstevel@tonic-gate 		  case T_SRV:
12597c478bd9Sstevel@tonic-gate 			type = "T_SRV";
12607c478bd9Sstevel@tonic-gate 			value = rr->rr_u.rr_srv->srv_r_target;
12617c478bd9Sstevel@tonic-gate 			break;
12627c478bd9Sstevel@tonic-gate 		  case T_PTR:
12637c478bd9Sstevel@tonic-gate 			type = "T_PTR";
12647c478bd9Sstevel@tonic-gate 			value = rr->rr_u.rr_txt;
12657c478bd9Sstevel@tonic-gate 			break;
12667c478bd9Sstevel@tonic-gate 		  case T_TXT:
12677c478bd9Sstevel@tonic-gate 			type = "T_TXT";
12687c478bd9Sstevel@tonic-gate 			value = rr->rr_u.rr_txt;
12697c478bd9Sstevel@tonic-gate 			break;
12707c478bd9Sstevel@tonic-gate 		  case T_MX:
12717c478bd9Sstevel@tonic-gate 			type = "T_MX";
12727c478bd9Sstevel@tonic-gate 			value = rr->rr_u.rr_mx->mx_r_domain;
12737c478bd9Sstevel@tonic-gate 			break;
12747c478bd9Sstevel@tonic-gate #  if NETINET
12757c478bd9Sstevel@tonic-gate 		  case T_A:
12767c478bd9Sstevel@tonic-gate 			type = "T_A";
12777c478bd9Sstevel@tonic-gate 			value = inet_ntoa(*(rr->rr_u.rr_a));
12787c478bd9Sstevel@tonic-gate 			break;
12797c478bd9Sstevel@tonic-gate #  endif /* NETINET */
12807c478bd9Sstevel@tonic-gate #  if NETINET6
12817c478bd9Sstevel@tonic-gate 		  case T_AAAA:
12827c478bd9Sstevel@tonic-gate 			type = "T_AAAA";
12837c478bd9Sstevel@tonic-gate 			value = anynet_ntop(rr->rr_u.rr_aaaa, buf6,
12847c478bd9Sstevel@tonic-gate 					    sizeof buf6);
12857c478bd9Sstevel@tonic-gate 			break;
12867c478bd9Sstevel@tonic-gate #  endif /* NETINET6 */
12877c478bd9Sstevel@tonic-gate 		}
12887c478bd9Sstevel@tonic-gate 
12897c478bd9Sstevel@tonic-gate 		(void) strreplnonprt(value, 'X');
12907c478bd9Sstevel@tonic-gate 		if (map_p->dns_m_type != rr->rr_type)
12917c478bd9Sstevel@tonic-gate 		{
12927c478bd9Sstevel@tonic-gate 			if (tTd(38, 40))
12937c478bd9Sstevel@tonic-gate 				sm_dprintf("\tskipping type %s (%d) value %s\n",
12947c478bd9Sstevel@tonic-gate 					   type != NULL ? type : "<UNKNOWN>",
12957c478bd9Sstevel@tonic-gate 					   rr->rr_type,
12967c478bd9Sstevel@tonic-gate 					   value != NULL ? value : "<NO VALUE>");
12977c478bd9Sstevel@tonic-gate 			continue;
12987c478bd9Sstevel@tonic-gate 		}
12997c478bd9Sstevel@tonic-gate 
13007c478bd9Sstevel@tonic-gate #  if NETINET6
13017c478bd9Sstevel@tonic-gate 		if (rr->rr_type == T_AAAA && value == NULL)
13027c478bd9Sstevel@tonic-gate 		{
13037c478bd9Sstevel@tonic-gate 			result = NULL;
13047c478bd9Sstevel@tonic-gate 			*statp = EX_DATAERR;
13057c478bd9Sstevel@tonic-gate 			if (tTd(38, 40))
13067c478bd9Sstevel@tonic-gate 				sm_dprintf("\tbad T_AAAA conversion\n");
13077c478bd9Sstevel@tonic-gate 			goto cleanup;
13087c478bd9Sstevel@tonic-gate 		}
13097c478bd9Sstevel@tonic-gate #  endif /* NETINET6 */
13107c478bd9Sstevel@tonic-gate 		if (tTd(38, 40))
13117c478bd9Sstevel@tonic-gate 			sm_dprintf("\tfound type %s (%d) value %s\n",
13127c478bd9Sstevel@tonic-gate 				   type != NULL ? type : "<UNKNOWN>",
13137c478bd9Sstevel@tonic-gate 				   rr->rr_type,
13147c478bd9Sstevel@tonic-gate 				   value != NULL ? value : "<NO VALUE>");
13157c478bd9Sstevel@tonic-gate #  if _FFR_DNSMAP_MULTI
13167c478bd9Sstevel@tonic-gate 		if (value != NULL &&
13177c478bd9Sstevel@tonic-gate 		    (map->map_coldelim == '\0' ||
13187c478bd9Sstevel@tonic-gate #   if _FFR_DNSMAP_MULTILIMIT
13197c478bd9Sstevel@tonic-gate 		     map->map_sizelimit == 1 ||
13207c478bd9Sstevel@tonic-gate #   endif /* _FFR_DNSMAP_MULTILIMIT */
13217c478bd9Sstevel@tonic-gate 		     bitset(MF_MATCHONLY, map->map_mflags)))
13227c478bd9Sstevel@tonic-gate 		{
13237c478bd9Sstevel@tonic-gate 			/* Only care about the first match */
13247c478bd9Sstevel@tonic-gate 			vp = newstr(value);
13257c478bd9Sstevel@tonic-gate 			break;
13267c478bd9Sstevel@tonic-gate 		}
13277c478bd9Sstevel@tonic-gate 		else if (vp == NULL)
13287c478bd9Sstevel@tonic-gate 		{
13297c478bd9Sstevel@tonic-gate 			/* First result */
13307c478bd9Sstevel@tonic-gate 			vp = newstr(value);
13317c478bd9Sstevel@tonic-gate 		}
13327c478bd9Sstevel@tonic-gate 		else
13337c478bd9Sstevel@tonic-gate 		{
13347c478bd9Sstevel@tonic-gate 			/* concatenate the results */
13357c478bd9Sstevel@tonic-gate 			int sz;
13367c478bd9Sstevel@tonic-gate 			char *new;
13377c478bd9Sstevel@tonic-gate 
13387c478bd9Sstevel@tonic-gate 			sz = strlen(vp) + strlen(value) + 2;
13397c478bd9Sstevel@tonic-gate 			new = xalloc(sz);
13407c478bd9Sstevel@tonic-gate 			(void) sm_snprintf(new, sz, "%s%c%s",
13417c478bd9Sstevel@tonic-gate 					   vp, map->map_coldelim, value);
13427c478bd9Sstevel@tonic-gate 			sm_free(vp);
13437c478bd9Sstevel@tonic-gate 			vp = new;
13447c478bd9Sstevel@tonic-gate #   if _FFR_DNSMAP_MULTILIMIT
13457c478bd9Sstevel@tonic-gate 			if (map->map_sizelimit > 0 &&
13467c478bd9Sstevel@tonic-gate 			    ++resnum >= map->map_sizelimit)
13477c478bd9Sstevel@tonic-gate 				break;
13487c478bd9Sstevel@tonic-gate #   endif /* _FFR_DNSMAP_MULTILIMIT */
13497c478bd9Sstevel@tonic-gate 		}
13507c478bd9Sstevel@tonic-gate #  else /* _FFR_DNSMAP_MULTI */
13517c478bd9Sstevel@tonic-gate 		vp = value;
13527c478bd9Sstevel@tonic-gate 		break;
13537c478bd9Sstevel@tonic-gate #  endif /* _FFR_DNSMAP_MULTI */
13547c478bd9Sstevel@tonic-gate 	}
13557c478bd9Sstevel@tonic-gate 	if (vp == NULL)
13567c478bd9Sstevel@tonic-gate 	{
13577c478bd9Sstevel@tonic-gate 		result = NULL;
13587c478bd9Sstevel@tonic-gate 		*statp = EX_NOTFOUND;
13597c478bd9Sstevel@tonic-gate 		if (tTd(38, 40))
13607c478bd9Sstevel@tonic-gate 			sm_dprintf("\tno match found\n");
13617c478bd9Sstevel@tonic-gate 		goto cleanup;
13627c478bd9Sstevel@tonic-gate 	}
13637c478bd9Sstevel@tonic-gate 
13647c478bd9Sstevel@tonic-gate #  if _FFR_DNSMAP_MULTI
13657c478bd9Sstevel@tonic-gate 	/* Cleanly truncate for rulesets */
13667c478bd9Sstevel@tonic-gate 	truncate_at_delim(vp, PSBUFSIZE / 2, map->map_coldelim);
13677c478bd9Sstevel@tonic-gate #  endif /* _FFR_DNSMAP_MULTI */
13687c478bd9Sstevel@tonic-gate 
13697c478bd9Sstevel@tonic-gate 	vsize = strlen(vp);
13707c478bd9Sstevel@tonic-gate 
13717c478bd9Sstevel@tonic-gate 	if (LogLevel > 9)
13727c478bd9Sstevel@tonic-gate 		sm_syslog(LOG_INFO, CurEnv->e_id, "dns %.100s => %s",
13737c478bd9Sstevel@tonic-gate 			  name, vp);
13747c478bd9Sstevel@tonic-gate 	if (bitset(MF_MATCHONLY, map->map_mflags))
13757c478bd9Sstevel@tonic-gate 		result = map_rewrite(map, name, strlen(name), NULL);
13767c478bd9Sstevel@tonic-gate 	else
13777c478bd9Sstevel@tonic-gate 		result = map_rewrite(map, vp, vsize, av);
13787c478bd9Sstevel@tonic-gate 
13797c478bd9Sstevel@tonic-gate   cleanup:
13807c478bd9Sstevel@tonic-gate #  if _FFR_DNSMAP_MULTI
13817c478bd9Sstevel@tonic-gate 	if (vp != NULL)
13827c478bd9Sstevel@tonic-gate 		sm_free(vp);
13837c478bd9Sstevel@tonic-gate #  endif /* _FFR_DNSMAP_MULTI */
13847c478bd9Sstevel@tonic-gate 	if (r != NULL)
13857c478bd9Sstevel@tonic-gate 		dns_free_data(r);
13867c478bd9Sstevel@tonic-gate 	return result;
13877c478bd9Sstevel@tonic-gate }
13887c478bd9Sstevel@tonic-gate # endif /* DNSMAP */
13897c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */
13907c478bd9Sstevel@tonic-gate 
13917c478bd9Sstevel@tonic-gate /*
13927c478bd9Sstevel@tonic-gate **  NDBM modules
13937c478bd9Sstevel@tonic-gate */
13947c478bd9Sstevel@tonic-gate 
13957c478bd9Sstevel@tonic-gate #if NDBM
13967c478bd9Sstevel@tonic-gate 
13977c478bd9Sstevel@tonic-gate /*
13987c478bd9Sstevel@tonic-gate **  NDBM_MAP_OPEN -- DBM-style map open
13997c478bd9Sstevel@tonic-gate */
14007c478bd9Sstevel@tonic-gate 
14017c478bd9Sstevel@tonic-gate bool
14027c478bd9Sstevel@tonic-gate ndbm_map_open(map, mode)
14037c478bd9Sstevel@tonic-gate 	MAP *map;
14047c478bd9Sstevel@tonic-gate 	int mode;
14057c478bd9Sstevel@tonic-gate {
14067c478bd9Sstevel@tonic-gate 	register DBM *dbm;
14077c478bd9Sstevel@tonic-gate 	int save_errno;
14087c478bd9Sstevel@tonic-gate 	int dfd;
14097c478bd9Sstevel@tonic-gate 	int pfd;
14107c478bd9Sstevel@tonic-gate 	long sff;
14117c478bd9Sstevel@tonic-gate 	int ret;
14127c478bd9Sstevel@tonic-gate 	int smode = S_IREAD;
14137c478bd9Sstevel@tonic-gate 	char dirfile[MAXPATHLEN];
14147c478bd9Sstevel@tonic-gate 	char pagfile[MAXPATHLEN];
14157c478bd9Sstevel@tonic-gate 	struct stat st;
14167c478bd9Sstevel@tonic-gate 	struct stat std, stp;
14177c478bd9Sstevel@tonic-gate 
14187c478bd9Sstevel@tonic-gate 	if (tTd(38, 2))
14197c478bd9Sstevel@tonic-gate 		sm_dprintf("ndbm_map_open(%s, %s, %d)\n",
14207c478bd9Sstevel@tonic-gate 			map->map_mname, map->map_file, mode);
14217c478bd9Sstevel@tonic-gate 	map->map_lockfd = -1;
14227c478bd9Sstevel@tonic-gate 	mode &= O_ACCMODE;
14237c478bd9Sstevel@tonic-gate 
14247c478bd9Sstevel@tonic-gate 	/* do initial file and directory checks */
14257c478bd9Sstevel@tonic-gate 	if (sm_strlcpyn(dirfile, sizeof dirfile, 2,
14267c478bd9Sstevel@tonic-gate 			map->map_file, ".dir") >= sizeof dirfile ||
14277c478bd9Sstevel@tonic-gate 	    sm_strlcpyn(pagfile, sizeof pagfile, 2,
14287c478bd9Sstevel@tonic-gate 			map->map_file, ".pag") >= sizeof pagfile)
14297c478bd9Sstevel@tonic-gate 	{
14307c478bd9Sstevel@tonic-gate 		errno = 0;
14317c478bd9Sstevel@tonic-gate 		if (!bitset(MF_OPTIONAL, map->map_mflags))
14327c478bd9Sstevel@tonic-gate 			syserr("dbm map \"%s\": map file %s name too long",
14337c478bd9Sstevel@tonic-gate 				map->map_mname, map->map_file);
14347c478bd9Sstevel@tonic-gate 		return false;
14357c478bd9Sstevel@tonic-gate 	}
14367c478bd9Sstevel@tonic-gate 	sff = SFF_ROOTOK|SFF_REGONLY;
14377c478bd9Sstevel@tonic-gate 	if (mode == O_RDWR)
14387c478bd9Sstevel@tonic-gate 	{
14397c478bd9Sstevel@tonic-gate 		sff |= SFF_CREAT;
14407c478bd9Sstevel@tonic-gate 		if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail))
14417c478bd9Sstevel@tonic-gate 			sff |= SFF_NOSLINK;
14427c478bd9Sstevel@tonic-gate 		if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail))
14437c478bd9Sstevel@tonic-gate 			sff |= SFF_NOHLINK;
14447c478bd9Sstevel@tonic-gate 		smode = S_IWRITE;
14457c478bd9Sstevel@tonic-gate 	}
14467c478bd9Sstevel@tonic-gate 	else
14477c478bd9Sstevel@tonic-gate 	{
14487c478bd9Sstevel@tonic-gate 		if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail))
14497c478bd9Sstevel@tonic-gate 			sff |= SFF_NOWLINK;
14507c478bd9Sstevel@tonic-gate 	}
14517c478bd9Sstevel@tonic-gate 	if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail))
14527c478bd9Sstevel@tonic-gate 		sff |= SFF_SAFEDIRPATH;
14537c478bd9Sstevel@tonic-gate 	ret = safefile(dirfile, RunAsUid, RunAsGid, RunAsUserName,
14547c478bd9Sstevel@tonic-gate 		       sff, smode, &std);
14557c478bd9Sstevel@tonic-gate 	if (ret == 0)
14567c478bd9Sstevel@tonic-gate 		ret = safefile(pagfile, RunAsUid, RunAsGid, RunAsUserName,
14577c478bd9Sstevel@tonic-gate 			       sff, smode, &stp);
14587c478bd9Sstevel@tonic-gate 
14597c478bd9Sstevel@tonic-gate 	if (ret != 0)
14607c478bd9Sstevel@tonic-gate 	{
14617c478bd9Sstevel@tonic-gate 		char *prob = "unsafe";
14627c478bd9Sstevel@tonic-gate 
14637c478bd9Sstevel@tonic-gate 		/* cannot open this map */
14647c478bd9Sstevel@tonic-gate 		if (ret == ENOENT)
14657c478bd9Sstevel@tonic-gate 			prob = "missing";
14667c478bd9Sstevel@tonic-gate 		if (tTd(38, 2))
14677c478bd9Sstevel@tonic-gate 			sm_dprintf("\t%s map file: %d\n", prob, ret);
14687c478bd9Sstevel@tonic-gate 		if (!bitset(MF_OPTIONAL, map->map_mflags))
14697c478bd9Sstevel@tonic-gate 			syserr("dbm map \"%s\": %s map file %s",
14707c478bd9Sstevel@tonic-gate 				map->map_mname, prob, map->map_file);
14717c478bd9Sstevel@tonic-gate 		return false;
14727c478bd9Sstevel@tonic-gate 	}
14737c478bd9Sstevel@tonic-gate 	if (std.st_mode == ST_MODE_NOFILE)
14747c478bd9Sstevel@tonic-gate 		mode |= O_CREAT|O_EXCL;
14757c478bd9Sstevel@tonic-gate 
14767c478bd9Sstevel@tonic-gate # if LOCK_ON_OPEN
14777c478bd9Sstevel@tonic-gate 	if (mode == O_RDONLY)
14787c478bd9Sstevel@tonic-gate 		mode |= O_SHLOCK;
14797c478bd9Sstevel@tonic-gate 	else
14807c478bd9Sstevel@tonic-gate 		mode |= O_TRUNC|O_EXLOCK;
14817c478bd9Sstevel@tonic-gate # else /* LOCK_ON_OPEN */
14827c478bd9Sstevel@tonic-gate 	if ((mode & O_ACCMODE) == O_RDWR)
14837c478bd9Sstevel@tonic-gate 	{
14847c478bd9Sstevel@tonic-gate #  if NOFTRUNCATE
14857c478bd9Sstevel@tonic-gate 		/*
14867c478bd9Sstevel@tonic-gate 		**  Warning: race condition.  Try to lock the file as
14877c478bd9Sstevel@tonic-gate 		**  quickly as possible after opening it.
14887c478bd9Sstevel@tonic-gate 		**	This may also have security problems on some systems,
14897c478bd9Sstevel@tonic-gate 		**	but there isn't anything we can do about it.
14907c478bd9Sstevel@tonic-gate 		*/
14917c478bd9Sstevel@tonic-gate 
14927c478bd9Sstevel@tonic-gate 		mode |= O_TRUNC;
14937c478bd9Sstevel@tonic-gate #  else /* NOFTRUNCATE */
14947c478bd9Sstevel@tonic-gate 		/*
14957c478bd9Sstevel@tonic-gate 		**  This ugly code opens the map without truncating it,
14967c478bd9Sstevel@tonic-gate 		**  locks the file, then truncates it.  Necessary to
14977c478bd9Sstevel@tonic-gate 		**  avoid race conditions.
14987c478bd9Sstevel@tonic-gate 		*/
14997c478bd9Sstevel@tonic-gate 
15007c478bd9Sstevel@tonic-gate 		int dirfd;
15017c478bd9Sstevel@tonic-gate 		int pagfd;
15027c478bd9Sstevel@tonic-gate 		long sff = SFF_CREAT|SFF_OPENASROOT;
15037c478bd9Sstevel@tonic-gate 
15047c478bd9Sstevel@tonic-gate 		if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail))
15057c478bd9Sstevel@tonic-gate 			sff |= SFF_NOSLINK;
15067c478bd9Sstevel@tonic-gate 		if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail))
15077c478bd9Sstevel@tonic-gate 			sff |= SFF_NOHLINK;
15087c478bd9Sstevel@tonic-gate 
15097c478bd9Sstevel@tonic-gate 		dirfd = safeopen(dirfile, mode, DBMMODE, sff);
15107c478bd9Sstevel@tonic-gate 		pagfd = safeopen(pagfile, mode, DBMMODE, sff);
15117c478bd9Sstevel@tonic-gate 
15127c478bd9Sstevel@tonic-gate 		if (dirfd < 0 || pagfd < 0)
15137c478bd9Sstevel@tonic-gate 		{
15147c478bd9Sstevel@tonic-gate 			save_errno = errno;
15157c478bd9Sstevel@tonic-gate 			if (dirfd >= 0)
15167c478bd9Sstevel@tonic-gate 				(void) close(dirfd);
15177c478bd9Sstevel@tonic-gate 			if (pagfd >= 0)
15187c478bd9Sstevel@tonic-gate 				(void) close(pagfd);
15197c478bd9Sstevel@tonic-gate 			errno = save_errno;
15207c478bd9Sstevel@tonic-gate 			syserr("ndbm_map_open: cannot create database %s",
15217c478bd9Sstevel@tonic-gate 				map->map_file);
15227c478bd9Sstevel@tonic-gate 			return false;
15237c478bd9Sstevel@tonic-gate 		}
15247c478bd9Sstevel@tonic-gate 		if (ftruncate(dirfd, (off_t) 0) < 0 ||
15257c478bd9Sstevel@tonic-gate 		    ftruncate(pagfd, (off_t) 0) < 0)
15267c478bd9Sstevel@tonic-gate 		{
15277c478bd9Sstevel@tonic-gate 			save_errno = errno;
15287c478bd9Sstevel@tonic-gate 			(void) close(dirfd);
15297c478bd9Sstevel@tonic-gate 			(void) close(pagfd);
15307c478bd9Sstevel@tonic-gate 			errno = save_errno;
15317c478bd9Sstevel@tonic-gate 			syserr("ndbm_map_open: cannot truncate %s.{dir,pag}",
15327c478bd9Sstevel@tonic-gate 				map->map_file);
15337c478bd9Sstevel@tonic-gate 			return false;
15347c478bd9Sstevel@tonic-gate 		}
15357c478bd9Sstevel@tonic-gate 
15367c478bd9Sstevel@tonic-gate 		/* if new file, get "before" bits for later filechanged check */
15377c478bd9Sstevel@tonic-gate 		if (std.st_mode == ST_MODE_NOFILE &&
15387c478bd9Sstevel@tonic-gate 		    (fstat(dirfd, &std) < 0 || fstat(pagfd, &stp) < 0))
15397c478bd9Sstevel@tonic-gate 		{
15407c478bd9Sstevel@tonic-gate 			save_errno = errno;
15417c478bd9Sstevel@tonic-gate 			(void) close(dirfd);
15427c478bd9Sstevel@tonic-gate 			(void) close(pagfd);
15437c478bd9Sstevel@tonic-gate 			errno = save_errno;
15447c478bd9Sstevel@tonic-gate 			syserr("ndbm_map_open(%s.{dir,pag}): cannot fstat pre-opened file",
15457c478bd9Sstevel@tonic-gate 				map->map_file);
15467c478bd9Sstevel@tonic-gate 			return false;
15477c478bd9Sstevel@tonic-gate 		}
15487c478bd9Sstevel@tonic-gate 
15497c478bd9Sstevel@tonic-gate 		/* have to save the lock for the duration (bletch) */
15507c478bd9Sstevel@tonic-gate 		map->map_lockfd = dirfd;
15517c478bd9Sstevel@tonic-gate 		(void) close(pagfd);
15527c478bd9Sstevel@tonic-gate 
15537c478bd9Sstevel@tonic-gate 		/* twiddle bits for dbm_open */
15547c478bd9Sstevel@tonic-gate 		mode &= ~(O_CREAT|O_EXCL);
15557c478bd9Sstevel@tonic-gate #  endif /* NOFTRUNCATE */
15567c478bd9Sstevel@tonic-gate 	}
15577c478bd9Sstevel@tonic-gate # endif /* LOCK_ON_OPEN */
15587c478bd9Sstevel@tonic-gate 
15597c478bd9Sstevel@tonic-gate 	/* open the database */
15607c478bd9Sstevel@tonic-gate 	dbm = dbm_open(map->map_file, mode, DBMMODE);
15617c478bd9Sstevel@tonic-gate 	if (dbm == NULL)
15627c478bd9Sstevel@tonic-gate 	{
15637c478bd9Sstevel@tonic-gate 		save_errno = errno;
15647c478bd9Sstevel@tonic-gate 		if (bitset(MF_ALIAS, map->map_mflags) &&
15657c478bd9Sstevel@tonic-gate 		    aliaswait(map, ".pag", false))
15667c478bd9Sstevel@tonic-gate 			return true;
15677c478bd9Sstevel@tonic-gate # if !LOCK_ON_OPEN && !NOFTRUNCATE
15687c478bd9Sstevel@tonic-gate 		if (map->map_lockfd >= 0)
15697c478bd9Sstevel@tonic-gate 			(void) close(map->map_lockfd);
15707c478bd9Sstevel@tonic-gate # endif /* !LOCK_ON_OPEN && !NOFTRUNCATE */
15717c478bd9Sstevel@tonic-gate 		errno = save_errno;
15727c478bd9Sstevel@tonic-gate 		if (!bitset(MF_OPTIONAL, map->map_mflags))
15737c478bd9Sstevel@tonic-gate 			syserr("Cannot open DBM database %s", map->map_file);
15747c478bd9Sstevel@tonic-gate 		return false;
15757c478bd9Sstevel@tonic-gate 	}
15767c478bd9Sstevel@tonic-gate 	dfd = dbm_dirfno(dbm);
15777c478bd9Sstevel@tonic-gate 	pfd = dbm_pagfno(dbm);
15787c478bd9Sstevel@tonic-gate 	if (dfd == pfd)
15797c478bd9Sstevel@tonic-gate 	{
15807c478bd9Sstevel@tonic-gate 		/* heuristic: if files are linked, this is actually gdbm */
15817c478bd9Sstevel@tonic-gate 		dbm_close(dbm);
15827c478bd9Sstevel@tonic-gate # if !LOCK_ON_OPEN && !NOFTRUNCATE
15837c478bd9Sstevel@tonic-gate 		if (map->map_lockfd >= 0)
15847c478bd9Sstevel@tonic-gate 			(void) close(map->map_lockfd);
15857c478bd9Sstevel@tonic-gate # endif /* !LOCK_ON_OPEN && !NOFTRUNCATE */
15867c478bd9Sstevel@tonic-gate 		errno = 0;
15877c478bd9Sstevel@tonic-gate 		syserr("dbm map \"%s\": cannot support GDBM",
15887c478bd9Sstevel@tonic-gate 			map->map_mname);
15897c478bd9Sstevel@tonic-gate 		return false;
15907c478bd9Sstevel@tonic-gate 	}
15917c478bd9Sstevel@tonic-gate 
15927c478bd9Sstevel@tonic-gate 	if (filechanged(dirfile, dfd, &std) ||
15937c478bd9Sstevel@tonic-gate 	    filechanged(pagfile, pfd, &stp))
15947c478bd9Sstevel@tonic-gate 	{
15957c478bd9Sstevel@tonic-gate 		save_errno = errno;
15967c478bd9Sstevel@tonic-gate 		dbm_close(dbm);
15977c478bd9Sstevel@tonic-gate # if !LOCK_ON_OPEN && !NOFTRUNCATE
15987c478bd9Sstevel@tonic-gate 		if (map->map_lockfd >= 0)
15997c478bd9Sstevel@tonic-gate 			(void) close(map->map_lockfd);
16007c478bd9Sstevel@tonic-gate # endif /* !LOCK_ON_OPEN && !NOFTRUNCATE */
16017c478bd9Sstevel@tonic-gate 		errno = save_errno;
16027c478bd9Sstevel@tonic-gate 		syserr("ndbm_map_open(%s): file changed after open",
16037c478bd9Sstevel@tonic-gate 			map->map_file);
16047c478bd9Sstevel@tonic-gate 		return false;
16057c478bd9Sstevel@tonic-gate 	}
16067c478bd9Sstevel@tonic-gate 
16077c478bd9Sstevel@tonic-gate 	map->map_db1 = (ARBPTR_T) dbm;
16087c478bd9Sstevel@tonic-gate 
16097c478bd9Sstevel@tonic-gate 	/*
16107c478bd9Sstevel@tonic-gate 	**  Need to set map_mtime before the call to aliaswait()
16117c478bd9Sstevel@tonic-gate 	**  as aliaswait() will call map_lookup() which requires
16127c478bd9Sstevel@tonic-gate 	**  map_mtime to be set
16137c478bd9Sstevel@tonic-gate 	*/
16147c478bd9Sstevel@tonic-gate 
16157c478bd9Sstevel@tonic-gate 	if (fstat(pfd, &st) >= 0)
16167c478bd9Sstevel@tonic-gate 		map->map_mtime = st.st_mtime;
16177c478bd9Sstevel@tonic-gate 
16187c478bd9Sstevel@tonic-gate 	if (mode == O_RDONLY)
16197c478bd9Sstevel@tonic-gate 	{
16207c478bd9Sstevel@tonic-gate # if LOCK_ON_OPEN
16217c478bd9Sstevel@tonic-gate 		if (dfd >= 0)
16227c478bd9Sstevel@tonic-gate 			(void) lockfile(dfd, map->map_file, ".dir", LOCK_UN);
16237c478bd9Sstevel@tonic-gate 		if (pfd >= 0)
16247c478bd9Sstevel@tonic-gate 			(void) lockfile(pfd, map->map_file, ".pag", LOCK_UN);
16257c478bd9Sstevel@tonic-gate # endif /* LOCK_ON_OPEN */
16267c478bd9Sstevel@tonic-gate 		if (bitset(MF_ALIAS, map->map_mflags) &&
16277c478bd9Sstevel@tonic-gate 		    !aliaswait(map, ".pag", true))
16287c478bd9Sstevel@tonic-gate 			return false;
16297c478bd9Sstevel@tonic-gate 	}
16307c478bd9Sstevel@tonic-gate 	else
16317c478bd9Sstevel@tonic-gate 	{
16327c478bd9Sstevel@tonic-gate 		map->map_mflags |= MF_LOCKED;
16337c478bd9Sstevel@tonic-gate 		if (geteuid() == 0 && TrustedUid != 0)
16347c478bd9Sstevel@tonic-gate 		{
16357c478bd9Sstevel@tonic-gate #  if HASFCHOWN
16367c478bd9Sstevel@tonic-gate 			if (fchown(dfd, TrustedUid, -1) < 0 ||
16377c478bd9Sstevel@tonic-gate 			    fchown(pfd, TrustedUid, -1) < 0)
16387c478bd9Sstevel@tonic-gate 			{
16397c478bd9Sstevel@tonic-gate 				int err = errno;
16407c478bd9Sstevel@tonic-gate 
16417c478bd9Sstevel@tonic-gate 				sm_syslog(LOG_ALERT, NOQID,
16427c478bd9Sstevel@tonic-gate 					  "ownership change on %s failed: %s",
16437c478bd9Sstevel@tonic-gate 					  map->map_file, sm_errstring(err));
16447c478bd9Sstevel@tonic-gate 				message("050 ownership change on %s failed: %s",
16457c478bd9Sstevel@tonic-gate 					map->map_file, sm_errstring(err));
16467c478bd9Sstevel@tonic-gate 			}
16477c478bd9Sstevel@tonic-gate #  else /* HASFCHOWN */
16487c478bd9Sstevel@tonic-gate 			sm_syslog(LOG_ALERT, NOQID,
16497c478bd9Sstevel@tonic-gate 				  "no fchown(): cannot change ownership on %s",
16507c478bd9Sstevel@tonic-gate 				  map->map_file);
16517c478bd9Sstevel@tonic-gate 			message("050 no fchown(): cannot change ownership on %s",
16527c478bd9Sstevel@tonic-gate 				map->map_file);
16537c478bd9Sstevel@tonic-gate #  endif /* HASFCHOWN */
16547c478bd9Sstevel@tonic-gate 		}
16557c478bd9Sstevel@tonic-gate 	}
16567c478bd9Sstevel@tonic-gate 	return true;
16577c478bd9Sstevel@tonic-gate }
16587c478bd9Sstevel@tonic-gate 
16597c478bd9Sstevel@tonic-gate 
16607c478bd9Sstevel@tonic-gate /*
16617c478bd9Sstevel@tonic-gate **  NDBM_MAP_LOOKUP -- look up a datum in a DBM-type map
16627c478bd9Sstevel@tonic-gate */
16637c478bd9Sstevel@tonic-gate 
16647c478bd9Sstevel@tonic-gate char *
16657c478bd9Sstevel@tonic-gate ndbm_map_lookup(map, name, av, statp)
16667c478bd9Sstevel@tonic-gate 	MAP *map;
16677c478bd9Sstevel@tonic-gate 	char *name;
16687c478bd9Sstevel@tonic-gate 	char **av;
16697c478bd9Sstevel@tonic-gate 	int *statp;
16707c478bd9Sstevel@tonic-gate {
16717c478bd9Sstevel@tonic-gate 	datum key, val;
16727c478bd9Sstevel@tonic-gate 	int dfd, pfd;
16737c478bd9Sstevel@tonic-gate 	char keybuf[MAXNAME + 1];
16747c478bd9Sstevel@tonic-gate 	struct stat stbuf;
16757c478bd9Sstevel@tonic-gate 
16767c478bd9Sstevel@tonic-gate 	if (tTd(38, 20))
16777c478bd9Sstevel@tonic-gate 		sm_dprintf("ndbm_map_lookup(%s, %s)\n",
16787c478bd9Sstevel@tonic-gate 			map->map_mname, name);
16797c478bd9Sstevel@tonic-gate 
16807c478bd9Sstevel@tonic-gate 	key.dptr = name;
16817c478bd9Sstevel@tonic-gate 	key.dsize = strlen(name);
16827c478bd9Sstevel@tonic-gate 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
16837c478bd9Sstevel@tonic-gate 	{
16847c478bd9Sstevel@tonic-gate 		if (key.dsize > sizeof keybuf - 1)
16857c478bd9Sstevel@tonic-gate 			key.dsize = sizeof keybuf - 1;
16867c478bd9Sstevel@tonic-gate 		memmove(keybuf, key.dptr, key.dsize);
16877c478bd9Sstevel@tonic-gate 		keybuf[key.dsize] = '\0';
16887c478bd9Sstevel@tonic-gate 		makelower(keybuf);
16897c478bd9Sstevel@tonic-gate 		key.dptr = keybuf;
16907c478bd9Sstevel@tonic-gate 	}
16917c478bd9Sstevel@tonic-gate lockdbm:
16927c478bd9Sstevel@tonic-gate 	dfd = dbm_dirfno((DBM *) map->map_db1);
16937c478bd9Sstevel@tonic-gate 	if (dfd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
16947c478bd9Sstevel@tonic-gate 		(void) lockfile(dfd, map->map_file, ".dir", LOCK_SH);
16957c478bd9Sstevel@tonic-gate 	pfd = dbm_pagfno((DBM *) map->map_db1);
16967c478bd9Sstevel@tonic-gate 	if (pfd < 0 || fstat(pfd, &stbuf) < 0 ||
16977c478bd9Sstevel@tonic-gate 	    stbuf.st_mtime > map->map_mtime)
16987c478bd9Sstevel@tonic-gate 	{
16997c478bd9Sstevel@tonic-gate 		/* Reopen the database to sync the cache */
17007c478bd9Sstevel@tonic-gate 		int omode = bitset(map->map_mflags, MF_WRITABLE) ? O_RDWR
17017c478bd9Sstevel@tonic-gate 								 : O_RDONLY;
17027c478bd9Sstevel@tonic-gate 
17037c478bd9Sstevel@tonic-gate 		if (dfd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
17047c478bd9Sstevel@tonic-gate 			(void) lockfile(dfd, map->map_file, ".dir", LOCK_UN);
17057c478bd9Sstevel@tonic-gate 		map->map_mflags |= MF_CLOSING;
17067c478bd9Sstevel@tonic-gate 		map->map_class->map_close(map);
17077c478bd9Sstevel@tonic-gate 		map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING);
17087c478bd9Sstevel@tonic-gate 		if (map->map_class->map_open(map, omode))
17097c478bd9Sstevel@tonic-gate 		{
17107c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_OPEN;
17117c478bd9Sstevel@tonic-gate 			map->map_pid = CurrentPid;
17127c478bd9Sstevel@tonic-gate 			if ((omode && O_ACCMODE) == O_RDWR)
17137c478bd9Sstevel@tonic-gate 				map->map_mflags |= MF_WRITABLE;
17147c478bd9Sstevel@tonic-gate 			goto lockdbm;
17157c478bd9Sstevel@tonic-gate 		}
17167c478bd9Sstevel@tonic-gate 		else
17177c478bd9Sstevel@tonic-gate 		{
17187c478bd9Sstevel@tonic-gate 			if (!bitset(MF_OPTIONAL, map->map_mflags))
17197c478bd9Sstevel@tonic-gate 			{
17207c478bd9Sstevel@tonic-gate 				extern MAPCLASS BogusMapClass;
17217c478bd9Sstevel@tonic-gate 
17227c478bd9Sstevel@tonic-gate 				*statp = EX_TEMPFAIL;
17237c478bd9Sstevel@tonic-gate 				map->map_orgclass = map->map_class;
17247c478bd9Sstevel@tonic-gate 				map->map_class = &BogusMapClass;
17257c478bd9Sstevel@tonic-gate 				map->map_mflags |= MF_OPEN;
17267c478bd9Sstevel@tonic-gate 				map->map_pid = CurrentPid;
17277c478bd9Sstevel@tonic-gate 				syserr("Cannot reopen NDBM database %s",
17287c478bd9Sstevel@tonic-gate 					map->map_file);
17297c478bd9Sstevel@tonic-gate 			}
17307c478bd9Sstevel@tonic-gate 			return NULL;
17317c478bd9Sstevel@tonic-gate 		}
17327c478bd9Sstevel@tonic-gate 	}
17337c478bd9Sstevel@tonic-gate 	val.dptr = NULL;
17347c478bd9Sstevel@tonic-gate 	if (bitset(MF_TRY0NULL, map->map_mflags))
17357c478bd9Sstevel@tonic-gate 	{
17367c478bd9Sstevel@tonic-gate 		val = dbm_fetch((DBM *) map->map_db1, key);
17377c478bd9Sstevel@tonic-gate 		if (val.dptr != NULL)
17387c478bd9Sstevel@tonic-gate 			map->map_mflags &= ~MF_TRY1NULL;
17397c478bd9Sstevel@tonic-gate 	}
17407c478bd9Sstevel@tonic-gate 	if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags))
17417c478bd9Sstevel@tonic-gate 	{
17427c478bd9Sstevel@tonic-gate 		key.dsize++;
17437c478bd9Sstevel@tonic-gate 		val = dbm_fetch((DBM *) map->map_db1, key);
17447c478bd9Sstevel@tonic-gate 		if (val.dptr != NULL)
17457c478bd9Sstevel@tonic-gate 			map->map_mflags &= ~MF_TRY0NULL;
17467c478bd9Sstevel@tonic-gate 	}
17477c478bd9Sstevel@tonic-gate 	if (dfd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
17487c478bd9Sstevel@tonic-gate 		(void) lockfile(dfd, map->map_file, ".dir", LOCK_UN);
17497c478bd9Sstevel@tonic-gate 	if (val.dptr == NULL)
17507c478bd9Sstevel@tonic-gate 		return NULL;
17517c478bd9Sstevel@tonic-gate 	if (bitset(MF_MATCHONLY, map->map_mflags))
17527c478bd9Sstevel@tonic-gate 		return map_rewrite(map, name, strlen(name), NULL);
17537c478bd9Sstevel@tonic-gate 	else
17547c478bd9Sstevel@tonic-gate 		return map_rewrite(map, val.dptr, val.dsize, av);
17557c478bd9Sstevel@tonic-gate }
17567c478bd9Sstevel@tonic-gate 
17577c478bd9Sstevel@tonic-gate 
17587c478bd9Sstevel@tonic-gate /*
17597c478bd9Sstevel@tonic-gate **  NDBM_MAP_STORE -- store a datum in the database
17607c478bd9Sstevel@tonic-gate */
17617c478bd9Sstevel@tonic-gate 
17627c478bd9Sstevel@tonic-gate void
17637c478bd9Sstevel@tonic-gate ndbm_map_store(map, lhs, rhs)
17647c478bd9Sstevel@tonic-gate 	register MAP *map;
17657c478bd9Sstevel@tonic-gate 	char *lhs;
17667c478bd9Sstevel@tonic-gate 	char *rhs;
17677c478bd9Sstevel@tonic-gate {
17687c478bd9Sstevel@tonic-gate 	datum key;
17697c478bd9Sstevel@tonic-gate 	datum data;
17707c478bd9Sstevel@tonic-gate 	int status;
17717c478bd9Sstevel@tonic-gate 	char keybuf[MAXNAME + 1];
17727c478bd9Sstevel@tonic-gate 
17737c478bd9Sstevel@tonic-gate 	if (tTd(38, 12))
17747c478bd9Sstevel@tonic-gate 		sm_dprintf("ndbm_map_store(%s, %s, %s)\n",
17757c478bd9Sstevel@tonic-gate 			map->map_mname, lhs, rhs);
17767c478bd9Sstevel@tonic-gate 
17777c478bd9Sstevel@tonic-gate 	key.dsize = strlen(lhs);
17787c478bd9Sstevel@tonic-gate 	key.dptr = lhs;
17797c478bd9Sstevel@tonic-gate 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
17807c478bd9Sstevel@tonic-gate 	{
17817c478bd9Sstevel@tonic-gate 		if (key.dsize > sizeof keybuf - 1)
17827c478bd9Sstevel@tonic-gate 			key.dsize = sizeof keybuf - 1;
17837c478bd9Sstevel@tonic-gate 		memmove(keybuf, key.dptr, key.dsize);
17847c478bd9Sstevel@tonic-gate 		keybuf[key.dsize] = '\0';
17857c478bd9Sstevel@tonic-gate 		makelower(keybuf);
17867c478bd9Sstevel@tonic-gate 		key.dptr = keybuf;
17877c478bd9Sstevel@tonic-gate 	}
17887c478bd9Sstevel@tonic-gate 
17897c478bd9Sstevel@tonic-gate 	data.dsize = strlen(rhs);
17907c478bd9Sstevel@tonic-gate 	data.dptr = rhs;
17917c478bd9Sstevel@tonic-gate 
17927c478bd9Sstevel@tonic-gate 	if (bitset(MF_INCLNULL, map->map_mflags))
17937c478bd9Sstevel@tonic-gate 	{
17947c478bd9Sstevel@tonic-gate 		key.dsize++;
17957c478bd9Sstevel@tonic-gate 		data.dsize++;
17967c478bd9Sstevel@tonic-gate 	}
17977c478bd9Sstevel@tonic-gate 
17987c478bd9Sstevel@tonic-gate 	status = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT);
17997c478bd9Sstevel@tonic-gate 	if (status > 0)
18007c478bd9Sstevel@tonic-gate 	{
18017c478bd9Sstevel@tonic-gate 		if (!bitset(MF_APPEND, map->map_mflags))
18027c478bd9Sstevel@tonic-gate 			message("050 Warning: duplicate alias name %s", lhs);
18037c478bd9Sstevel@tonic-gate 		else
18047c478bd9Sstevel@tonic-gate 		{
18057c478bd9Sstevel@tonic-gate 			static char *buf = NULL;
18067c478bd9Sstevel@tonic-gate 			static int bufsiz = 0;
18077c478bd9Sstevel@tonic-gate 			auto int xstat;
18087c478bd9Sstevel@tonic-gate 			datum old;
18097c478bd9Sstevel@tonic-gate 
18107c478bd9Sstevel@tonic-gate 			old.dptr = ndbm_map_lookup(map, key.dptr,
18117c478bd9Sstevel@tonic-gate 						   (char **) NULL, &xstat);
18127c478bd9Sstevel@tonic-gate 			if (old.dptr != NULL && *(char *) old.dptr != '\0')
18137c478bd9Sstevel@tonic-gate 			{
18147c478bd9Sstevel@tonic-gate 				old.dsize = strlen(old.dptr);
18157c478bd9Sstevel@tonic-gate 				if (data.dsize + old.dsize + 2 > bufsiz)
18167c478bd9Sstevel@tonic-gate 				{
18177c478bd9Sstevel@tonic-gate 					if (buf != NULL)
18187c478bd9Sstevel@tonic-gate 						(void) sm_free(buf);
18197c478bd9Sstevel@tonic-gate 					bufsiz = data.dsize + old.dsize + 2;
18207c478bd9Sstevel@tonic-gate 					buf = sm_pmalloc_x(bufsiz);
18217c478bd9Sstevel@tonic-gate 				}
18227c478bd9Sstevel@tonic-gate 				(void) sm_strlcpyn(buf, bufsiz, 3,
18237c478bd9Sstevel@tonic-gate 					data.dptr, ",", old.dptr);
18247c478bd9Sstevel@tonic-gate 				data.dsize = data.dsize + old.dsize + 1;
18257c478bd9Sstevel@tonic-gate 				data.dptr = buf;
18267c478bd9Sstevel@tonic-gate 				if (tTd(38, 9))
18277c478bd9Sstevel@tonic-gate 					sm_dprintf("ndbm_map_store append=%s\n",
18287c478bd9Sstevel@tonic-gate 						data.dptr);
18297c478bd9Sstevel@tonic-gate 			}
18307c478bd9Sstevel@tonic-gate 		}
18317c478bd9Sstevel@tonic-gate 		status = dbm_store((DBM *) map->map_db1,
18327c478bd9Sstevel@tonic-gate 				   key, data, DBM_REPLACE);
18337c478bd9Sstevel@tonic-gate 	}
18347c478bd9Sstevel@tonic-gate 	if (status != 0)
18357c478bd9Sstevel@tonic-gate 		syserr("readaliases: dbm put (%s): %d", lhs, status);
18367c478bd9Sstevel@tonic-gate }
18377c478bd9Sstevel@tonic-gate 
18387c478bd9Sstevel@tonic-gate 
18397c478bd9Sstevel@tonic-gate /*
18407c478bd9Sstevel@tonic-gate **  NDBM_MAP_CLOSE -- close the database
18417c478bd9Sstevel@tonic-gate */
18427c478bd9Sstevel@tonic-gate 
18437c478bd9Sstevel@tonic-gate void
18447c478bd9Sstevel@tonic-gate ndbm_map_close(map)
18457c478bd9Sstevel@tonic-gate 	register MAP  *map;
18467c478bd9Sstevel@tonic-gate {
18477c478bd9Sstevel@tonic-gate 	if (tTd(38, 9))
18487c478bd9Sstevel@tonic-gate 		sm_dprintf("ndbm_map_close(%s, %s, %lx)\n",
18497c478bd9Sstevel@tonic-gate 			map->map_mname, map->map_file, map->map_mflags);
18507c478bd9Sstevel@tonic-gate 
18517c478bd9Sstevel@tonic-gate 	if (bitset(MF_WRITABLE, map->map_mflags))
18527c478bd9Sstevel@tonic-gate 	{
18537c478bd9Sstevel@tonic-gate # ifdef NDBM_YP_COMPAT
18547c478bd9Sstevel@tonic-gate 		bool inclnull;
18557c478bd9Sstevel@tonic-gate 		char buf[MAXHOSTNAMELEN];
18567c478bd9Sstevel@tonic-gate 
18577c478bd9Sstevel@tonic-gate 		inclnull = bitset(MF_INCLNULL, map->map_mflags);
18587c478bd9Sstevel@tonic-gate 		map->map_mflags &= ~MF_INCLNULL;
18597c478bd9Sstevel@tonic-gate 
18607c478bd9Sstevel@tonic-gate 		if (strstr(map->map_file, "/yp/") != NULL)
18617c478bd9Sstevel@tonic-gate 		{
18627c478bd9Sstevel@tonic-gate 			long save_mflags = map->map_mflags;
18637c478bd9Sstevel@tonic-gate 
18647c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_NOFOLDCASE;
18657c478bd9Sstevel@tonic-gate 
18667c478bd9Sstevel@tonic-gate 			(void) sm_snprintf(buf, sizeof buf, "%010ld", curtime());
18677c478bd9Sstevel@tonic-gate 			ndbm_map_store(map, "YP_LAST_MODIFIED", buf);
18687c478bd9Sstevel@tonic-gate 
18697c478bd9Sstevel@tonic-gate 			(void) gethostname(buf, sizeof buf);
18707c478bd9Sstevel@tonic-gate 			ndbm_map_store(map, "YP_MASTER_NAME", buf);
18717c478bd9Sstevel@tonic-gate 
18727c478bd9Sstevel@tonic-gate 			map->map_mflags = save_mflags;
18737c478bd9Sstevel@tonic-gate 		}
18747c478bd9Sstevel@tonic-gate 
18757c478bd9Sstevel@tonic-gate 		if (inclnull)
18767c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_INCLNULL;
18777c478bd9Sstevel@tonic-gate # endif /* NDBM_YP_COMPAT */
18787c478bd9Sstevel@tonic-gate 
18797c478bd9Sstevel@tonic-gate 		/* write out the distinguished alias */
18807c478bd9Sstevel@tonic-gate 		ndbm_map_store(map, "@", "@");
18817c478bd9Sstevel@tonic-gate 	}
18827c478bd9Sstevel@tonic-gate 	dbm_close((DBM *) map->map_db1);
18837c478bd9Sstevel@tonic-gate 
18847c478bd9Sstevel@tonic-gate 	/* release lock (if needed) */
18857c478bd9Sstevel@tonic-gate # if !LOCK_ON_OPEN
18867c478bd9Sstevel@tonic-gate 	if (map->map_lockfd >= 0)
18877c478bd9Sstevel@tonic-gate 		(void) close(map->map_lockfd);
18887c478bd9Sstevel@tonic-gate # endif /* !LOCK_ON_OPEN */
18897c478bd9Sstevel@tonic-gate }
18907c478bd9Sstevel@tonic-gate 
18917c478bd9Sstevel@tonic-gate #endif /* NDBM */
18927c478bd9Sstevel@tonic-gate /*
18937c478bd9Sstevel@tonic-gate **  NEWDB (Hash and BTree) Modules
18947c478bd9Sstevel@tonic-gate */
18957c478bd9Sstevel@tonic-gate 
18967c478bd9Sstevel@tonic-gate #if NEWDB
18977c478bd9Sstevel@tonic-gate 
18987c478bd9Sstevel@tonic-gate /*
18997c478bd9Sstevel@tonic-gate **  BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives.
19007c478bd9Sstevel@tonic-gate **
19017c478bd9Sstevel@tonic-gate **	These do rather bizarre locking.  If you can lock on open,
19027c478bd9Sstevel@tonic-gate **	do that to avoid the condition of opening a database that
19037c478bd9Sstevel@tonic-gate **	is being rebuilt.  If you don't, we'll try to fake it, but
19047c478bd9Sstevel@tonic-gate **	there will be a race condition.  If opening for read-only,
19057c478bd9Sstevel@tonic-gate **	we immediately release the lock to avoid freezing things up.
19067c478bd9Sstevel@tonic-gate **	We really ought to hold the lock, but guarantee that we won't
19077c478bd9Sstevel@tonic-gate **	be pokey about it.  That's hard to do.
19087c478bd9Sstevel@tonic-gate */
19097c478bd9Sstevel@tonic-gate 
19107c478bd9Sstevel@tonic-gate /* these should be K line arguments */
19117c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2
19127c478bd9Sstevel@tonic-gate #  define db_cachesize	cachesize
19137c478bd9Sstevel@tonic-gate #  define h_nelem	nelem
19147c478bd9Sstevel@tonic-gate #  ifndef DB_CACHE_SIZE
19157c478bd9Sstevel@tonic-gate #   define DB_CACHE_SIZE	(1024 * 1024)	/* database memory cache size */
19167c478bd9Sstevel@tonic-gate #  endif /* ! DB_CACHE_SIZE */
19177c478bd9Sstevel@tonic-gate #  ifndef DB_HASH_NELEM
19187c478bd9Sstevel@tonic-gate #   define DB_HASH_NELEM	4096		/* (starting) size of hash table */
19197c478bd9Sstevel@tonic-gate #  endif /* ! DB_HASH_NELEM */
19207c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */
19217c478bd9Sstevel@tonic-gate 
19227c478bd9Sstevel@tonic-gate bool
19237c478bd9Sstevel@tonic-gate bt_map_open(map, mode)
19247c478bd9Sstevel@tonic-gate 	MAP *map;
19257c478bd9Sstevel@tonic-gate 	int mode;
19267c478bd9Sstevel@tonic-gate {
19277c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2
19287c478bd9Sstevel@tonic-gate 	BTREEINFO btinfo;
19297c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */
19307c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR == 2
19317c478bd9Sstevel@tonic-gate 	DB_INFO btinfo;
19327c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR == 2 */
19337c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR > 2
19347c478bd9Sstevel@tonic-gate 	void *btinfo = NULL;
19357c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR > 2 */
19367c478bd9Sstevel@tonic-gate 
19377c478bd9Sstevel@tonic-gate 	if (tTd(38, 2))
19387c478bd9Sstevel@tonic-gate 		sm_dprintf("bt_map_open(%s, %s, %d)\n",
19397c478bd9Sstevel@tonic-gate 			map->map_mname, map->map_file, mode);
19407c478bd9Sstevel@tonic-gate 
19417c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 3
19427c478bd9Sstevel@tonic-gate 	memset(&btinfo, '\0', sizeof btinfo);
19437c478bd9Sstevel@tonic-gate #  ifdef DB_CACHE_SIZE
19447c478bd9Sstevel@tonic-gate 	btinfo.db_cachesize = DB_CACHE_SIZE;
19457c478bd9Sstevel@tonic-gate #  endif /* DB_CACHE_SIZE */
19467c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 3 */
19477c478bd9Sstevel@tonic-gate 
19487c478bd9Sstevel@tonic-gate 	return db_map_open(map, mode, "btree", DB_BTREE, &btinfo);
19497c478bd9Sstevel@tonic-gate }
19507c478bd9Sstevel@tonic-gate 
19517c478bd9Sstevel@tonic-gate bool
19527c478bd9Sstevel@tonic-gate hash_map_open(map, mode)
19537c478bd9Sstevel@tonic-gate 	MAP *map;
19547c478bd9Sstevel@tonic-gate 	int mode;
19557c478bd9Sstevel@tonic-gate {
19567c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2
19577c478bd9Sstevel@tonic-gate 	HASHINFO hinfo;
19587c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */
19597c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR == 2
19607c478bd9Sstevel@tonic-gate 	DB_INFO hinfo;
19617c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR == 2 */
19627c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR > 2
19637c478bd9Sstevel@tonic-gate 	void *hinfo = NULL;
19647c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR > 2 */
19657c478bd9Sstevel@tonic-gate 
19667c478bd9Sstevel@tonic-gate 	if (tTd(38, 2))
19677c478bd9Sstevel@tonic-gate 		sm_dprintf("hash_map_open(%s, %s, %d)\n",
19687c478bd9Sstevel@tonic-gate 			map->map_mname, map->map_file, mode);
19697c478bd9Sstevel@tonic-gate 
19707c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 3
19717c478bd9Sstevel@tonic-gate 	memset(&hinfo, '\0', sizeof hinfo);
19727c478bd9Sstevel@tonic-gate #  ifdef DB_HASH_NELEM
19737c478bd9Sstevel@tonic-gate 	hinfo.h_nelem = DB_HASH_NELEM;
19747c478bd9Sstevel@tonic-gate #  endif /* DB_HASH_NELEM */
19757c478bd9Sstevel@tonic-gate #  ifdef DB_CACHE_SIZE
19767c478bd9Sstevel@tonic-gate 	hinfo.db_cachesize = DB_CACHE_SIZE;
19777c478bd9Sstevel@tonic-gate #  endif /* DB_CACHE_SIZE */
19787c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 3 */
19797c478bd9Sstevel@tonic-gate 
19807c478bd9Sstevel@tonic-gate 	return db_map_open(map, mode, "hash", DB_HASH, &hinfo);
19817c478bd9Sstevel@tonic-gate }
19827c478bd9Sstevel@tonic-gate 
19837c478bd9Sstevel@tonic-gate static bool
19847c478bd9Sstevel@tonic-gate db_map_open(map, mode, mapclassname, dbtype, openinfo)
19857c478bd9Sstevel@tonic-gate 	MAP *map;
19867c478bd9Sstevel@tonic-gate 	int mode;
19877c478bd9Sstevel@tonic-gate 	char *mapclassname;
19887c478bd9Sstevel@tonic-gate 	DBTYPE dbtype;
19897c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2
19907c478bd9Sstevel@tonic-gate 	const void *openinfo;
19917c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */
19927c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR == 2
19937c478bd9Sstevel@tonic-gate 	DB_INFO *openinfo;
19947c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR == 2 */
19957c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR > 2
19967c478bd9Sstevel@tonic-gate 	void **openinfo;
19977c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR > 2 */
19987c478bd9Sstevel@tonic-gate {
19997c478bd9Sstevel@tonic-gate 	DB *db = NULL;
20007c478bd9Sstevel@tonic-gate 	int i;
20017c478bd9Sstevel@tonic-gate 	int omode;
20027c478bd9Sstevel@tonic-gate 	int smode = S_IREAD;
20037c478bd9Sstevel@tonic-gate 	int fd;
20047c478bd9Sstevel@tonic-gate 	long sff;
20057c478bd9Sstevel@tonic-gate 	int save_errno;
20067c478bd9Sstevel@tonic-gate 	struct stat st;
20077c478bd9Sstevel@tonic-gate 	char buf[MAXPATHLEN];
20087c478bd9Sstevel@tonic-gate 
20097c478bd9Sstevel@tonic-gate 	/* do initial file and directory checks */
20107c478bd9Sstevel@tonic-gate 	if (sm_strlcpy(buf, map->map_file, sizeof buf) >= sizeof buf)
20117c478bd9Sstevel@tonic-gate 	{
20127c478bd9Sstevel@tonic-gate 		errno = 0;
20137c478bd9Sstevel@tonic-gate 		if (!bitset(MF_OPTIONAL, map->map_mflags))
20147c478bd9Sstevel@tonic-gate 			syserr("map \"%s\": map file %s name too long",
20157c478bd9Sstevel@tonic-gate 				map->map_mname, map->map_file);
20167c478bd9Sstevel@tonic-gate 		return false;
20177c478bd9Sstevel@tonic-gate 	}
20187c478bd9Sstevel@tonic-gate 	i = strlen(buf);
20197c478bd9Sstevel@tonic-gate 	if (i < 3 || strcmp(&buf[i - 3], ".db") != 0)
20207c478bd9Sstevel@tonic-gate 	{
20217c478bd9Sstevel@tonic-gate 		if (sm_strlcat(buf, ".db", sizeof buf) >= sizeof buf)
20227c478bd9Sstevel@tonic-gate 		{
20237c478bd9Sstevel@tonic-gate 			errno = 0;
20247c478bd9Sstevel@tonic-gate 			if (!bitset(MF_OPTIONAL, map->map_mflags))
20257c478bd9Sstevel@tonic-gate 				syserr("map \"%s\": map file %s name too long",
20267c478bd9Sstevel@tonic-gate 					map->map_mname, map->map_file);
20277c478bd9Sstevel@tonic-gate 			return false;
20287c478bd9Sstevel@tonic-gate 		}
20297c478bd9Sstevel@tonic-gate 	}
20307c478bd9Sstevel@tonic-gate 
20317c478bd9Sstevel@tonic-gate 	mode &= O_ACCMODE;
20327c478bd9Sstevel@tonic-gate 	omode = mode;
20337c478bd9Sstevel@tonic-gate 
20347c478bd9Sstevel@tonic-gate 	sff = SFF_ROOTOK|SFF_REGONLY;
20357c478bd9Sstevel@tonic-gate 	if (mode == O_RDWR)
20367c478bd9Sstevel@tonic-gate 	{
20377c478bd9Sstevel@tonic-gate 		sff |= SFF_CREAT;
20387c478bd9Sstevel@tonic-gate 		if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail))
20397c478bd9Sstevel@tonic-gate 			sff |= SFF_NOSLINK;
20407c478bd9Sstevel@tonic-gate 		if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail))
20417c478bd9Sstevel@tonic-gate 			sff |= SFF_NOHLINK;
20427c478bd9Sstevel@tonic-gate 		smode = S_IWRITE;
20437c478bd9Sstevel@tonic-gate 	}
20447c478bd9Sstevel@tonic-gate 	else
20457c478bd9Sstevel@tonic-gate 	{
20467c478bd9Sstevel@tonic-gate 		if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail))
20477c478bd9Sstevel@tonic-gate 			sff |= SFF_NOWLINK;
20487c478bd9Sstevel@tonic-gate 	}
20497c478bd9Sstevel@tonic-gate 	if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail))
20507c478bd9Sstevel@tonic-gate 		sff |= SFF_SAFEDIRPATH;
20517c478bd9Sstevel@tonic-gate 	i = safefile(buf, RunAsUid, RunAsGid, RunAsUserName, sff, smode, &st);
20527c478bd9Sstevel@tonic-gate 
20537c478bd9Sstevel@tonic-gate 	if (i != 0)
20547c478bd9Sstevel@tonic-gate 	{
20557c478bd9Sstevel@tonic-gate 		char *prob = "unsafe";
20567c478bd9Sstevel@tonic-gate 
20577c478bd9Sstevel@tonic-gate 		/* cannot open this map */
20587c478bd9Sstevel@tonic-gate 		if (i == ENOENT)
20597c478bd9Sstevel@tonic-gate 			prob = "missing";
20607c478bd9Sstevel@tonic-gate 		if (tTd(38, 2))
20617c478bd9Sstevel@tonic-gate 			sm_dprintf("\t%s map file: %s\n", prob, sm_errstring(i));
20627c478bd9Sstevel@tonic-gate 		errno = i;
20637c478bd9Sstevel@tonic-gate 		if (!bitset(MF_OPTIONAL, map->map_mflags))
20647c478bd9Sstevel@tonic-gate 			syserr("%s map \"%s\": %s map file %s",
20657c478bd9Sstevel@tonic-gate 				mapclassname, map->map_mname, prob, buf);
20667c478bd9Sstevel@tonic-gate 		return false;
20677c478bd9Sstevel@tonic-gate 	}
20687c478bd9Sstevel@tonic-gate 	if (st.st_mode == ST_MODE_NOFILE)
20697c478bd9Sstevel@tonic-gate 		omode |= O_CREAT|O_EXCL;
20707c478bd9Sstevel@tonic-gate 
20717c478bd9Sstevel@tonic-gate 	map->map_lockfd = -1;
20727c478bd9Sstevel@tonic-gate 
20737c478bd9Sstevel@tonic-gate # if LOCK_ON_OPEN
20747c478bd9Sstevel@tonic-gate 	if (mode == O_RDWR)
20757c478bd9Sstevel@tonic-gate 		omode |= O_TRUNC|O_EXLOCK;
20767c478bd9Sstevel@tonic-gate 	else
20777c478bd9Sstevel@tonic-gate 		omode |= O_SHLOCK;
20787c478bd9Sstevel@tonic-gate # else /* LOCK_ON_OPEN */
20797c478bd9Sstevel@tonic-gate 	/*
20807c478bd9Sstevel@tonic-gate 	**  Pre-lock the file to avoid race conditions.  In particular,
20817c478bd9Sstevel@tonic-gate 	**  since dbopen returns NULL if the file is zero length, we
20827c478bd9Sstevel@tonic-gate 	**  must have a locked instance around the dbopen.
20837c478bd9Sstevel@tonic-gate 	*/
20847c478bd9Sstevel@tonic-gate 
20857c478bd9Sstevel@tonic-gate 	fd = open(buf, omode, DBMMODE);
20867c478bd9Sstevel@tonic-gate 	if (fd < 0)
20877c478bd9Sstevel@tonic-gate 	{
20887c478bd9Sstevel@tonic-gate 		if (!bitset(MF_OPTIONAL, map->map_mflags))
20897c478bd9Sstevel@tonic-gate 			syserr("db_map_open: cannot pre-open database %s", buf);
20907c478bd9Sstevel@tonic-gate 		return false;
20917c478bd9Sstevel@tonic-gate 	}
20927c478bd9Sstevel@tonic-gate 
20937c478bd9Sstevel@tonic-gate 	/* make sure no baddies slipped in just before the open... */
20947c478bd9Sstevel@tonic-gate 	if (filechanged(buf, fd, &st))
20957c478bd9Sstevel@tonic-gate 	{
20967c478bd9Sstevel@tonic-gate 		save_errno = errno;
20977c478bd9Sstevel@tonic-gate 		(void) close(fd);
20987c478bd9Sstevel@tonic-gate 		errno = save_errno;
20997c478bd9Sstevel@tonic-gate 		syserr("db_map_open(%s): file changed after pre-open", buf);
21007c478bd9Sstevel@tonic-gate 		return false;
21017c478bd9Sstevel@tonic-gate 	}
21027c478bd9Sstevel@tonic-gate 
21037c478bd9Sstevel@tonic-gate 	/* if new file, get the "before" bits for later filechanged check */
21047c478bd9Sstevel@tonic-gate 	if (st.st_mode == ST_MODE_NOFILE && fstat(fd, &st) < 0)
21057c478bd9Sstevel@tonic-gate 	{
21067c478bd9Sstevel@tonic-gate 		save_errno = errno;
21077c478bd9Sstevel@tonic-gate 		(void) close(fd);
21087c478bd9Sstevel@tonic-gate 		errno = save_errno;
21097c478bd9Sstevel@tonic-gate 		syserr("db_map_open(%s): cannot fstat pre-opened file",
21107c478bd9Sstevel@tonic-gate 			buf);
21117c478bd9Sstevel@tonic-gate 		return false;
21127c478bd9Sstevel@tonic-gate 	}
21137c478bd9Sstevel@tonic-gate 
21147c478bd9Sstevel@tonic-gate 	/* actually lock the pre-opened file */
21157c478bd9Sstevel@tonic-gate 	if (!lockfile(fd, buf, NULL, mode == O_RDONLY ? LOCK_SH : LOCK_EX))
21167c478bd9Sstevel@tonic-gate 		syserr("db_map_open: cannot lock %s", buf);
21177c478bd9Sstevel@tonic-gate 
21187c478bd9Sstevel@tonic-gate 	/* set up mode bits for dbopen */
21197c478bd9Sstevel@tonic-gate 	if (mode == O_RDWR)
21207c478bd9Sstevel@tonic-gate 		omode |= O_TRUNC;
21217c478bd9Sstevel@tonic-gate 	omode &= ~(O_EXCL|O_CREAT);
21227c478bd9Sstevel@tonic-gate # endif /* LOCK_ON_OPEN */
21237c478bd9Sstevel@tonic-gate 
21247c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2
21257c478bd9Sstevel@tonic-gate 	db = dbopen(buf, omode, DBMMODE, dbtype, openinfo);
21267c478bd9Sstevel@tonic-gate # else /* DB_VERSION_MAJOR < 2 */
21277c478bd9Sstevel@tonic-gate 	{
21287c478bd9Sstevel@tonic-gate 		int flags = 0;
21297c478bd9Sstevel@tonic-gate #  if DB_VERSION_MAJOR > 2
21307c478bd9Sstevel@tonic-gate 		int ret;
21317c478bd9Sstevel@tonic-gate #  endif /* DB_VERSION_MAJOR > 2 */
21327c478bd9Sstevel@tonic-gate 
21337c478bd9Sstevel@tonic-gate 		if (mode == O_RDONLY)
21347c478bd9Sstevel@tonic-gate 			flags |= DB_RDONLY;
21357c478bd9Sstevel@tonic-gate 		if (bitset(O_CREAT, omode))
21367c478bd9Sstevel@tonic-gate 			flags |= DB_CREATE;
21377c478bd9Sstevel@tonic-gate 		if (bitset(O_TRUNC, omode))
21387c478bd9Sstevel@tonic-gate 			flags |= DB_TRUNCATE;
21397c478bd9Sstevel@tonic-gate 		SM_DB_FLAG_ADD(flags);
21407c478bd9Sstevel@tonic-gate 
21417c478bd9Sstevel@tonic-gate #  if DB_VERSION_MAJOR > 2
21427c478bd9Sstevel@tonic-gate 		ret = db_create(&db, NULL, 0);
21437c478bd9Sstevel@tonic-gate #  ifdef DB_CACHE_SIZE
21447c478bd9Sstevel@tonic-gate 		if (ret == 0 && db != NULL)
21457c478bd9Sstevel@tonic-gate 		{
21467c478bd9Sstevel@tonic-gate 			ret = db->set_cachesize(db, 0, DB_CACHE_SIZE, 0);
21477c478bd9Sstevel@tonic-gate 			if (ret != 0)
21487c478bd9Sstevel@tonic-gate 			{
21497c478bd9Sstevel@tonic-gate 				(void) db->close(db, 0);
21507c478bd9Sstevel@tonic-gate 				db = NULL;
21517c478bd9Sstevel@tonic-gate 			}
21527c478bd9Sstevel@tonic-gate 		}
21537c478bd9Sstevel@tonic-gate #  endif /* DB_CACHE_SIZE */
21547c478bd9Sstevel@tonic-gate #  ifdef DB_HASH_NELEM
21557c478bd9Sstevel@tonic-gate 		if (dbtype == DB_HASH && ret == 0 && db != NULL)
21567c478bd9Sstevel@tonic-gate 		{
21577c478bd9Sstevel@tonic-gate 			ret = db->set_h_nelem(db, DB_HASH_NELEM);
21587c478bd9Sstevel@tonic-gate 			if (ret != 0)
21597c478bd9Sstevel@tonic-gate 			{
21607c478bd9Sstevel@tonic-gate 				(void) db->close(db, 0);
21617c478bd9Sstevel@tonic-gate 				db = NULL;
21627c478bd9Sstevel@tonic-gate 			}
21637c478bd9Sstevel@tonic-gate 		}
21647c478bd9Sstevel@tonic-gate #  endif /* DB_HASH_NELEM */
21657c478bd9Sstevel@tonic-gate 		if (ret == 0 && db != NULL)
21667c478bd9Sstevel@tonic-gate 		{
21677c478bd9Sstevel@tonic-gate 			ret = db->open(db,
21687c478bd9Sstevel@tonic-gate 					DBTXN	/* transaction for DB 4.1 */
21697c478bd9Sstevel@tonic-gate 					buf, NULL, dbtype, flags, DBMMODE);
21707c478bd9Sstevel@tonic-gate 			if (ret != 0)
21717c478bd9Sstevel@tonic-gate 			{
21727c478bd9Sstevel@tonic-gate #ifdef DB_OLD_VERSION
21737c478bd9Sstevel@tonic-gate 				if (ret == DB_OLD_VERSION)
21747c478bd9Sstevel@tonic-gate 					ret = EINVAL;
21757c478bd9Sstevel@tonic-gate #endif /* DB_OLD_VERSION */
21767c478bd9Sstevel@tonic-gate 				(void) db->close(db, 0);
21777c478bd9Sstevel@tonic-gate 				db = NULL;
21787c478bd9Sstevel@tonic-gate 			}
21797c478bd9Sstevel@tonic-gate 		}
21807c478bd9Sstevel@tonic-gate 		errno = ret;
21817c478bd9Sstevel@tonic-gate #  else /* DB_VERSION_MAJOR > 2 */
21827c478bd9Sstevel@tonic-gate 		errno = db_open(buf, dbtype, flags, DBMMODE,
21837c478bd9Sstevel@tonic-gate 				NULL, openinfo, &db);
21847c478bd9Sstevel@tonic-gate #  endif /* DB_VERSION_MAJOR > 2 */
21857c478bd9Sstevel@tonic-gate 	}
21867c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */
21877c478bd9Sstevel@tonic-gate 	save_errno = errno;
21887c478bd9Sstevel@tonic-gate 
21897c478bd9Sstevel@tonic-gate # if !LOCK_ON_OPEN
21907c478bd9Sstevel@tonic-gate 	if (mode == O_RDWR)
21917c478bd9Sstevel@tonic-gate 		map->map_lockfd = fd;
21927c478bd9Sstevel@tonic-gate 	else
21937c478bd9Sstevel@tonic-gate 		(void) close(fd);
21947c478bd9Sstevel@tonic-gate # endif /* !LOCK_ON_OPEN */
21957c478bd9Sstevel@tonic-gate 
21967c478bd9Sstevel@tonic-gate 	if (db == NULL)
21977c478bd9Sstevel@tonic-gate 	{
21987c478bd9Sstevel@tonic-gate 		if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags) &&
21997c478bd9Sstevel@tonic-gate 		    aliaswait(map, ".db", false))
22007c478bd9Sstevel@tonic-gate 			return true;
22017c478bd9Sstevel@tonic-gate # if !LOCK_ON_OPEN
22027c478bd9Sstevel@tonic-gate 		if (map->map_lockfd >= 0)
22037c478bd9Sstevel@tonic-gate 			(void) close(map->map_lockfd);
22047c478bd9Sstevel@tonic-gate # endif /* !LOCK_ON_OPEN */
22057c478bd9Sstevel@tonic-gate 		errno = save_errno;
22067c478bd9Sstevel@tonic-gate 		if (!bitset(MF_OPTIONAL, map->map_mflags))
22077c478bd9Sstevel@tonic-gate 			syserr("Cannot open %s database %s",
22087c478bd9Sstevel@tonic-gate 				mapclassname, buf);
22097c478bd9Sstevel@tonic-gate 		return false;
22107c478bd9Sstevel@tonic-gate 	}
22117c478bd9Sstevel@tonic-gate 
22127c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2
22137c478bd9Sstevel@tonic-gate 	fd = db->fd(db);
22147c478bd9Sstevel@tonic-gate # else /* DB_VERSION_MAJOR < 2 */
22157c478bd9Sstevel@tonic-gate 	fd = -1;
22167c478bd9Sstevel@tonic-gate 	errno = db->fd(db, &fd);
22177c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */
22187c478bd9Sstevel@tonic-gate 	if (filechanged(buf, fd, &st))
22197c478bd9Sstevel@tonic-gate 	{
22207c478bd9Sstevel@tonic-gate 		save_errno = errno;
22217c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2
22227c478bd9Sstevel@tonic-gate 		(void) db->close(db);
22237c478bd9Sstevel@tonic-gate # else /* DB_VERSION_MAJOR < 2 */
22247c478bd9Sstevel@tonic-gate 		errno = db->close(db, 0);
22257c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */
22267c478bd9Sstevel@tonic-gate # if !LOCK_ON_OPEN
22277c478bd9Sstevel@tonic-gate 		if (map->map_lockfd >= 0)
22287c478bd9Sstevel@tonic-gate 			(void) close(map->map_lockfd);
22297c478bd9Sstevel@tonic-gate # endif /* !LOCK_ON_OPEN */
22307c478bd9Sstevel@tonic-gate 		errno = save_errno;
22317c478bd9Sstevel@tonic-gate 		syserr("db_map_open(%s): file changed after open", buf);
22327c478bd9Sstevel@tonic-gate 		return false;
22337c478bd9Sstevel@tonic-gate 	}
22347c478bd9Sstevel@tonic-gate 
22357c478bd9Sstevel@tonic-gate 	if (mode == O_RDWR)
22367c478bd9Sstevel@tonic-gate 		map->map_mflags |= MF_LOCKED;
22377c478bd9Sstevel@tonic-gate # if LOCK_ON_OPEN
22387c478bd9Sstevel@tonic-gate 	if (fd >= 0 && mode == O_RDONLY)
22397c478bd9Sstevel@tonic-gate 	{
22407c478bd9Sstevel@tonic-gate 		(void) lockfile(fd, buf, NULL, LOCK_UN);
22417c478bd9Sstevel@tonic-gate 	}
22427c478bd9Sstevel@tonic-gate # endif /* LOCK_ON_OPEN */
22437c478bd9Sstevel@tonic-gate 
22447c478bd9Sstevel@tonic-gate 	/* try to make sure that at least the database header is on disk */
22457c478bd9Sstevel@tonic-gate 	if (mode == O_RDWR)
22467c478bd9Sstevel@tonic-gate 	{
22477c478bd9Sstevel@tonic-gate 		(void) db->sync(db, 0);
22487c478bd9Sstevel@tonic-gate 		if (geteuid() == 0 && TrustedUid != 0)
22497c478bd9Sstevel@tonic-gate 		{
22507c478bd9Sstevel@tonic-gate #  if HASFCHOWN
22517c478bd9Sstevel@tonic-gate 			if (fchown(fd, TrustedUid, -1) < 0)
22527c478bd9Sstevel@tonic-gate 			{
22537c478bd9Sstevel@tonic-gate 				int err = errno;
22547c478bd9Sstevel@tonic-gate 
22557c478bd9Sstevel@tonic-gate 				sm_syslog(LOG_ALERT, NOQID,
22567c478bd9Sstevel@tonic-gate 					  "ownership change on %s failed: %s",
22577c478bd9Sstevel@tonic-gate 					  buf, sm_errstring(err));
22587c478bd9Sstevel@tonic-gate 				message("050 ownership change on %s failed: %s",
22597c478bd9Sstevel@tonic-gate 					buf, sm_errstring(err));
22607c478bd9Sstevel@tonic-gate 			}
22617c478bd9Sstevel@tonic-gate #  else /* HASFCHOWN */
22627c478bd9Sstevel@tonic-gate 			sm_syslog(LOG_ALERT, NOQID,
22637c478bd9Sstevel@tonic-gate 				  "no fchown(): cannot change ownership on %s",
22647c478bd9Sstevel@tonic-gate 				  map->map_file);
22657c478bd9Sstevel@tonic-gate 			message("050 no fchown(): cannot change ownership on %s",
22667c478bd9Sstevel@tonic-gate 				map->map_file);
22677c478bd9Sstevel@tonic-gate #  endif /* HASFCHOWN */
22687c478bd9Sstevel@tonic-gate 		}
22697c478bd9Sstevel@tonic-gate 	}
22707c478bd9Sstevel@tonic-gate 
22717c478bd9Sstevel@tonic-gate 	map->map_db2 = (ARBPTR_T) db;
22727c478bd9Sstevel@tonic-gate 
22737c478bd9Sstevel@tonic-gate 	/*
22747c478bd9Sstevel@tonic-gate 	**  Need to set map_mtime before the call to aliaswait()
22757c478bd9Sstevel@tonic-gate 	**  as aliaswait() will call map_lookup() which requires
22767c478bd9Sstevel@tonic-gate 	**  map_mtime to be set
22777c478bd9Sstevel@tonic-gate 	*/
22787c478bd9Sstevel@tonic-gate 
22797c478bd9Sstevel@tonic-gate 	if (fd >= 0 && fstat(fd, &st) >= 0)
22807c478bd9Sstevel@tonic-gate 		map->map_mtime = st.st_mtime;
22817c478bd9Sstevel@tonic-gate 
22827c478bd9Sstevel@tonic-gate 	if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags) &&
22837c478bd9Sstevel@tonic-gate 	    !aliaswait(map, ".db", true))
22847c478bd9Sstevel@tonic-gate 		return false;
22857c478bd9Sstevel@tonic-gate 	return true;
22867c478bd9Sstevel@tonic-gate }
22877c478bd9Sstevel@tonic-gate 
22887c478bd9Sstevel@tonic-gate 
22897c478bd9Sstevel@tonic-gate /*
22907c478bd9Sstevel@tonic-gate **  DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map
22917c478bd9Sstevel@tonic-gate */
22927c478bd9Sstevel@tonic-gate 
22937c478bd9Sstevel@tonic-gate char *
22947c478bd9Sstevel@tonic-gate db_map_lookup(map, name, av, statp)
22957c478bd9Sstevel@tonic-gate 	MAP *map;
22967c478bd9Sstevel@tonic-gate 	char *name;
22977c478bd9Sstevel@tonic-gate 	char **av;
22987c478bd9Sstevel@tonic-gate 	int *statp;
22997c478bd9Sstevel@tonic-gate {
23007c478bd9Sstevel@tonic-gate 	DBT key, val;
23017c478bd9Sstevel@tonic-gate 	register DB *db = (DB *) map->map_db2;
23027c478bd9Sstevel@tonic-gate 	int i;
23037c478bd9Sstevel@tonic-gate 	int st;
23047c478bd9Sstevel@tonic-gate 	int save_errno;
23057c478bd9Sstevel@tonic-gate 	int fd;
23067c478bd9Sstevel@tonic-gate 	struct stat stbuf;
23077c478bd9Sstevel@tonic-gate 	char keybuf[MAXNAME + 1];
23087c478bd9Sstevel@tonic-gate 	char buf[MAXPATHLEN];
23097c478bd9Sstevel@tonic-gate 
23107c478bd9Sstevel@tonic-gate 	memset(&key, '\0', sizeof key);
23117c478bd9Sstevel@tonic-gate 	memset(&val, '\0', sizeof val);
23127c478bd9Sstevel@tonic-gate 
23137c478bd9Sstevel@tonic-gate 	if (tTd(38, 20))
23147c478bd9Sstevel@tonic-gate 		sm_dprintf("db_map_lookup(%s, %s)\n",
23157c478bd9Sstevel@tonic-gate 			map->map_mname, name);
23167c478bd9Sstevel@tonic-gate 
23177c478bd9Sstevel@tonic-gate 	if (sm_strlcpy(buf, map->map_file, sizeof buf) >= sizeof buf)
23187c478bd9Sstevel@tonic-gate 	{
23197c478bd9Sstevel@tonic-gate 		errno = 0;
23207c478bd9Sstevel@tonic-gate 		if (!bitset(MF_OPTIONAL, map->map_mflags))
23217c478bd9Sstevel@tonic-gate 			syserr("map \"%s\": map file %s name too long",
23227c478bd9Sstevel@tonic-gate 				map->map_mname, map->map_file);
23237c478bd9Sstevel@tonic-gate 		return NULL;
23247c478bd9Sstevel@tonic-gate 	}
23257c478bd9Sstevel@tonic-gate 	i = strlen(buf);
23267c478bd9Sstevel@tonic-gate 	if (i > 3 && strcmp(&buf[i - 3], ".db") == 0)
23277c478bd9Sstevel@tonic-gate 		buf[i - 3] = '\0';
23287c478bd9Sstevel@tonic-gate 
23297c478bd9Sstevel@tonic-gate 	key.size = strlen(name);
23307c478bd9Sstevel@tonic-gate 	if (key.size > sizeof keybuf - 1)
23317c478bd9Sstevel@tonic-gate 		key.size = sizeof keybuf - 1;
23327c478bd9Sstevel@tonic-gate 	key.data = keybuf;
23337c478bd9Sstevel@tonic-gate 	memmove(keybuf, name, key.size);
23347c478bd9Sstevel@tonic-gate 	keybuf[key.size] = '\0';
23357c478bd9Sstevel@tonic-gate 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
23367c478bd9Sstevel@tonic-gate 		makelower(keybuf);
23377c478bd9Sstevel@tonic-gate   lockdb:
23387c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2
23397c478bd9Sstevel@tonic-gate 	fd = db->fd(db);
23407c478bd9Sstevel@tonic-gate # else /* DB_VERSION_MAJOR < 2 */
23417c478bd9Sstevel@tonic-gate 	fd = -1;
23427c478bd9Sstevel@tonic-gate 	errno = db->fd(db, &fd);
23437c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */
23447c478bd9Sstevel@tonic-gate 	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
23457c478bd9Sstevel@tonic-gate 		(void) lockfile(fd, buf, ".db", LOCK_SH);
23467c478bd9Sstevel@tonic-gate 	if (fd < 0 || fstat(fd, &stbuf) < 0 || stbuf.st_mtime > map->map_mtime)
23477c478bd9Sstevel@tonic-gate 	{
23487c478bd9Sstevel@tonic-gate 		/* Reopen the database to sync the cache */
23497c478bd9Sstevel@tonic-gate 		int omode = bitset(map->map_mflags, MF_WRITABLE) ? O_RDWR
23507c478bd9Sstevel@tonic-gate 								 : O_RDONLY;
23517c478bd9Sstevel@tonic-gate 
23527c478bd9Sstevel@tonic-gate 		if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
23537c478bd9Sstevel@tonic-gate 			(void) lockfile(fd, buf, ".db", LOCK_UN);
23547c478bd9Sstevel@tonic-gate 		map->map_mflags |= MF_CLOSING;
23557c478bd9Sstevel@tonic-gate 		map->map_class->map_close(map);
23567c478bd9Sstevel@tonic-gate 		map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING);
23577c478bd9Sstevel@tonic-gate 		if (map->map_class->map_open(map, omode))
23587c478bd9Sstevel@tonic-gate 		{
23597c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_OPEN;
23607c478bd9Sstevel@tonic-gate 			map->map_pid = CurrentPid;
23617c478bd9Sstevel@tonic-gate 			if ((omode && O_ACCMODE) == O_RDWR)
23627c478bd9Sstevel@tonic-gate 				map->map_mflags |= MF_WRITABLE;
23637c478bd9Sstevel@tonic-gate 			db = (DB *) map->map_db2;
23647c478bd9Sstevel@tonic-gate 			goto lockdb;
23657c478bd9Sstevel@tonic-gate 		}
23667c478bd9Sstevel@tonic-gate 		else
23677c478bd9Sstevel@tonic-gate 		{
23687c478bd9Sstevel@tonic-gate 			if (!bitset(MF_OPTIONAL, map->map_mflags))
23697c478bd9Sstevel@tonic-gate 			{
23707c478bd9Sstevel@tonic-gate 				extern MAPCLASS BogusMapClass;
23717c478bd9Sstevel@tonic-gate 
23727c478bd9Sstevel@tonic-gate 				*statp = EX_TEMPFAIL;
23737c478bd9Sstevel@tonic-gate 				map->map_orgclass = map->map_class;
23747c478bd9Sstevel@tonic-gate 				map->map_class = &BogusMapClass;
23757c478bd9Sstevel@tonic-gate 				map->map_mflags |= MF_OPEN;
23767c478bd9Sstevel@tonic-gate 				map->map_pid = CurrentPid;
23777c478bd9Sstevel@tonic-gate 				syserr("Cannot reopen DB database %s",
23787c478bd9Sstevel@tonic-gate 					map->map_file);
23797c478bd9Sstevel@tonic-gate 			}
23807c478bd9Sstevel@tonic-gate 			return NULL;
23817c478bd9Sstevel@tonic-gate 		}
23827c478bd9Sstevel@tonic-gate 	}
23837c478bd9Sstevel@tonic-gate 
23847c478bd9Sstevel@tonic-gate 	st = 1;
23857c478bd9Sstevel@tonic-gate 	if (bitset(MF_TRY0NULL, map->map_mflags))
23867c478bd9Sstevel@tonic-gate 	{
23877c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2
23887c478bd9Sstevel@tonic-gate 		st = db->get(db, &key, &val, 0);
23897c478bd9Sstevel@tonic-gate # else /* DB_VERSION_MAJOR < 2 */
23907c478bd9Sstevel@tonic-gate 		errno = db->get(db, NULL, &key, &val, 0);
23917c478bd9Sstevel@tonic-gate 		switch (errno)
23927c478bd9Sstevel@tonic-gate 		{
23937c478bd9Sstevel@tonic-gate 		  case DB_NOTFOUND:
23947c478bd9Sstevel@tonic-gate 		  case DB_KEYEMPTY:
23957c478bd9Sstevel@tonic-gate 			st = 1;
23967c478bd9Sstevel@tonic-gate 			break;
23977c478bd9Sstevel@tonic-gate 
23987c478bd9Sstevel@tonic-gate 		  case 0:
23997c478bd9Sstevel@tonic-gate 			st = 0;
24007c478bd9Sstevel@tonic-gate 			break;
24017c478bd9Sstevel@tonic-gate 
24027c478bd9Sstevel@tonic-gate 		  default:
24037c478bd9Sstevel@tonic-gate 			st = -1;
24047c478bd9Sstevel@tonic-gate 			break;
24057c478bd9Sstevel@tonic-gate 		}
24067c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */
24077c478bd9Sstevel@tonic-gate 		if (st == 0)
24087c478bd9Sstevel@tonic-gate 			map->map_mflags &= ~MF_TRY1NULL;
24097c478bd9Sstevel@tonic-gate 	}
24107c478bd9Sstevel@tonic-gate 	if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags))
24117c478bd9Sstevel@tonic-gate 	{
24127c478bd9Sstevel@tonic-gate 		key.size++;
24137c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2
24147c478bd9Sstevel@tonic-gate 		st = db->get(db, &key, &val, 0);
24157c478bd9Sstevel@tonic-gate # else /* DB_VERSION_MAJOR < 2 */
24167c478bd9Sstevel@tonic-gate 		errno = db->get(db, NULL, &key, &val, 0);
24177c478bd9Sstevel@tonic-gate 		switch (errno)
24187c478bd9Sstevel@tonic-gate 		{
24197c478bd9Sstevel@tonic-gate 		  case DB_NOTFOUND:
24207c478bd9Sstevel@tonic-gate 		  case DB_KEYEMPTY:
24217c478bd9Sstevel@tonic-gate 			st = 1;
24227c478bd9Sstevel@tonic-gate 			break;
24237c478bd9Sstevel@tonic-gate 
24247c478bd9Sstevel@tonic-gate 		  case 0:
24257c478bd9Sstevel@tonic-gate 			st = 0;
24267c478bd9Sstevel@tonic-gate 			break;
24277c478bd9Sstevel@tonic-gate 
24287c478bd9Sstevel@tonic-gate 		  default:
24297c478bd9Sstevel@tonic-gate 			st = -1;
24307c478bd9Sstevel@tonic-gate 			break;
24317c478bd9Sstevel@tonic-gate 		}
24327c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */
24337c478bd9Sstevel@tonic-gate 		if (st == 0)
24347c478bd9Sstevel@tonic-gate 			map->map_mflags &= ~MF_TRY0NULL;
24357c478bd9Sstevel@tonic-gate 	}
24367c478bd9Sstevel@tonic-gate 	save_errno = errno;
24377c478bd9Sstevel@tonic-gate 	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
24387c478bd9Sstevel@tonic-gate 		(void) lockfile(fd, buf, ".db", LOCK_UN);
24397c478bd9Sstevel@tonic-gate 	if (st != 0)
24407c478bd9Sstevel@tonic-gate 	{
24417c478bd9Sstevel@tonic-gate 		errno = save_errno;
24427c478bd9Sstevel@tonic-gate 		if (st < 0)
24437c478bd9Sstevel@tonic-gate 			syserr("db_map_lookup: get (%s)", name);
24447c478bd9Sstevel@tonic-gate 		return NULL;
24457c478bd9Sstevel@tonic-gate 	}
24467c478bd9Sstevel@tonic-gate 	if (bitset(MF_MATCHONLY, map->map_mflags))
24477c478bd9Sstevel@tonic-gate 		return map_rewrite(map, name, strlen(name), NULL);
24487c478bd9Sstevel@tonic-gate 	else
24497c478bd9Sstevel@tonic-gate 		return map_rewrite(map, val.data, val.size, av);
24507c478bd9Sstevel@tonic-gate }
24517c478bd9Sstevel@tonic-gate 
24527c478bd9Sstevel@tonic-gate 
24537c478bd9Sstevel@tonic-gate /*
24547c478bd9Sstevel@tonic-gate **  DB_MAP_STORE -- store a datum in the NEWDB database
24557c478bd9Sstevel@tonic-gate */
24567c478bd9Sstevel@tonic-gate 
24577c478bd9Sstevel@tonic-gate void
24587c478bd9Sstevel@tonic-gate db_map_store(map, lhs, rhs)
24597c478bd9Sstevel@tonic-gate 	register MAP *map;
24607c478bd9Sstevel@tonic-gate 	char *lhs;
24617c478bd9Sstevel@tonic-gate 	char *rhs;
24627c478bd9Sstevel@tonic-gate {
24637c478bd9Sstevel@tonic-gate 	int status;
24647c478bd9Sstevel@tonic-gate 	DBT key;
24657c478bd9Sstevel@tonic-gate 	DBT data;
24667c478bd9Sstevel@tonic-gate 	register DB *db = map->map_db2;
24677c478bd9Sstevel@tonic-gate 	char keybuf[MAXNAME + 1];
24687c478bd9Sstevel@tonic-gate 
24697c478bd9Sstevel@tonic-gate 	memset(&key, '\0', sizeof key);
24707c478bd9Sstevel@tonic-gate 	memset(&data, '\0', sizeof data);
24717c478bd9Sstevel@tonic-gate 
24727c478bd9Sstevel@tonic-gate 	if (tTd(38, 12))
24737c478bd9Sstevel@tonic-gate 		sm_dprintf("db_map_store(%s, %s, %s)\n",
24747c478bd9Sstevel@tonic-gate 			map->map_mname, lhs, rhs);
24757c478bd9Sstevel@tonic-gate 
24767c478bd9Sstevel@tonic-gate 	key.size = strlen(lhs);
24777c478bd9Sstevel@tonic-gate 	key.data = lhs;
24787c478bd9Sstevel@tonic-gate 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
24797c478bd9Sstevel@tonic-gate 	{
24807c478bd9Sstevel@tonic-gate 		if (key.size > sizeof keybuf - 1)
24817c478bd9Sstevel@tonic-gate 			key.size = sizeof keybuf - 1;
24827c478bd9Sstevel@tonic-gate 		memmove(keybuf, key.data, key.size);
24837c478bd9Sstevel@tonic-gate 		keybuf[key.size] = '\0';
24847c478bd9Sstevel@tonic-gate 		makelower(keybuf);
24857c478bd9Sstevel@tonic-gate 		key.data = keybuf;
24867c478bd9Sstevel@tonic-gate 	}
24877c478bd9Sstevel@tonic-gate 
24887c478bd9Sstevel@tonic-gate 	data.size = strlen(rhs);
24897c478bd9Sstevel@tonic-gate 	data.data = rhs;
24907c478bd9Sstevel@tonic-gate 
24917c478bd9Sstevel@tonic-gate 	if (bitset(MF_INCLNULL, map->map_mflags))
24927c478bd9Sstevel@tonic-gate 	{
24937c478bd9Sstevel@tonic-gate 		key.size++;
24947c478bd9Sstevel@tonic-gate 		data.size++;
24957c478bd9Sstevel@tonic-gate 	}
24967c478bd9Sstevel@tonic-gate 
24977c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2
24987c478bd9Sstevel@tonic-gate 	status = db->put(db, &key, &data, R_NOOVERWRITE);
24997c478bd9Sstevel@tonic-gate # else /* DB_VERSION_MAJOR < 2 */
25007c478bd9Sstevel@tonic-gate 	errno = db->put(db, NULL, &key, &data, DB_NOOVERWRITE);
25017c478bd9Sstevel@tonic-gate 	switch (errno)
25027c478bd9Sstevel@tonic-gate 	{
25037c478bd9Sstevel@tonic-gate 	  case DB_KEYEXIST:
25047c478bd9Sstevel@tonic-gate 		status = 1;
25057c478bd9Sstevel@tonic-gate 		break;
25067c478bd9Sstevel@tonic-gate 
25077c478bd9Sstevel@tonic-gate 	  case 0:
25087c478bd9Sstevel@tonic-gate 		status = 0;
25097c478bd9Sstevel@tonic-gate 		break;
25107c478bd9Sstevel@tonic-gate 
25117c478bd9Sstevel@tonic-gate 	  default:
25127c478bd9Sstevel@tonic-gate 		status = -1;
25137c478bd9Sstevel@tonic-gate 		break;
25147c478bd9Sstevel@tonic-gate 	}
25157c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */
25167c478bd9Sstevel@tonic-gate 	if (status > 0)
25177c478bd9Sstevel@tonic-gate 	{
25187c478bd9Sstevel@tonic-gate 		if (!bitset(MF_APPEND, map->map_mflags))
25197c478bd9Sstevel@tonic-gate 			message("050 Warning: duplicate alias name %s", lhs);
25207c478bd9Sstevel@tonic-gate 		else
25217c478bd9Sstevel@tonic-gate 		{
25227c478bd9Sstevel@tonic-gate 			static char *buf = NULL;
25237c478bd9Sstevel@tonic-gate 			static int bufsiz = 0;
25247c478bd9Sstevel@tonic-gate 			DBT old;
25257c478bd9Sstevel@tonic-gate 
25267c478bd9Sstevel@tonic-gate 			memset(&old, '\0', sizeof old);
25277c478bd9Sstevel@tonic-gate 
25287c478bd9Sstevel@tonic-gate 			old.data = db_map_lookup(map, key.data,
25297c478bd9Sstevel@tonic-gate 						 (char **) NULL, &status);
25307c478bd9Sstevel@tonic-gate 			if (old.data != NULL)
25317c478bd9Sstevel@tonic-gate 			{
25327c478bd9Sstevel@tonic-gate 				old.size = strlen(old.data);
25337c478bd9Sstevel@tonic-gate 				if (data.size + old.size + 2 > (size_t) bufsiz)
25347c478bd9Sstevel@tonic-gate 				{
25357c478bd9Sstevel@tonic-gate 					if (buf != NULL)
25367c478bd9Sstevel@tonic-gate 						sm_free(buf);
25377c478bd9Sstevel@tonic-gate 					bufsiz = data.size + old.size + 2;
25387c478bd9Sstevel@tonic-gate 					buf = sm_pmalloc_x(bufsiz);
25397c478bd9Sstevel@tonic-gate 				}
25407c478bd9Sstevel@tonic-gate 				(void) sm_strlcpyn(buf, bufsiz, 3,
25417c478bd9Sstevel@tonic-gate 					(char *) data.data, ",",
25427c478bd9Sstevel@tonic-gate 					(char *) old.data);
25437c478bd9Sstevel@tonic-gate 				data.size = data.size + old.size + 1;
25447c478bd9Sstevel@tonic-gate 				data.data = buf;
25457c478bd9Sstevel@tonic-gate 				if (tTd(38, 9))
25467c478bd9Sstevel@tonic-gate 					sm_dprintf("db_map_store append=%s\n",
25477c478bd9Sstevel@tonic-gate 						(char *) data.data);
25487c478bd9Sstevel@tonic-gate 			}
25497c478bd9Sstevel@tonic-gate 		}
25507c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2
25517c478bd9Sstevel@tonic-gate 		status = db->put(db, &key, &data, 0);
25527c478bd9Sstevel@tonic-gate # else /* DB_VERSION_MAJOR < 2 */
25537c478bd9Sstevel@tonic-gate 		status = errno = db->put(db, NULL, &key, &data, 0);
25547c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */
25557c478bd9Sstevel@tonic-gate 	}
25567c478bd9Sstevel@tonic-gate 	if (status != 0)
25577c478bd9Sstevel@tonic-gate 		syserr("readaliases: db put (%s)", lhs);
25587c478bd9Sstevel@tonic-gate }
25597c478bd9Sstevel@tonic-gate 
25607c478bd9Sstevel@tonic-gate 
25617c478bd9Sstevel@tonic-gate /*
25627c478bd9Sstevel@tonic-gate **  DB_MAP_CLOSE -- add distinguished entries and close the database
25637c478bd9Sstevel@tonic-gate */
25647c478bd9Sstevel@tonic-gate 
25657c478bd9Sstevel@tonic-gate void
25667c478bd9Sstevel@tonic-gate db_map_close(map)
25677c478bd9Sstevel@tonic-gate 	MAP *map;
25687c478bd9Sstevel@tonic-gate {
25697c478bd9Sstevel@tonic-gate 	register DB *db = map->map_db2;
25707c478bd9Sstevel@tonic-gate 
25717c478bd9Sstevel@tonic-gate 	if (tTd(38, 9))
25727c478bd9Sstevel@tonic-gate 		sm_dprintf("db_map_close(%s, %s, %lx)\n",
25737c478bd9Sstevel@tonic-gate 			map->map_mname, map->map_file, map->map_mflags);
25747c478bd9Sstevel@tonic-gate 
25757c478bd9Sstevel@tonic-gate 	if (bitset(MF_WRITABLE, map->map_mflags))
25767c478bd9Sstevel@tonic-gate 	{
25777c478bd9Sstevel@tonic-gate 		/* write out the distinguished alias */
25787c478bd9Sstevel@tonic-gate 		db_map_store(map, "@", "@");
25797c478bd9Sstevel@tonic-gate 	}
25807c478bd9Sstevel@tonic-gate 
25817c478bd9Sstevel@tonic-gate 	(void) db->sync(db, 0);
25827c478bd9Sstevel@tonic-gate 
25837c478bd9Sstevel@tonic-gate # if !LOCK_ON_OPEN
25847c478bd9Sstevel@tonic-gate 	if (map->map_lockfd >= 0)
25857c478bd9Sstevel@tonic-gate 		(void) close(map->map_lockfd);
25867c478bd9Sstevel@tonic-gate # endif /* !LOCK_ON_OPEN */
25877c478bd9Sstevel@tonic-gate 
25887c478bd9Sstevel@tonic-gate # if DB_VERSION_MAJOR < 2
25897c478bd9Sstevel@tonic-gate 	if (db->close(db) != 0)
25907c478bd9Sstevel@tonic-gate # else /* DB_VERSION_MAJOR < 2 */
25917c478bd9Sstevel@tonic-gate 	/*
25927c478bd9Sstevel@tonic-gate 	**  Berkeley DB can use internal shared memory
25937c478bd9Sstevel@tonic-gate 	**  locking for its memory pool.  Closing a map
25947c478bd9Sstevel@tonic-gate 	**  opened by another process will interfere
25957c478bd9Sstevel@tonic-gate 	**  with the shared memory and locks of the parent
25967c478bd9Sstevel@tonic-gate 	**  process leaving things in a bad state.
25977c478bd9Sstevel@tonic-gate 	*/
25987c478bd9Sstevel@tonic-gate 
25997c478bd9Sstevel@tonic-gate 	/*
26007c478bd9Sstevel@tonic-gate 	**  If this map was not opened by the current
26017c478bd9Sstevel@tonic-gate 	**  process, do not close the map but recover
26027c478bd9Sstevel@tonic-gate 	**  the file descriptor.
26037c478bd9Sstevel@tonic-gate 	*/
26047c478bd9Sstevel@tonic-gate 
26057c478bd9Sstevel@tonic-gate 	if (map->map_pid != CurrentPid)
26067c478bd9Sstevel@tonic-gate 	{
26077c478bd9Sstevel@tonic-gate 		int fd = -1;
26087c478bd9Sstevel@tonic-gate 
26097c478bd9Sstevel@tonic-gate 		errno = db->fd(db, &fd);
26107c478bd9Sstevel@tonic-gate 		if (fd >= 0)
26117c478bd9Sstevel@tonic-gate 			(void) close(fd);
26127c478bd9Sstevel@tonic-gate 		return;
26137c478bd9Sstevel@tonic-gate 	}
26147c478bd9Sstevel@tonic-gate 
26157c478bd9Sstevel@tonic-gate 	if ((errno = db->close(db, 0)) != 0)
26167c478bd9Sstevel@tonic-gate # endif /* DB_VERSION_MAJOR < 2 */
26177c478bd9Sstevel@tonic-gate 		syserr("db_map_close(%s, %s, %lx): db close failure",
26187c478bd9Sstevel@tonic-gate 			map->map_mname, map->map_file, map->map_mflags);
26197c478bd9Sstevel@tonic-gate }
26207c478bd9Sstevel@tonic-gate #endif /* NEWDB */
26217c478bd9Sstevel@tonic-gate /*
26227c478bd9Sstevel@tonic-gate **  NIS Modules
26237c478bd9Sstevel@tonic-gate */
26247c478bd9Sstevel@tonic-gate 
26257c478bd9Sstevel@tonic-gate #if NIS
26267c478bd9Sstevel@tonic-gate 
26277c478bd9Sstevel@tonic-gate # ifndef YPERR_BUSY
26287c478bd9Sstevel@tonic-gate #  define YPERR_BUSY	16
26297c478bd9Sstevel@tonic-gate # endif /* ! YPERR_BUSY */
26307c478bd9Sstevel@tonic-gate 
26317c478bd9Sstevel@tonic-gate /*
26327c478bd9Sstevel@tonic-gate **  NIS_MAP_OPEN -- open DBM map
26337c478bd9Sstevel@tonic-gate */
26347c478bd9Sstevel@tonic-gate 
26357c478bd9Sstevel@tonic-gate bool
26367c478bd9Sstevel@tonic-gate nis_map_open(map, mode)
26377c478bd9Sstevel@tonic-gate 	MAP *map;
26387c478bd9Sstevel@tonic-gate 	int mode;
26397c478bd9Sstevel@tonic-gate {
26407c478bd9Sstevel@tonic-gate 	int yperr;
26417c478bd9Sstevel@tonic-gate 	register char *p;
26427c478bd9Sstevel@tonic-gate 	auto char *vp;
26437c478bd9Sstevel@tonic-gate 	auto int vsize;
26447c478bd9Sstevel@tonic-gate 
26457c478bd9Sstevel@tonic-gate 	if (tTd(38, 2))
26467c478bd9Sstevel@tonic-gate 		sm_dprintf("nis_map_open(%s, %s, %d)\n",
26477c478bd9Sstevel@tonic-gate 			map->map_mname, map->map_file, mode);
26487c478bd9Sstevel@tonic-gate 
26497c478bd9Sstevel@tonic-gate 	mode &= O_ACCMODE;
26507c478bd9Sstevel@tonic-gate 	if (mode != O_RDONLY)
26517c478bd9Sstevel@tonic-gate 	{
26527c478bd9Sstevel@tonic-gate 		/* issue a pseudo-error message */
26537c478bd9Sstevel@tonic-gate 		errno = SM_EMAPCANTWRITE;
26547c478bd9Sstevel@tonic-gate 		return false;
26557c478bd9Sstevel@tonic-gate 	}
26567c478bd9Sstevel@tonic-gate 
26577c478bd9Sstevel@tonic-gate 	p = strchr(map->map_file, '@');
26587c478bd9Sstevel@tonic-gate 	if (p != NULL)
26597c478bd9Sstevel@tonic-gate 	{
26607c478bd9Sstevel@tonic-gate 		*p++ = '\0';
26617c478bd9Sstevel@tonic-gate 		if (*p != '\0')
26627c478bd9Sstevel@tonic-gate 			map->map_domain = p;
26637c478bd9Sstevel@tonic-gate 	}
26647c478bd9Sstevel@tonic-gate 
26657c478bd9Sstevel@tonic-gate 	if (*map->map_file == '\0')
26667c478bd9Sstevel@tonic-gate 		map->map_file = "mail.aliases";
26677c478bd9Sstevel@tonic-gate 
26687c478bd9Sstevel@tonic-gate 	if (map->map_domain == NULL)
26697c478bd9Sstevel@tonic-gate 	{
26707c478bd9Sstevel@tonic-gate 		yperr = yp_get_default_domain(&map->map_domain);
26717c478bd9Sstevel@tonic-gate 		if (yperr != 0)
26727c478bd9Sstevel@tonic-gate 		{
26737c478bd9Sstevel@tonic-gate 			if (!bitset(MF_OPTIONAL, map->map_mflags))
26747c478bd9Sstevel@tonic-gate 				syserr("451 4.3.5 NIS map %s specified, but NIS not running",
26757c478bd9Sstevel@tonic-gate 				       map->map_file);
26767c478bd9Sstevel@tonic-gate 			return false;
26777c478bd9Sstevel@tonic-gate 		}
26787c478bd9Sstevel@tonic-gate 	}
26797c478bd9Sstevel@tonic-gate 
26807c478bd9Sstevel@tonic-gate 	/* check to see if this map actually exists */
26817c478bd9Sstevel@tonic-gate 	vp = NULL;
26827c478bd9Sstevel@tonic-gate 	yperr = yp_match(map->map_domain, map->map_file, "@", 1,
26837c478bd9Sstevel@tonic-gate 			&vp, &vsize);
26847c478bd9Sstevel@tonic-gate 	if (tTd(38, 10))
26857c478bd9Sstevel@tonic-gate 		sm_dprintf("nis_map_open: yp_match(@, %s, %s) => %s\n",
26867c478bd9Sstevel@tonic-gate 			map->map_domain, map->map_file, yperr_string(yperr));
26877c478bd9Sstevel@tonic-gate 	if (vp != NULL)
26887c478bd9Sstevel@tonic-gate 		sm_free(vp);
26897c478bd9Sstevel@tonic-gate 
26907c478bd9Sstevel@tonic-gate 	if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY)
26917c478bd9Sstevel@tonic-gate 	{
26927c478bd9Sstevel@tonic-gate 		/*
26937c478bd9Sstevel@tonic-gate 		**  We ought to be calling aliaswait() here if this is an
26947c478bd9Sstevel@tonic-gate 		**  alias file, but powerful HP-UX NIS servers  apparently
26957c478bd9Sstevel@tonic-gate 		**  don't insert the @:@ token into the alias map when it
26967c478bd9Sstevel@tonic-gate 		**  is rebuilt, so aliaswait() just hangs.  I hate HP-UX.
26977c478bd9Sstevel@tonic-gate 		*/
26987c478bd9Sstevel@tonic-gate 
26997c478bd9Sstevel@tonic-gate # if 0
27007c478bd9Sstevel@tonic-gate 		if (!bitset(MF_ALIAS, map->map_mflags) ||
27017c478bd9Sstevel@tonic-gate 		    aliaswait(map, NULL, true))
27027c478bd9Sstevel@tonic-gate # endif /* 0 */
27037c478bd9Sstevel@tonic-gate 			return true;
27047c478bd9Sstevel@tonic-gate 	}
27057c478bd9Sstevel@tonic-gate 
27067c478bd9Sstevel@tonic-gate 	if (!bitset(MF_OPTIONAL, map->map_mflags))
27077c478bd9Sstevel@tonic-gate 	{
27087c478bd9Sstevel@tonic-gate 		syserr("451 4.3.5 Cannot bind to map %s in domain %s: %s",
27097c478bd9Sstevel@tonic-gate 			map->map_file, map->map_domain, yperr_string(yperr));
27107c478bd9Sstevel@tonic-gate 	}
27117c478bd9Sstevel@tonic-gate 
27127c478bd9Sstevel@tonic-gate 	return false;
27137c478bd9Sstevel@tonic-gate }
27147c478bd9Sstevel@tonic-gate 
27157c478bd9Sstevel@tonic-gate 
27167c478bd9Sstevel@tonic-gate /*
27177c478bd9Sstevel@tonic-gate **  NIS_MAP_LOOKUP -- look up a datum in a NIS map
27187c478bd9Sstevel@tonic-gate */
27197c478bd9Sstevel@tonic-gate 
27207c478bd9Sstevel@tonic-gate /* ARGSUSED3 */
27217c478bd9Sstevel@tonic-gate char *
27227c478bd9Sstevel@tonic-gate nis_map_lookup(map, name, av, statp)
27237c478bd9Sstevel@tonic-gate 	MAP *map;
27247c478bd9Sstevel@tonic-gate 	char *name;
27257c478bd9Sstevel@tonic-gate 	char **av;
27267c478bd9Sstevel@tonic-gate 	int *statp;
27277c478bd9Sstevel@tonic-gate {
27287c478bd9Sstevel@tonic-gate 	char *vp;
27297c478bd9Sstevel@tonic-gate 	auto int vsize;
27307c478bd9Sstevel@tonic-gate 	int buflen;
27317c478bd9Sstevel@tonic-gate 	int yperr;
27327c478bd9Sstevel@tonic-gate 	char keybuf[MAXNAME + 1];
27337c478bd9Sstevel@tonic-gate 	char *SM_NONVOLATILE result = NULL;
27347c478bd9Sstevel@tonic-gate 
27357c478bd9Sstevel@tonic-gate 	if (tTd(38, 20))
27367c478bd9Sstevel@tonic-gate 		sm_dprintf("nis_map_lookup(%s, %s)\n",
27377c478bd9Sstevel@tonic-gate 			map->map_mname, name);
27387c478bd9Sstevel@tonic-gate 
27397c478bd9Sstevel@tonic-gate 	buflen = strlen(name);
27407c478bd9Sstevel@tonic-gate 	if (buflen > sizeof keybuf - 1)
27417c478bd9Sstevel@tonic-gate 		buflen = sizeof keybuf - 1;
27427c478bd9Sstevel@tonic-gate 	memmove(keybuf, name, buflen);
27437c478bd9Sstevel@tonic-gate 	keybuf[buflen] = '\0';
27447c478bd9Sstevel@tonic-gate 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
27457c478bd9Sstevel@tonic-gate 		makelower(keybuf);
27467c478bd9Sstevel@tonic-gate 	yperr = YPERR_KEY;
27477c478bd9Sstevel@tonic-gate 	vp = NULL;
27487c478bd9Sstevel@tonic-gate 	if (bitset(MF_TRY0NULL, map->map_mflags))
27497c478bd9Sstevel@tonic-gate 	{
27507c478bd9Sstevel@tonic-gate 		yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
27517c478bd9Sstevel@tonic-gate 			     &vp, &vsize);
27527c478bd9Sstevel@tonic-gate 		if (yperr == 0)
27537c478bd9Sstevel@tonic-gate 			map->map_mflags &= ~MF_TRY1NULL;
27547c478bd9Sstevel@tonic-gate 	}
27557c478bd9Sstevel@tonic-gate 	if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags))
27567c478bd9Sstevel@tonic-gate 	{
27577c478bd9Sstevel@tonic-gate 		SM_FREE_CLR(vp);
27587c478bd9Sstevel@tonic-gate 		buflen++;
27597c478bd9Sstevel@tonic-gate 		yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
27607c478bd9Sstevel@tonic-gate 			     &vp, &vsize);
27617c478bd9Sstevel@tonic-gate 		if (yperr == 0)
27627c478bd9Sstevel@tonic-gate 			map->map_mflags &= ~MF_TRY0NULL;
27637c478bd9Sstevel@tonic-gate 	}
27647c478bd9Sstevel@tonic-gate 	if (yperr != 0)
27657c478bd9Sstevel@tonic-gate 	{
27667c478bd9Sstevel@tonic-gate 		if (yperr != YPERR_KEY && yperr != YPERR_BUSY)
27677c478bd9Sstevel@tonic-gate 			map->map_mflags &= ~(MF_VALID|MF_OPEN);
27687c478bd9Sstevel@tonic-gate 		if (vp != NULL)
27697c478bd9Sstevel@tonic-gate 			sm_free(vp);
27707c478bd9Sstevel@tonic-gate 		return NULL;
27717c478bd9Sstevel@tonic-gate 	}
27727c478bd9Sstevel@tonic-gate 	SM_TRY
27737c478bd9Sstevel@tonic-gate 		if (bitset(MF_MATCHONLY, map->map_mflags))
27747c478bd9Sstevel@tonic-gate 			result = map_rewrite(map, name, strlen(name), NULL);
27757c478bd9Sstevel@tonic-gate 		else
27767c478bd9Sstevel@tonic-gate 			result = map_rewrite(map, vp, vsize, av);
27777c478bd9Sstevel@tonic-gate 	SM_FINALLY
27787c478bd9Sstevel@tonic-gate 		if (vp != NULL)
27797c478bd9Sstevel@tonic-gate 			sm_free(vp);
27807c478bd9Sstevel@tonic-gate 	SM_END_TRY
27817c478bd9Sstevel@tonic-gate 	return result;
27827c478bd9Sstevel@tonic-gate }
27837c478bd9Sstevel@tonic-gate 
27847c478bd9Sstevel@tonic-gate 
27857c478bd9Sstevel@tonic-gate /*
27867c478bd9Sstevel@tonic-gate **  NIS_GETCANONNAME -- look up canonical name in NIS
27877c478bd9Sstevel@tonic-gate */
27887c478bd9Sstevel@tonic-gate 
27897c478bd9Sstevel@tonic-gate static bool
27907c478bd9Sstevel@tonic-gate nis_getcanonname(name, hbsize, statp)
27917c478bd9Sstevel@tonic-gate 	char *name;
27927c478bd9Sstevel@tonic-gate 	int hbsize;
27937c478bd9Sstevel@tonic-gate 	int *statp;
27947c478bd9Sstevel@tonic-gate {
27957c478bd9Sstevel@tonic-gate 	char *vp;
27967c478bd9Sstevel@tonic-gate 	auto int vsize;
27977c478bd9Sstevel@tonic-gate 	int keylen;
27987c478bd9Sstevel@tonic-gate 	int yperr;
27997c478bd9Sstevel@tonic-gate 	static bool try0null = true;
28007c478bd9Sstevel@tonic-gate 	static bool try1null = true;
28017c478bd9Sstevel@tonic-gate 	static char *yp_domain = NULL;
28027c478bd9Sstevel@tonic-gate 	char host_record[MAXLINE];
28037c478bd9Sstevel@tonic-gate 	char cbuf[MAXNAME];
28047c478bd9Sstevel@tonic-gate 	char nbuf[MAXNAME + 1];
28057c478bd9Sstevel@tonic-gate 
28067c478bd9Sstevel@tonic-gate 	if (tTd(38, 20))
28077c478bd9Sstevel@tonic-gate 		sm_dprintf("nis_getcanonname(%s)\n", name);
28087c478bd9Sstevel@tonic-gate 
28097c478bd9Sstevel@tonic-gate 	if (sm_strlcpy(nbuf, name, sizeof nbuf) >= sizeof nbuf)
28107c478bd9Sstevel@tonic-gate 	{
28117c478bd9Sstevel@tonic-gate 		*statp = EX_UNAVAILABLE;
28127c478bd9Sstevel@tonic-gate 		return false;
28137c478bd9Sstevel@tonic-gate 	}
28147c478bd9Sstevel@tonic-gate 	(void) shorten_hostname(nbuf);
28157c478bd9Sstevel@tonic-gate 	keylen = strlen(nbuf);
28167c478bd9Sstevel@tonic-gate 
28177c478bd9Sstevel@tonic-gate 	if (yp_domain == NULL)
28187c478bd9Sstevel@tonic-gate 		(void) yp_get_default_domain(&yp_domain);
28197c478bd9Sstevel@tonic-gate 	makelower(nbuf);
28207c478bd9Sstevel@tonic-gate 	yperr = YPERR_KEY;
28217c478bd9Sstevel@tonic-gate 	vp = NULL;
28227c478bd9Sstevel@tonic-gate 	if (try0null)
28237c478bd9Sstevel@tonic-gate 	{
28247c478bd9Sstevel@tonic-gate 		yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen,
28257c478bd9Sstevel@tonic-gate 			     &vp, &vsize);
28267c478bd9Sstevel@tonic-gate 		if (yperr == 0)
28277c478bd9Sstevel@tonic-gate 			try1null = false;
28287c478bd9Sstevel@tonic-gate 	}
28297c478bd9Sstevel@tonic-gate 	if (yperr == YPERR_KEY && try1null)
28307c478bd9Sstevel@tonic-gate 	{
28317c478bd9Sstevel@tonic-gate 		SM_FREE_CLR(vp);
28327c478bd9Sstevel@tonic-gate 		keylen++;
28337c478bd9Sstevel@tonic-gate 		yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen,
28347c478bd9Sstevel@tonic-gate 			     &vp, &vsize);
28357c478bd9Sstevel@tonic-gate 		if (yperr == 0)
28367c478bd9Sstevel@tonic-gate 			try0null = false;
28377c478bd9Sstevel@tonic-gate 	}
28387c478bd9Sstevel@tonic-gate 	if (yperr != 0)
28397c478bd9Sstevel@tonic-gate 	{
28407c478bd9Sstevel@tonic-gate 		if (yperr == YPERR_KEY)
28417c478bd9Sstevel@tonic-gate 			*statp = EX_NOHOST;
28427c478bd9Sstevel@tonic-gate 		else if (yperr == YPERR_BUSY)
28437c478bd9Sstevel@tonic-gate 			*statp = EX_TEMPFAIL;
28447c478bd9Sstevel@tonic-gate 		else
28457c478bd9Sstevel@tonic-gate 			*statp = EX_UNAVAILABLE;
28467c478bd9Sstevel@tonic-gate 		if (vp != NULL)
28477c478bd9Sstevel@tonic-gate 			sm_free(vp);
28487c478bd9Sstevel@tonic-gate 		return false;
28497c478bd9Sstevel@tonic-gate 	}
28507c478bd9Sstevel@tonic-gate 	(void) sm_strlcpy(host_record, vp, sizeof host_record);
28517c478bd9Sstevel@tonic-gate 	sm_free(vp);
28527c478bd9Sstevel@tonic-gate 	if (tTd(38, 44))
28537c478bd9Sstevel@tonic-gate 		sm_dprintf("got record `%s'\n", host_record);
28547c478bd9Sstevel@tonic-gate 	vp = strpbrk(host_record, "#\n");
28557c478bd9Sstevel@tonic-gate 	if (vp != NULL)
28567c478bd9Sstevel@tonic-gate 		*vp = '\0';
28577c478bd9Sstevel@tonic-gate 	if (!extract_canonname(nbuf, NULL, host_record, cbuf, sizeof cbuf))
28587c478bd9Sstevel@tonic-gate 	{
28597c478bd9Sstevel@tonic-gate 		/* this should not happen, but.... */
28607c478bd9Sstevel@tonic-gate 		*statp = EX_NOHOST;
28617c478bd9Sstevel@tonic-gate 		return false;
28627c478bd9Sstevel@tonic-gate 	}
28637c478bd9Sstevel@tonic-gate 	if (sm_strlcpy(name, cbuf, hbsize) >= hbsize)
28647c478bd9Sstevel@tonic-gate 	{
28657c478bd9Sstevel@tonic-gate 		*statp = EX_UNAVAILABLE;
28667c478bd9Sstevel@tonic-gate 		return false;
28677c478bd9Sstevel@tonic-gate 	}
28687c478bd9Sstevel@tonic-gate 	*statp = EX_OK;
28697c478bd9Sstevel@tonic-gate 	return true;
28707c478bd9Sstevel@tonic-gate }
28717c478bd9Sstevel@tonic-gate 
28727c478bd9Sstevel@tonic-gate #endif /* NIS */
28737c478bd9Sstevel@tonic-gate /*
28747c478bd9Sstevel@tonic-gate **  NISPLUS Modules
28757c478bd9Sstevel@tonic-gate **
28767c478bd9Sstevel@tonic-gate **	This code donated by Sun Microsystems.
28777c478bd9Sstevel@tonic-gate */
28787c478bd9Sstevel@tonic-gate 
28797c478bd9Sstevel@tonic-gate #if NISPLUS
28807c478bd9Sstevel@tonic-gate 
28817c478bd9Sstevel@tonic-gate # undef NIS		/* symbol conflict in nis.h */
28827c478bd9Sstevel@tonic-gate # undef T_UNSPEC	/* symbol conflict in nis.h -> ... -> sys/tiuser.h */
28837c478bd9Sstevel@tonic-gate # include <rpcsvc/nis.h>
28847c478bd9Sstevel@tonic-gate # include <rpcsvc/nislib.h>
28857c478bd9Sstevel@tonic-gate 
28867c478bd9Sstevel@tonic-gate # define EN_col(col)	zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val
28877c478bd9Sstevel@tonic-gate # define COL_NAME(res,i)	((res->objects.objects_val)->TA_data.ta_cols.ta_cols_val)[i].tc_name
28887c478bd9Sstevel@tonic-gate # define COL_MAX(res)	((res->objects.objects_val)->TA_data.ta_cols.ta_cols_len)
28897c478bd9Sstevel@tonic-gate # define PARTIAL_NAME(x)	((x)[strlen(x) - 1] != '.')
28907c478bd9Sstevel@tonic-gate 
28917c478bd9Sstevel@tonic-gate /*
28927c478bd9Sstevel@tonic-gate **  NISPLUS_MAP_OPEN -- open nisplus table
28937c478bd9Sstevel@tonic-gate */
28947c478bd9Sstevel@tonic-gate 
28957c478bd9Sstevel@tonic-gate bool
28967c478bd9Sstevel@tonic-gate nisplus_map_open(map, mode)
28977c478bd9Sstevel@tonic-gate 	MAP *map;
28987c478bd9Sstevel@tonic-gate 	int mode;
28997c478bd9Sstevel@tonic-gate {
29007c478bd9Sstevel@tonic-gate 	nis_result *res = NULL;
29017c478bd9Sstevel@tonic-gate 	int retry_cnt, max_col, i;
29027c478bd9Sstevel@tonic-gate 	char qbuf[MAXLINE + NIS_MAXNAMELEN];
29037c478bd9Sstevel@tonic-gate 
29047c478bd9Sstevel@tonic-gate 	if (tTd(38, 2))
29057c478bd9Sstevel@tonic-gate 		sm_dprintf("nisplus_map_open(%s, %s, %d)\n",
29067c478bd9Sstevel@tonic-gate 			map->map_mname, map->map_file, mode);
29077c478bd9Sstevel@tonic-gate 
29087c478bd9Sstevel@tonic-gate 	mode &= O_ACCMODE;
29097c478bd9Sstevel@tonic-gate 	if (mode != O_RDONLY)
29107c478bd9Sstevel@tonic-gate 	{
29117c478bd9Sstevel@tonic-gate 		errno = EPERM;
29127c478bd9Sstevel@tonic-gate 		return false;
29137c478bd9Sstevel@tonic-gate 	}
29147c478bd9Sstevel@tonic-gate 
29157c478bd9Sstevel@tonic-gate 	if (*map->map_file == '\0')
29167c478bd9Sstevel@tonic-gate 		map->map_file = "mail_aliases.org_dir";
29177c478bd9Sstevel@tonic-gate 
29187c478bd9Sstevel@tonic-gate 	if (PARTIAL_NAME(map->map_file) && map->map_domain == NULL)
29197c478bd9Sstevel@tonic-gate 	{
29207c478bd9Sstevel@tonic-gate 		/* set default NISPLUS Domain to $m */
29217c478bd9Sstevel@tonic-gate 		map->map_domain = newstr(nisplus_default_domain());
29227c478bd9Sstevel@tonic-gate 		if (tTd(38, 2))
29237c478bd9Sstevel@tonic-gate 			sm_dprintf("nisplus_map_open(%s): using domain %s\n",
29247c478bd9Sstevel@tonic-gate 				map->map_file, map->map_domain);
29257c478bd9Sstevel@tonic-gate 	}
29267c478bd9Sstevel@tonic-gate 	if (!PARTIAL_NAME(map->map_file))
29277c478bd9Sstevel@tonic-gate 	{
29287c478bd9Sstevel@tonic-gate 		map->map_domain = newstr("");
29297c478bd9Sstevel@tonic-gate 		(void) sm_strlcpy(qbuf, map->map_file, sizeof qbuf);
29307c478bd9Sstevel@tonic-gate 	}
29317c478bd9Sstevel@tonic-gate 	else
29327c478bd9Sstevel@tonic-gate 	{
29337c478bd9Sstevel@tonic-gate 		/* check to see if this map actually exists */
29347c478bd9Sstevel@tonic-gate 		(void) sm_strlcpyn(qbuf, sizeof qbuf, 3,
29357c478bd9Sstevel@tonic-gate 				   map->map_file, ".", map->map_domain);
29367c478bd9Sstevel@tonic-gate 	}
29377c478bd9Sstevel@tonic-gate 
29387c478bd9Sstevel@tonic-gate 	retry_cnt = 0;
29397c478bd9Sstevel@tonic-gate 	while (res == NULL || res->status != NIS_SUCCESS)
29407c478bd9Sstevel@tonic-gate 	{
29417c478bd9Sstevel@tonic-gate 		res = nis_lookup(qbuf, FOLLOW_LINKS);
29427c478bd9Sstevel@tonic-gate 		switch (res->status)
29437c478bd9Sstevel@tonic-gate 		{
29447c478bd9Sstevel@tonic-gate 		  case NIS_SUCCESS:
29457c478bd9Sstevel@tonic-gate 			break;
29467c478bd9Sstevel@tonic-gate 
29477c478bd9Sstevel@tonic-gate 		  case NIS_TRYAGAIN:
29487c478bd9Sstevel@tonic-gate 		  case NIS_RPCERROR:
29497c478bd9Sstevel@tonic-gate 		  case NIS_NAMEUNREACHABLE:
29507c478bd9Sstevel@tonic-gate 			if (retry_cnt++ > 4)
29517c478bd9Sstevel@tonic-gate 			{
29527c478bd9Sstevel@tonic-gate 				errno = EAGAIN;
29537c478bd9Sstevel@tonic-gate 				return false;
29547c478bd9Sstevel@tonic-gate 			}
29557c478bd9Sstevel@tonic-gate 			/* try not to overwhelm hosed server */
29567c478bd9Sstevel@tonic-gate 			sleep(2);
29577c478bd9Sstevel@tonic-gate 			break;
29587c478bd9Sstevel@tonic-gate 
29597c478bd9Sstevel@tonic-gate 		  default:		/* all other nisplus errors */
29607c478bd9Sstevel@tonic-gate # if 0
29617c478bd9Sstevel@tonic-gate 			if (!bitset(MF_OPTIONAL, map->map_mflags))
29627c478bd9Sstevel@tonic-gate 				syserr("451 4.3.5 Cannot find table %s.%s: %s",
29637c478bd9Sstevel@tonic-gate 					map->map_file, map->map_domain,
29647c478bd9Sstevel@tonic-gate 					nis_sperrno(res->status));
29657c478bd9Sstevel@tonic-gate # endif /* 0 */
29667c478bd9Sstevel@tonic-gate 			errno = EAGAIN;
29677c478bd9Sstevel@tonic-gate 			return false;
29687c478bd9Sstevel@tonic-gate 		}
29697c478bd9Sstevel@tonic-gate 	}
29707c478bd9Sstevel@tonic-gate 
29717c478bd9Sstevel@tonic-gate 	if (NIS_RES_NUMOBJ(res) != 1 ||
29727c478bd9Sstevel@tonic-gate 	    (NIS_RES_OBJECT(res)->zo_data.zo_type != TABLE_OBJ))
29737c478bd9Sstevel@tonic-gate 	{
29747c478bd9Sstevel@tonic-gate 		if (tTd(38, 10))
29757c478bd9Sstevel@tonic-gate 			sm_dprintf("nisplus_map_open: %s is not a table\n", qbuf);
29767c478bd9Sstevel@tonic-gate # if 0
29777c478bd9Sstevel@tonic-gate 		if (!bitset(MF_OPTIONAL, map->map_mflags))
29787c478bd9Sstevel@tonic-gate 			syserr("451 4.3.5 %s.%s: %s is not a table",
29797c478bd9Sstevel@tonic-gate 				map->map_file, map->map_domain,
29807c478bd9Sstevel@tonic-gate 				nis_sperrno(res->status));
29817c478bd9Sstevel@tonic-gate # endif /* 0 */
29827c478bd9Sstevel@tonic-gate 		errno = EBADF;
29837c478bd9Sstevel@tonic-gate 		return false;
29847c478bd9Sstevel@tonic-gate 	}
29857c478bd9Sstevel@tonic-gate 	/* default key column is column 0 */
29867c478bd9Sstevel@tonic-gate 	if (map->map_keycolnm == NULL)
29877c478bd9Sstevel@tonic-gate 		map->map_keycolnm = newstr(COL_NAME(res,0));
29887c478bd9Sstevel@tonic-gate 
29897c478bd9Sstevel@tonic-gate 	max_col = COL_MAX(res);
29907c478bd9Sstevel@tonic-gate 
29917c478bd9Sstevel@tonic-gate 	/* verify the key column exist */
29927c478bd9Sstevel@tonic-gate 	for (i = 0; i < max_col; i++)
29937c478bd9Sstevel@tonic-gate 	{
29947c478bd9Sstevel@tonic-gate 		if (strcmp(map->map_keycolnm, COL_NAME(res,i)) == 0)
29957c478bd9Sstevel@tonic-gate 			break;
29967c478bd9Sstevel@tonic-gate 	}
29977c478bd9Sstevel@tonic-gate 	if (i == max_col)
29987c478bd9Sstevel@tonic-gate 	{
29997c478bd9Sstevel@tonic-gate 		if (tTd(38, 2))
30007c478bd9Sstevel@tonic-gate 			sm_dprintf("nisplus_map_open(%s): can not find key column %s\n",
30017c478bd9Sstevel@tonic-gate 				map->map_file, map->map_keycolnm);
30027c478bd9Sstevel@tonic-gate 		errno = ENOENT;
30037c478bd9Sstevel@tonic-gate 		return false;
30047c478bd9Sstevel@tonic-gate 	}
30057c478bd9Sstevel@tonic-gate 
30067c478bd9Sstevel@tonic-gate 	/* default value column is the last column */
30077c478bd9Sstevel@tonic-gate 	if (map->map_valcolnm == NULL)
30087c478bd9Sstevel@tonic-gate 	{
30097c478bd9Sstevel@tonic-gate 		map->map_valcolno = max_col - 1;
30107c478bd9Sstevel@tonic-gate 		return true;
30117c478bd9Sstevel@tonic-gate 	}
30127c478bd9Sstevel@tonic-gate 
30137c478bd9Sstevel@tonic-gate 	for (i = 0; i< max_col; i++)
30147c478bd9Sstevel@tonic-gate 	{
30157c478bd9Sstevel@tonic-gate 		if (strcmp(map->map_valcolnm, COL_NAME(res,i)) == 0)
30167c478bd9Sstevel@tonic-gate 		{
30177c478bd9Sstevel@tonic-gate 			map->map_valcolno = i;
30187c478bd9Sstevel@tonic-gate 			return true;
30197c478bd9Sstevel@tonic-gate 		}
30207c478bd9Sstevel@tonic-gate 	}
30217c478bd9Sstevel@tonic-gate 
30227c478bd9Sstevel@tonic-gate 	if (tTd(38, 2))
30237c478bd9Sstevel@tonic-gate 		sm_dprintf("nisplus_map_open(%s): can not find column %s\n",
30247c478bd9Sstevel@tonic-gate 			map->map_file, map->map_keycolnm);
30257c478bd9Sstevel@tonic-gate 	errno = ENOENT;
30267c478bd9Sstevel@tonic-gate 	return false;
30277c478bd9Sstevel@tonic-gate }
30287c478bd9Sstevel@tonic-gate 
30297c478bd9Sstevel@tonic-gate 
30307c478bd9Sstevel@tonic-gate /*
30317c478bd9Sstevel@tonic-gate **  NISPLUS_MAP_LOOKUP -- look up a datum in a NISPLUS table
30327c478bd9Sstevel@tonic-gate */
30337c478bd9Sstevel@tonic-gate 
30347c478bd9Sstevel@tonic-gate char *
30357c478bd9Sstevel@tonic-gate nisplus_map_lookup(map, name, av, statp)
30367c478bd9Sstevel@tonic-gate 	MAP *map;
30377c478bd9Sstevel@tonic-gate 	char *name;
30387c478bd9Sstevel@tonic-gate 	char **av;
30397c478bd9Sstevel@tonic-gate 	int *statp;
30407c478bd9Sstevel@tonic-gate {
30417c478bd9Sstevel@tonic-gate 	char *p;
30427c478bd9Sstevel@tonic-gate 	auto int vsize;
30437c478bd9Sstevel@tonic-gate 	char *skp;
30447c478bd9Sstevel@tonic-gate 	int skleft;
30457c478bd9Sstevel@tonic-gate 	char search_key[MAXNAME + 4];
30467c478bd9Sstevel@tonic-gate 	char qbuf[MAXLINE + NIS_MAXNAMELEN];
30477c478bd9Sstevel@tonic-gate 	nis_result *result;
30487c478bd9Sstevel@tonic-gate 
30497c478bd9Sstevel@tonic-gate 	if (tTd(38, 20))
30507c478bd9Sstevel@tonic-gate 		sm_dprintf("nisplus_map_lookup(%s, %s)\n",
30517c478bd9Sstevel@tonic-gate 			map->map_mname, name);
30527c478bd9Sstevel@tonic-gate 
30537c478bd9Sstevel@tonic-gate 	if (!bitset(MF_OPEN, map->map_mflags))
30547c478bd9Sstevel@tonic-gate 	{
30557c478bd9Sstevel@tonic-gate 		if (nisplus_map_open(map, O_RDONLY))
30567c478bd9Sstevel@tonic-gate 		{
30577c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_OPEN;
30587c478bd9Sstevel@tonic-gate 			map->map_pid = CurrentPid;
30597c478bd9Sstevel@tonic-gate 		}
30607c478bd9Sstevel@tonic-gate 		else
30617c478bd9Sstevel@tonic-gate 		{
30627c478bd9Sstevel@tonic-gate 			*statp = EX_UNAVAILABLE;
30637c478bd9Sstevel@tonic-gate 			return NULL;
30647c478bd9Sstevel@tonic-gate 		}
30657c478bd9Sstevel@tonic-gate 	}
30667c478bd9Sstevel@tonic-gate 
30677c478bd9Sstevel@tonic-gate 	/*
30687c478bd9Sstevel@tonic-gate 	**  Copy the name to the key buffer, escaping double quote characters
30697c478bd9Sstevel@tonic-gate 	**  by doubling them and quoting "]" and "," to avoid having the
30707c478bd9Sstevel@tonic-gate 	**  NIS+ parser choke on them.
30717c478bd9Sstevel@tonic-gate 	*/
30727c478bd9Sstevel@tonic-gate 
30737c478bd9Sstevel@tonic-gate 	skleft = sizeof search_key - 4;
30747c478bd9Sstevel@tonic-gate 	skp = search_key;
30757c478bd9Sstevel@tonic-gate 	for (p = name; *p != '\0' && skleft > 0; p++)
30767c478bd9Sstevel@tonic-gate 	{
30777c478bd9Sstevel@tonic-gate 		switch (*p)
30787c478bd9Sstevel@tonic-gate 		{
30797c478bd9Sstevel@tonic-gate 		  case ']':
30807c478bd9Sstevel@tonic-gate 		  case ',':
30817c478bd9Sstevel@tonic-gate 			/* quote the character */
30827c478bd9Sstevel@tonic-gate 			*skp++ = '"';
30837c478bd9Sstevel@tonic-gate 			*skp++ = *p;
30847c478bd9Sstevel@tonic-gate 			*skp++ = '"';
30857c478bd9Sstevel@tonic-gate 			skleft -= 3;
30867c478bd9Sstevel@tonic-gate 			break;
30877c478bd9Sstevel@tonic-gate 
30887c478bd9Sstevel@tonic-gate 		  case '"':
30897c478bd9Sstevel@tonic-gate 			/* double the quote */
30907c478bd9Sstevel@tonic-gate 			*skp++ = '"';
30917c478bd9Sstevel@tonic-gate 			skleft--;
30927c478bd9Sstevel@tonic-gate 			/* FALLTHROUGH */
30937c478bd9Sstevel@tonic-gate 
30947c478bd9Sstevel@tonic-gate 		  default:
30957c478bd9Sstevel@tonic-gate 			*skp++ = *p;
30967c478bd9Sstevel@tonic-gate 			skleft--;
30977c478bd9Sstevel@tonic-gate 			break;
30987c478bd9Sstevel@tonic-gate 		}
30997c478bd9Sstevel@tonic-gate 	}
31007c478bd9Sstevel@tonic-gate 	*skp = '\0';
31017c478bd9Sstevel@tonic-gate 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
31027c478bd9Sstevel@tonic-gate 		makelower(search_key);
31037c478bd9Sstevel@tonic-gate 
31047c478bd9Sstevel@tonic-gate 	/* construct the query */
31057c478bd9Sstevel@tonic-gate 	if (PARTIAL_NAME(map->map_file))
31067c478bd9Sstevel@tonic-gate 		(void) sm_snprintf(qbuf, sizeof qbuf, "[%s=%s],%s.%s",
31077c478bd9Sstevel@tonic-gate 			map->map_keycolnm, search_key, map->map_file,
31087c478bd9Sstevel@tonic-gate 			map->map_domain);
31097c478bd9Sstevel@tonic-gate 	else
31107c478bd9Sstevel@tonic-gate 		(void) sm_snprintf(qbuf, sizeof qbuf, "[%s=%s],%s",
31117c478bd9Sstevel@tonic-gate 			map->map_keycolnm, search_key, map->map_file);
31127c478bd9Sstevel@tonic-gate 
31137c478bd9Sstevel@tonic-gate 	if (tTd(38, 20))
31147c478bd9Sstevel@tonic-gate 		sm_dprintf("qbuf=%s\n", qbuf);
31157c478bd9Sstevel@tonic-gate 	result = nis_list(qbuf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL);
31167c478bd9Sstevel@tonic-gate 	if (result->status == NIS_SUCCESS)
31177c478bd9Sstevel@tonic-gate 	{
31187c478bd9Sstevel@tonic-gate 		int count;
31197c478bd9Sstevel@tonic-gate 		char *str;
31207c478bd9Sstevel@tonic-gate 
31217c478bd9Sstevel@tonic-gate 		if ((count = NIS_RES_NUMOBJ(result)) != 1)
31227c478bd9Sstevel@tonic-gate 		{
31237c478bd9Sstevel@tonic-gate 			if (LogLevel > 10)
31247c478bd9Sstevel@tonic-gate 				sm_syslog(LOG_WARNING, CurEnv->e_id,
31257c478bd9Sstevel@tonic-gate 					  "%s: lookup error, expected 1 entry, got %d",
31267c478bd9Sstevel@tonic-gate 					  map->map_file, count);
31277c478bd9Sstevel@tonic-gate 
31287c478bd9Sstevel@tonic-gate 			/* ignore second entry */
31297c478bd9Sstevel@tonic-gate 			if (tTd(38, 20))
31307c478bd9Sstevel@tonic-gate 				sm_dprintf("nisplus_map_lookup(%s), got %d entries, additional entries ignored\n",
31317c478bd9Sstevel@tonic-gate 					name, count);
31327c478bd9Sstevel@tonic-gate 		}
31337c478bd9Sstevel@tonic-gate 
31347c478bd9Sstevel@tonic-gate 		p = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno));
31357c478bd9Sstevel@tonic-gate 		/* set the length of the result */
31367c478bd9Sstevel@tonic-gate 		if (p == NULL)
31377c478bd9Sstevel@tonic-gate 			p = "";
31387c478bd9Sstevel@tonic-gate 		vsize = strlen(p);
31397c478bd9Sstevel@tonic-gate 		if (tTd(38, 20))
31407c478bd9Sstevel@tonic-gate 			sm_dprintf("nisplus_map_lookup(%s), found %s\n",
31417c478bd9Sstevel@tonic-gate 				name, p);
31427c478bd9Sstevel@tonic-gate 		if (bitset(MF_MATCHONLY, map->map_mflags))
31437c478bd9Sstevel@tonic-gate 			str = map_rewrite(map, name, strlen(name), NULL);
31447c478bd9Sstevel@tonic-gate 		else
31457c478bd9Sstevel@tonic-gate 			str = map_rewrite(map, p, vsize, av);
31467c478bd9Sstevel@tonic-gate 		nis_freeresult(result);
31477c478bd9Sstevel@tonic-gate 		*statp = EX_OK;
31487c478bd9Sstevel@tonic-gate 		return str;
31497c478bd9Sstevel@tonic-gate 	}
31507c478bd9Sstevel@tonic-gate 	else
31517c478bd9Sstevel@tonic-gate 	{
31527c478bd9Sstevel@tonic-gate 		if (result->status == NIS_NOTFOUND)
31537c478bd9Sstevel@tonic-gate 			*statp = EX_NOTFOUND;
31547c478bd9Sstevel@tonic-gate 		else if (result->status == NIS_TRYAGAIN)
31557c478bd9Sstevel@tonic-gate 			*statp = EX_TEMPFAIL;
31567c478bd9Sstevel@tonic-gate 		else
31577c478bd9Sstevel@tonic-gate 		{
31587c478bd9Sstevel@tonic-gate 			*statp = EX_UNAVAILABLE;
31597c478bd9Sstevel@tonic-gate 			map->map_mflags &= ~(MF_VALID|MF_OPEN);
31607c478bd9Sstevel@tonic-gate 		}
31617c478bd9Sstevel@tonic-gate 	}
31627c478bd9Sstevel@tonic-gate 	if (tTd(38, 20))
31637c478bd9Sstevel@tonic-gate 		sm_dprintf("nisplus_map_lookup(%s), failed\n", name);
31647c478bd9Sstevel@tonic-gate 	nis_freeresult(result);
31657c478bd9Sstevel@tonic-gate 	return NULL;
31667c478bd9Sstevel@tonic-gate }
31677c478bd9Sstevel@tonic-gate 
31687c478bd9Sstevel@tonic-gate 
31697c478bd9Sstevel@tonic-gate 
31707c478bd9Sstevel@tonic-gate /*
31717c478bd9Sstevel@tonic-gate **  NISPLUS_GETCANONNAME -- look up canonical name in NIS+
31727c478bd9Sstevel@tonic-gate */
31737c478bd9Sstevel@tonic-gate 
31747c478bd9Sstevel@tonic-gate static bool
31757c478bd9Sstevel@tonic-gate nisplus_getcanonname(name, hbsize, statp)
31767c478bd9Sstevel@tonic-gate 	char *name;
31777c478bd9Sstevel@tonic-gate 	int hbsize;
31787c478bd9Sstevel@tonic-gate 	int *statp;
31797c478bd9Sstevel@tonic-gate {
31807c478bd9Sstevel@tonic-gate 	char *vp;
31817c478bd9Sstevel@tonic-gate 	auto int vsize;
31827c478bd9Sstevel@tonic-gate 	nis_result *result;
31837c478bd9Sstevel@tonic-gate 	char *p;
31847c478bd9Sstevel@tonic-gate 	char nbuf[MAXNAME + 1];
31857c478bd9Sstevel@tonic-gate 	char qbuf[MAXLINE + NIS_MAXNAMELEN];
31867c478bd9Sstevel@tonic-gate 
31877c478bd9Sstevel@tonic-gate 	if (sm_strlcpy(nbuf, name, sizeof nbuf) >= sizeof nbuf)
31887c478bd9Sstevel@tonic-gate 	{
31897c478bd9Sstevel@tonic-gate 		*statp = EX_UNAVAILABLE;
31907c478bd9Sstevel@tonic-gate 		return false;
31917c478bd9Sstevel@tonic-gate 	}
31927c478bd9Sstevel@tonic-gate 	(void) shorten_hostname(nbuf);
31937c478bd9Sstevel@tonic-gate 
31947c478bd9Sstevel@tonic-gate 	p = strchr(nbuf, '.');
31957c478bd9Sstevel@tonic-gate 	if (p == NULL)
31967c478bd9Sstevel@tonic-gate 	{
31977c478bd9Sstevel@tonic-gate 		/* single token */
31987c478bd9Sstevel@tonic-gate 		(void) sm_snprintf(qbuf, sizeof qbuf,
31997c478bd9Sstevel@tonic-gate 			"[name=%s],hosts.org_dir", nbuf);
32007c478bd9Sstevel@tonic-gate 	}
32017c478bd9Sstevel@tonic-gate 	else if (p[1] != '\0')
32027c478bd9Sstevel@tonic-gate 	{
32037c478bd9Sstevel@tonic-gate 		/* multi token -- take only first token in nbuf */
32047c478bd9Sstevel@tonic-gate 		*p = '\0';
32057c478bd9Sstevel@tonic-gate 		(void) sm_snprintf(qbuf, sizeof qbuf,
32067c478bd9Sstevel@tonic-gate 				   "[name=%s],hosts.org_dir.%s", nbuf, &p[1]);
32077c478bd9Sstevel@tonic-gate 	}
32087c478bd9Sstevel@tonic-gate 	else
32097c478bd9Sstevel@tonic-gate 	{
32107c478bd9Sstevel@tonic-gate 		*statp = EX_NOHOST;
32117c478bd9Sstevel@tonic-gate 		return false;
32127c478bd9Sstevel@tonic-gate 	}
32137c478bd9Sstevel@tonic-gate 
32147c478bd9Sstevel@tonic-gate 	if (tTd(38, 20))
32157c478bd9Sstevel@tonic-gate 		sm_dprintf("\nnisplus_getcanonname(%s), qbuf=%s\n",
32167c478bd9Sstevel@tonic-gate 			   name, qbuf);
32177c478bd9Sstevel@tonic-gate 
32187c478bd9Sstevel@tonic-gate 	result = nis_list(qbuf, EXPAND_NAME|FOLLOW_LINKS|FOLLOW_PATH,
32197c478bd9Sstevel@tonic-gate 			  NULL, NULL);
32207c478bd9Sstevel@tonic-gate 
32217c478bd9Sstevel@tonic-gate 	if (result->status == NIS_SUCCESS)
32227c478bd9Sstevel@tonic-gate 	{
32237c478bd9Sstevel@tonic-gate 		int count;
32247c478bd9Sstevel@tonic-gate 		char *domain;
32257c478bd9Sstevel@tonic-gate 
32267c478bd9Sstevel@tonic-gate 		if ((count = NIS_RES_NUMOBJ(result)) != 1)
32277c478bd9Sstevel@tonic-gate 		{
32287c478bd9Sstevel@tonic-gate 			if (LogLevel > 10)
32297c478bd9Sstevel@tonic-gate 				sm_syslog(LOG_WARNING, CurEnv->e_id,
32307c478bd9Sstevel@tonic-gate 					  "nisplus_getcanonname: lookup error, expected 1 entry, got %d",
32317c478bd9Sstevel@tonic-gate 					  count);
32327c478bd9Sstevel@tonic-gate 
32337c478bd9Sstevel@tonic-gate 			/* ignore second entry */
32347c478bd9Sstevel@tonic-gate 			if (tTd(38, 20))
32357c478bd9Sstevel@tonic-gate 				sm_dprintf("nisplus_getcanonname(%s), got %d entries, all but first ignored\n",
32367c478bd9Sstevel@tonic-gate 					   name, count);
32377c478bd9Sstevel@tonic-gate 		}
32387c478bd9Sstevel@tonic-gate 
32397c478bd9Sstevel@tonic-gate 		if (tTd(38, 20))
32407c478bd9Sstevel@tonic-gate 			sm_dprintf("nisplus_getcanonname(%s), found in directory \"%s\"\n",
32417c478bd9Sstevel@tonic-gate 				   name, (NIS_RES_OBJECT(result))->zo_domain);
32427c478bd9Sstevel@tonic-gate 
32437c478bd9Sstevel@tonic-gate 
32447c478bd9Sstevel@tonic-gate 		vp = ((NIS_RES_OBJECT(result))->EN_col(0));
32457c478bd9Sstevel@tonic-gate 		vsize = strlen(vp);
32467c478bd9Sstevel@tonic-gate 		if (tTd(38, 20))
32477c478bd9Sstevel@tonic-gate 			sm_dprintf("nisplus_getcanonname(%s), found %s\n",
32487c478bd9Sstevel@tonic-gate 				   name, vp);
32497c478bd9Sstevel@tonic-gate 		if (strchr(vp, '.') != NULL)
32507c478bd9Sstevel@tonic-gate 		{
32517c478bd9Sstevel@tonic-gate 			domain = "";
32527c478bd9Sstevel@tonic-gate 		}
32537c478bd9Sstevel@tonic-gate 		else
32547c478bd9Sstevel@tonic-gate 		{
32557c478bd9Sstevel@tonic-gate 			domain = macvalue('m', CurEnv);
32567c478bd9Sstevel@tonic-gate 			if (domain == NULL)
32577c478bd9Sstevel@tonic-gate 				domain = "";
32587c478bd9Sstevel@tonic-gate 		}
32597c478bd9Sstevel@tonic-gate 		if (hbsize > vsize + (int) strlen(domain) + 1)
32607c478bd9Sstevel@tonic-gate 		{
32617c478bd9Sstevel@tonic-gate 			if (domain[0] == '\0')
32627c478bd9Sstevel@tonic-gate 				(void) sm_strlcpy(name, vp, hbsize);
32637c478bd9Sstevel@tonic-gate 			else
32647c478bd9Sstevel@tonic-gate 				(void) sm_snprintf(name, hbsize,
32657c478bd9Sstevel@tonic-gate 						   "%s.%s", vp, domain);
32667c478bd9Sstevel@tonic-gate 			*statp = EX_OK;
32677c478bd9Sstevel@tonic-gate 		}
32687c478bd9Sstevel@tonic-gate 		else
32697c478bd9Sstevel@tonic-gate 			*statp = EX_NOHOST;
32707c478bd9Sstevel@tonic-gate 		nis_freeresult(result);
32717c478bd9Sstevel@tonic-gate 		return true;
32727c478bd9Sstevel@tonic-gate 	}
32737c478bd9Sstevel@tonic-gate 	else
32747c478bd9Sstevel@tonic-gate 	{
32757c478bd9Sstevel@tonic-gate 		if (result->status == NIS_NOTFOUND)
32767c478bd9Sstevel@tonic-gate 			*statp = EX_NOHOST;
32777c478bd9Sstevel@tonic-gate 		else if (result->status == NIS_TRYAGAIN)
32787c478bd9Sstevel@tonic-gate 			*statp = EX_TEMPFAIL;
32797c478bd9Sstevel@tonic-gate 		else
32807c478bd9Sstevel@tonic-gate 			*statp = EX_UNAVAILABLE;
32817c478bd9Sstevel@tonic-gate 	}
32827c478bd9Sstevel@tonic-gate 	if (tTd(38, 20))
32837c478bd9Sstevel@tonic-gate 		sm_dprintf("nisplus_getcanonname(%s), failed, status=%d, nsw_stat=%d\n",
32847c478bd9Sstevel@tonic-gate 			   name, result->status, *statp);
32857c478bd9Sstevel@tonic-gate 	nis_freeresult(result);
32867c478bd9Sstevel@tonic-gate 	return false;
32877c478bd9Sstevel@tonic-gate }
32887c478bd9Sstevel@tonic-gate 
32897c478bd9Sstevel@tonic-gate char *
32907c478bd9Sstevel@tonic-gate nisplus_default_domain()
32917c478bd9Sstevel@tonic-gate {
32927c478bd9Sstevel@tonic-gate 	static char default_domain[MAXNAME + 1] = "";
32937c478bd9Sstevel@tonic-gate 	char *p;
32947c478bd9Sstevel@tonic-gate 
32957c478bd9Sstevel@tonic-gate 	if (default_domain[0] != '\0')
32967c478bd9Sstevel@tonic-gate 		return default_domain;
32977c478bd9Sstevel@tonic-gate 
32987c478bd9Sstevel@tonic-gate 	p = nis_local_directory();
32997c478bd9Sstevel@tonic-gate 	(void) sm_strlcpy(default_domain, p, sizeof default_domain);
33007c478bd9Sstevel@tonic-gate 	return default_domain;
33017c478bd9Sstevel@tonic-gate }
33027c478bd9Sstevel@tonic-gate 
33037c478bd9Sstevel@tonic-gate #endif /* NISPLUS */
33047c478bd9Sstevel@tonic-gate /*
33057c478bd9Sstevel@tonic-gate **  LDAP Modules
33067c478bd9Sstevel@tonic-gate */
33077c478bd9Sstevel@tonic-gate 
33087c478bd9Sstevel@tonic-gate /*
33097c478bd9Sstevel@tonic-gate **  LDAPMAP_DEQUOTE - helper routine for ldapmap_parseargs
33107c478bd9Sstevel@tonic-gate */
33117c478bd9Sstevel@tonic-gate 
33127c478bd9Sstevel@tonic-gate #if defined(LDAPMAP) || defined(PH_MAP)
33137c478bd9Sstevel@tonic-gate 
33147c478bd9Sstevel@tonic-gate # if PH_MAP
33157c478bd9Sstevel@tonic-gate #  define ph_map_dequote ldapmap_dequote
33167c478bd9Sstevel@tonic-gate # endif /* PH_MAP */
33177c478bd9Sstevel@tonic-gate 
33187c478bd9Sstevel@tonic-gate static char *ldapmap_dequote __P((char *));
33197c478bd9Sstevel@tonic-gate 
33207c478bd9Sstevel@tonic-gate static char *
33217c478bd9Sstevel@tonic-gate ldapmap_dequote(str)
33227c478bd9Sstevel@tonic-gate 	char *str;
33237c478bd9Sstevel@tonic-gate {
33247c478bd9Sstevel@tonic-gate 	char *p;
33257c478bd9Sstevel@tonic-gate 	char *start;
33267c478bd9Sstevel@tonic-gate 
33277c478bd9Sstevel@tonic-gate 	if (str == NULL)
33287c478bd9Sstevel@tonic-gate 		return NULL;
33297c478bd9Sstevel@tonic-gate 
33307c478bd9Sstevel@tonic-gate 	p = str;
33317c478bd9Sstevel@tonic-gate 	if (*p == '"')
33327c478bd9Sstevel@tonic-gate 	{
33337c478bd9Sstevel@tonic-gate 		/* Should probably swallow initial whitespace here */
33347c478bd9Sstevel@tonic-gate 		start = ++p;
33357c478bd9Sstevel@tonic-gate 	}
33367c478bd9Sstevel@tonic-gate 	else
33377c478bd9Sstevel@tonic-gate 		return str;
33387c478bd9Sstevel@tonic-gate 	while (*p != '"' && *p != '\0')
33397c478bd9Sstevel@tonic-gate 		p++;
33407c478bd9Sstevel@tonic-gate 	if (*p != '\0')
33417c478bd9Sstevel@tonic-gate 		*p = '\0';
33427c478bd9Sstevel@tonic-gate 	return start;
33437c478bd9Sstevel@tonic-gate }
33447c478bd9Sstevel@tonic-gate #endif /* defined(LDAPMAP) || defined(PH_MAP) */
33457c478bd9Sstevel@tonic-gate 
33467c478bd9Sstevel@tonic-gate #if LDAPMAP
33477c478bd9Sstevel@tonic-gate 
33487c478bd9Sstevel@tonic-gate static SM_LDAP_STRUCT *LDAPDefaults = NULL;
33497c478bd9Sstevel@tonic-gate 
33507c478bd9Sstevel@tonic-gate /*
33517c478bd9Sstevel@tonic-gate **  LDAPMAP_OPEN -- open LDAP map
33527c478bd9Sstevel@tonic-gate **
33537c478bd9Sstevel@tonic-gate **	Connect to the LDAP server.  Re-use existing connections since a
33547c478bd9Sstevel@tonic-gate **	single server connection to a host (with the same host, port,
33557c478bd9Sstevel@tonic-gate **	bind DN, and secret) can answer queries for multiple maps.
33567c478bd9Sstevel@tonic-gate */
33577c478bd9Sstevel@tonic-gate 
33587c478bd9Sstevel@tonic-gate bool
33597c478bd9Sstevel@tonic-gate ldapmap_open(map, mode)
33607c478bd9Sstevel@tonic-gate 	MAP *map;
33617c478bd9Sstevel@tonic-gate 	int mode;
33627c478bd9Sstevel@tonic-gate {
33637c478bd9Sstevel@tonic-gate 	SM_LDAP_STRUCT *lmap;
33647c478bd9Sstevel@tonic-gate 	STAB *s;
33657c478bd9Sstevel@tonic-gate 	char *id;
33667c478bd9Sstevel@tonic-gate 
33677c478bd9Sstevel@tonic-gate 	if (tTd(38, 2))
33687c478bd9Sstevel@tonic-gate 		sm_dprintf("ldapmap_open(%s, %d): ", map->map_mname, mode);
33697c478bd9Sstevel@tonic-gate 
33707c478bd9Sstevel@tonic-gate #if defined(SUN_EXTENSIONS) && defined(SUN_SIMPLIFIED_LDAP) && \
33717c478bd9Sstevel@tonic-gate     defined(HASLDAPGETALIASBYNAME)
33727c478bd9Sstevel@tonic-gate 	if (VendorCode == VENDOR_SUN &&
33737c478bd9Sstevel@tonic-gate 	    strcmp(map->map_mname, "aliases.ldap") == 0)
33747c478bd9Sstevel@tonic-gate 	{
33757c478bd9Sstevel@tonic-gate 		return true;
33767c478bd9Sstevel@tonic-gate 	}
33777c478bd9Sstevel@tonic-gate #endif
33787c478bd9Sstevel@tonic-gate 
33797c478bd9Sstevel@tonic-gate 	mode &= O_ACCMODE;
33807c478bd9Sstevel@tonic-gate 
33817c478bd9Sstevel@tonic-gate 	/* sendmail doesn't have the ability to write to LDAP (yet) */
33827c478bd9Sstevel@tonic-gate 	if (mode != O_RDONLY)
33837c478bd9Sstevel@tonic-gate 	{
33847c478bd9Sstevel@tonic-gate 		/* issue a pseudo-error message */
33857c478bd9Sstevel@tonic-gate 		errno = SM_EMAPCANTWRITE;
33867c478bd9Sstevel@tonic-gate 		return false;
33877c478bd9Sstevel@tonic-gate 	}
33887c478bd9Sstevel@tonic-gate 
33897c478bd9Sstevel@tonic-gate 	lmap = (SM_LDAP_STRUCT *) map->map_db1;
33907c478bd9Sstevel@tonic-gate 
33917c478bd9Sstevel@tonic-gate 	s = ldapmap_findconn(lmap);
33927c478bd9Sstevel@tonic-gate 	if (s->s_lmap != NULL)
33937c478bd9Sstevel@tonic-gate 	{
33947c478bd9Sstevel@tonic-gate 		/* Already have a connection open to this LDAP server */
33957c478bd9Sstevel@tonic-gate 		lmap->ldap_ld = ((SM_LDAP_STRUCT *)s->s_lmap->map_db1)->ldap_ld;
33967c478bd9Sstevel@tonic-gate 		lmap->ldap_pid = ((SM_LDAP_STRUCT *)s->s_lmap->map_db1)->ldap_pid;
33977c478bd9Sstevel@tonic-gate 
33987c478bd9Sstevel@tonic-gate 		/* Add this map as head of linked list */
33997c478bd9Sstevel@tonic-gate 		lmap->ldap_next = s->s_lmap;
34007c478bd9Sstevel@tonic-gate 		s->s_lmap = map;
34017c478bd9Sstevel@tonic-gate 
34027c478bd9Sstevel@tonic-gate 		if (tTd(38, 2))
34037c478bd9Sstevel@tonic-gate 			sm_dprintf("using cached connection\n");
34047c478bd9Sstevel@tonic-gate 		return true;
34057c478bd9Sstevel@tonic-gate 	}
34067c478bd9Sstevel@tonic-gate 
34077c478bd9Sstevel@tonic-gate 	if (tTd(38, 2))
34087c478bd9Sstevel@tonic-gate 		sm_dprintf("opening new connection\n");
34097c478bd9Sstevel@tonic-gate 
34107c478bd9Sstevel@tonic-gate 	if (lmap->ldap_host != NULL)
34117c478bd9Sstevel@tonic-gate 		id = lmap->ldap_host;
34127c478bd9Sstevel@tonic-gate 	else if (lmap->ldap_uri != NULL)
34137c478bd9Sstevel@tonic-gate 		id = lmap->ldap_uri;
34147c478bd9Sstevel@tonic-gate 	else
34157c478bd9Sstevel@tonic-gate 		id = "localhost";
34167c478bd9Sstevel@tonic-gate 
34177c478bd9Sstevel@tonic-gate 	/* No connection yet, connect */
34187c478bd9Sstevel@tonic-gate 	if (!sm_ldap_start(map->map_mname, lmap))
34197c478bd9Sstevel@tonic-gate 	{
34207c478bd9Sstevel@tonic-gate 		if (errno == ETIMEDOUT)
34217c478bd9Sstevel@tonic-gate 		{
34227c478bd9Sstevel@tonic-gate 			if (LogLevel > 1)
34237c478bd9Sstevel@tonic-gate 				sm_syslog(LOG_NOTICE, CurEnv->e_id,
34247c478bd9Sstevel@tonic-gate 					  "timeout conning to LDAP server %.100s",
34257c478bd9Sstevel@tonic-gate 					  id);
34267c478bd9Sstevel@tonic-gate 		}
34277c478bd9Sstevel@tonic-gate 
34287c478bd9Sstevel@tonic-gate 		if (!bitset(MF_OPTIONAL, map->map_mflags))
34297c478bd9Sstevel@tonic-gate 		{
34307c478bd9Sstevel@tonic-gate 			if (bitset(MF_NODEFER, map->map_mflags))
34317c478bd9Sstevel@tonic-gate 			{
34327c478bd9Sstevel@tonic-gate 				syserr("%s failed to %s in map %s",
34337c478bd9Sstevel@tonic-gate # if USE_LDAP_INIT
34347c478bd9Sstevel@tonic-gate 				       "ldap_init/ldap_bind",
34357c478bd9Sstevel@tonic-gate # else /* USE_LDAP_INIT */
34367c478bd9Sstevel@tonic-gate 				       "ldap_open",
34377c478bd9Sstevel@tonic-gate # endif /* USE_LDAP_INIT */
34387c478bd9Sstevel@tonic-gate 				       id, map->map_mname);
34397c478bd9Sstevel@tonic-gate 			}
34407c478bd9Sstevel@tonic-gate 			else
34417c478bd9Sstevel@tonic-gate 			{
34427c478bd9Sstevel@tonic-gate 				syserr("451 4.3.5 %s failed to %s in map %s",
34437c478bd9Sstevel@tonic-gate # if USE_LDAP_INIT
34447c478bd9Sstevel@tonic-gate 				       "ldap_init/ldap_bind",
34457c478bd9Sstevel@tonic-gate # else /* USE_LDAP_INIT */
34467c478bd9Sstevel@tonic-gate 				       "ldap_open",
34477c478bd9Sstevel@tonic-gate # endif /* USE_LDAP_INIT */
34487c478bd9Sstevel@tonic-gate 				       id, map->map_mname);
34497c478bd9Sstevel@tonic-gate 			}
34507c478bd9Sstevel@tonic-gate 		}
34517c478bd9Sstevel@tonic-gate 		return false;
34527c478bd9Sstevel@tonic-gate 	}
34537c478bd9Sstevel@tonic-gate 
34547c478bd9Sstevel@tonic-gate 	/* Save connection for reuse */
34557c478bd9Sstevel@tonic-gate 	s->s_lmap = map;
34567c478bd9Sstevel@tonic-gate 	return true;
34577c478bd9Sstevel@tonic-gate }
34587c478bd9Sstevel@tonic-gate 
34597c478bd9Sstevel@tonic-gate /*
34607c478bd9Sstevel@tonic-gate **  LDAPMAP_CLOSE -- close ldap map
34617c478bd9Sstevel@tonic-gate */
34627c478bd9Sstevel@tonic-gate 
34637c478bd9Sstevel@tonic-gate void
34647c478bd9Sstevel@tonic-gate ldapmap_close(map)
34657c478bd9Sstevel@tonic-gate 	MAP *map;
34667c478bd9Sstevel@tonic-gate {
34677c478bd9Sstevel@tonic-gate 	SM_LDAP_STRUCT *lmap;
34687c478bd9Sstevel@tonic-gate 	STAB *s;
34697c478bd9Sstevel@tonic-gate 
34707c478bd9Sstevel@tonic-gate 	if (tTd(38, 2))
34717c478bd9Sstevel@tonic-gate 		sm_dprintf("ldapmap_close(%s)\n", map->map_mname);
34727c478bd9Sstevel@tonic-gate 
34737c478bd9Sstevel@tonic-gate 	lmap = (SM_LDAP_STRUCT *) map->map_db1;
34747c478bd9Sstevel@tonic-gate 
34757c478bd9Sstevel@tonic-gate 	/* Check if already closed */
34767c478bd9Sstevel@tonic-gate 	if (lmap->ldap_ld == NULL)
34777c478bd9Sstevel@tonic-gate 		return;
34787c478bd9Sstevel@tonic-gate 
34797c478bd9Sstevel@tonic-gate 	/* Close the LDAP connection */
34807c478bd9Sstevel@tonic-gate 	sm_ldap_close(lmap);
34817c478bd9Sstevel@tonic-gate 
34827c478bd9Sstevel@tonic-gate 	/* Mark all the maps that share the connection as closed */
34837c478bd9Sstevel@tonic-gate 	s = ldapmap_findconn(lmap);
34847c478bd9Sstevel@tonic-gate 
34857c478bd9Sstevel@tonic-gate 	while (s->s_lmap != NULL)
34867c478bd9Sstevel@tonic-gate 	{
34877c478bd9Sstevel@tonic-gate 		MAP *smap = s->s_lmap;
34887c478bd9Sstevel@tonic-gate 
34897c478bd9Sstevel@tonic-gate 		if (tTd(38, 2) && smap != map)
34907c478bd9Sstevel@tonic-gate 			sm_dprintf("ldapmap_close(%s): closed %s (shared LDAP connection)\n",
34917c478bd9Sstevel@tonic-gate 				   map->map_mname, smap->map_mname);
34927c478bd9Sstevel@tonic-gate 		smap->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
34937c478bd9Sstevel@tonic-gate 		lmap = (SM_LDAP_STRUCT *) smap->map_db1;
34947c478bd9Sstevel@tonic-gate 		lmap->ldap_ld = NULL;
34957c478bd9Sstevel@tonic-gate 		s->s_lmap = lmap->ldap_next;
34967c478bd9Sstevel@tonic-gate 		lmap->ldap_next = NULL;
34977c478bd9Sstevel@tonic-gate 	}
34987c478bd9Sstevel@tonic-gate }
34997c478bd9Sstevel@tonic-gate 
35007c478bd9Sstevel@tonic-gate # ifdef SUNET_ID
35017c478bd9Sstevel@tonic-gate /*
35027c478bd9Sstevel@tonic-gate **  SUNET_ID_HASH -- Convert a string to its Sunet_id canonical form
35037c478bd9Sstevel@tonic-gate **  This only makes sense at Stanford University.
35047c478bd9Sstevel@tonic-gate */
35057c478bd9Sstevel@tonic-gate 
35067c478bd9Sstevel@tonic-gate static char *
35077c478bd9Sstevel@tonic-gate sunet_id_hash(str)
35087c478bd9Sstevel@tonic-gate 	char *str;
35097c478bd9Sstevel@tonic-gate {
35107c478bd9Sstevel@tonic-gate 	char *p, *p_last;
35117c478bd9Sstevel@tonic-gate 
35127c478bd9Sstevel@tonic-gate 	p = str;
35137c478bd9Sstevel@tonic-gate 	p_last = p;
35147c478bd9Sstevel@tonic-gate 	while (*p != '\0')
35157c478bd9Sstevel@tonic-gate 	{
35167c478bd9Sstevel@tonic-gate 		if (islower(*p) || isdigit(*p))
35177c478bd9Sstevel@tonic-gate 		{
35187c478bd9Sstevel@tonic-gate 			*p_last = *p;
35197c478bd9Sstevel@tonic-gate 			p_last++;
35207c478bd9Sstevel@tonic-gate 		}
35217c478bd9Sstevel@tonic-gate 		else if (isupper(*p))
35227c478bd9Sstevel@tonic-gate 		{
35237c478bd9Sstevel@tonic-gate 			*p_last = tolower(*p);
35247c478bd9Sstevel@tonic-gate 			p_last++;
35257c478bd9Sstevel@tonic-gate 		}
35267c478bd9Sstevel@tonic-gate 		++p;
35277c478bd9Sstevel@tonic-gate 	}
35287c478bd9Sstevel@tonic-gate 	if (*p_last != '\0')
35297c478bd9Sstevel@tonic-gate 		*p_last = '\0';
35307c478bd9Sstevel@tonic-gate 	return str;
35317c478bd9Sstevel@tonic-gate }
35327c478bd9Sstevel@tonic-gate # endif /* SUNET_ID */
35337c478bd9Sstevel@tonic-gate 
35347c478bd9Sstevel@tonic-gate /*
35357c478bd9Sstevel@tonic-gate **  LDAPMAP_LOOKUP -- look up a datum in a LDAP map
35367c478bd9Sstevel@tonic-gate */
35377c478bd9Sstevel@tonic-gate 
35387c478bd9Sstevel@tonic-gate char *
35397c478bd9Sstevel@tonic-gate ldapmap_lookup(map, name, av, statp)
35407c478bd9Sstevel@tonic-gate 	MAP *map;
35417c478bd9Sstevel@tonic-gate 	char *name;
35427c478bd9Sstevel@tonic-gate 	char **av;
35437c478bd9Sstevel@tonic-gate 	int *statp;
35447c478bd9Sstevel@tonic-gate {
35457c478bd9Sstevel@tonic-gate 	int flags;
35467c478bd9Sstevel@tonic-gate 	int plen = 0;
35477c478bd9Sstevel@tonic-gate 	int psize = 0;
35487c478bd9Sstevel@tonic-gate 	int msgid;
35497c478bd9Sstevel@tonic-gate 	int save_errno;
35507c478bd9Sstevel@tonic-gate 	char *vp, *p;
35517c478bd9Sstevel@tonic-gate 	char *result = NULL;
35527c478bd9Sstevel@tonic-gate 	SM_RPOOL_T *rpool;
35537c478bd9Sstevel@tonic-gate 	SM_LDAP_STRUCT *lmap = NULL;
3554445f2479Sjbeck 	char keybuf[MAXKEY];
35557c478bd9Sstevel@tonic-gate 
35567c478bd9Sstevel@tonic-gate 	if (tTd(38, 20))
35577c478bd9Sstevel@tonic-gate 		sm_dprintf("ldapmap_lookup(%s, %s)\n", map->map_mname, name);
35587c478bd9Sstevel@tonic-gate 
35597c478bd9Sstevel@tonic-gate #if defined(SUN_EXTENSIONS) && defined(SUN_SIMPLIFIED_LDAP) && \
35607c478bd9Sstevel@tonic-gate     defined(HASLDAPGETALIASBYNAME)
35617c478bd9Sstevel@tonic-gate 	if (VendorCode == VENDOR_SUN &&
35627c478bd9Sstevel@tonic-gate 	    strcmp(map->map_mname, "aliases.ldap") == 0)
35637c478bd9Sstevel@tonic-gate 	{
35647c478bd9Sstevel@tonic-gate 		char answer[MAXNAME + 1];
35657c478bd9Sstevel@tonic-gate 		int rc;
35667c478bd9Sstevel@tonic-gate 
35677c478bd9Sstevel@tonic-gate 		rc = __getldapaliasbyname(name, answer, sizeof(answer));
35687c478bd9Sstevel@tonic-gate 		if (rc != 0)
35697c478bd9Sstevel@tonic-gate 		{
35707c478bd9Sstevel@tonic-gate 			if (tTd(38, 20))
35717c478bd9Sstevel@tonic-gate 				sm_dprintf("getldapaliasbyname(%.100s) failed, errno=%d\n",
35727c478bd9Sstevel@tonic-gate 					   name, errno);
35737c478bd9Sstevel@tonic-gate 			*statp = EX_NOTFOUND;
35747c478bd9Sstevel@tonic-gate 			return NULL;
35757c478bd9Sstevel@tonic-gate 		}
35767c478bd9Sstevel@tonic-gate 		*statp = EX_OK;
35777c478bd9Sstevel@tonic-gate 		if (tTd(38, 20))
35787c478bd9Sstevel@tonic-gate 			sm_dprintf("getldapaliasbyname(%.100s) => %s\n", name,
35797c478bd9Sstevel@tonic-gate 				   answer);
35807c478bd9Sstevel@tonic-gate 		if (bitset(MF_MATCHONLY, map->map_mflags))
35817c478bd9Sstevel@tonic-gate 			result = map_rewrite(map, name, strlen(name), NULL);
35827c478bd9Sstevel@tonic-gate 		else
35837c478bd9Sstevel@tonic-gate 			result = map_rewrite(map, answer, strlen(answer), av);
35847c478bd9Sstevel@tonic-gate 		return result;
35857c478bd9Sstevel@tonic-gate 	}
35867c478bd9Sstevel@tonic-gate #endif
35877c478bd9Sstevel@tonic-gate 
35887c478bd9Sstevel@tonic-gate 	/* Get ldap struct pointer from map */
35897c478bd9Sstevel@tonic-gate 	lmap = (SM_LDAP_STRUCT *) map->map_db1;
35907c478bd9Sstevel@tonic-gate 	sm_ldap_setopts(lmap->ldap_ld, lmap);
35917c478bd9Sstevel@tonic-gate 
35927c478bd9Sstevel@tonic-gate 	(void) sm_strlcpy(keybuf, name, sizeof keybuf);
35937c478bd9Sstevel@tonic-gate 
35947c478bd9Sstevel@tonic-gate 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
35957c478bd9Sstevel@tonic-gate 	{
35967c478bd9Sstevel@tonic-gate # ifdef SUNET_ID
35977c478bd9Sstevel@tonic-gate 		sunet_id_hash(keybuf);
35987c478bd9Sstevel@tonic-gate # else /* SUNET_ID */
35997c478bd9Sstevel@tonic-gate 		makelower(keybuf);
36007c478bd9Sstevel@tonic-gate # endif /* SUNET_ID */
36017c478bd9Sstevel@tonic-gate 	}
36027c478bd9Sstevel@tonic-gate 
36037c478bd9Sstevel@tonic-gate 	msgid = sm_ldap_search(lmap, keybuf);
36047c478bd9Sstevel@tonic-gate 	if (msgid == -1)
36057c478bd9Sstevel@tonic-gate 	{
36067c478bd9Sstevel@tonic-gate 		errno = sm_ldap_geterrno(lmap->ldap_ld) + E_LDAPBASE;
36077c478bd9Sstevel@tonic-gate 		save_errno = errno;
36087c478bd9Sstevel@tonic-gate 		if (!bitset(MF_OPTIONAL, map->map_mflags))
36097c478bd9Sstevel@tonic-gate 		{
36107c478bd9Sstevel@tonic-gate 			if (bitset(MF_NODEFER, map->map_mflags))
36117c478bd9Sstevel@tonic-gate 				syserr("Error in ldap_search using %s in map %s",
36127c478bd9Sstevel@tonic-gate 				       keybuf, map->map_mname);
36137c478bd9Sstevel@tonic-gate 			else
36147c478bd9Sstevel@tonic-gate 				syserr("451 4.3.5 Error in ldap_search using %s in map %s",
36157c478bd9Sstevel@tonic-gate 				       keybuf, map->map_mname);
36167c478bd9Sstevel@tonic-gate 		}
36177c478bd9Sstevel@tonic-gate 		*statp = EX_TEMPFAIL;
36187c478bd9Sstevel@tonic-gate 		switch (save_errno - E_LDAPBASE)
36197c478bd9Sstevel@tonic-gate 		{
36207c478bd9Sstevel@tonic-gate # ifdef LDAP_SERVER_DOWN
36217c478bd9Sstevel@tonic-gate 		  case LDAP_SERVER_DOWN:
36227c478bd9Sstevel@tonic-gate # endif /* LDAP_SERVER_DOWN */
36237c478bd9Sstevel@tonic-gate 		  case LDAP_TIMEOUT:
36247c478bd9Sstevel@tonic-gate 		  case LDAP_UNAVAILABLE:
36257c478bd9Sstevel@tonic-gate 			/* server disappeared, try reopen on next search */
36267c478bd9Sstevel@tonic-gate 			ldapmap_close(map);
36277c478bd9Sstevel@tonic-gate 			break;
36287c478bd9Sstevel@tonic-gate 		}
36297c478bd9Sstevel@tonic-gate 		errno = save_errno;
36307c478bd9Sstevel@tonic-gate 		return NULL;
36317c478bd9Sstevel@tonic-gate 	}
36327c478bd9Sstevel@tonic-gate 
36337c478bd9Sstevel@tonic-gate 	*statp = EX_NOTFOUND;
36347c478bd9Sstevel@tonic-gate 	vp = NULL;
36357c478bd9Sstevel@tonic-gate 
36367c478bd9Sstevel@tonic-gate 	flags = 0;
36377c478bd9Sstevel@tonic-gate 	if (bitset(MF_SINGLEMATCH, map->map_mflags))
36387c478bd9Sstevel@tonic-gate 		flags |= SM_LDAP_SINGLEMATCH;
36397c478bd9Sstevel@tonic-gate 	if (bitset(MF_MATCHONLY, map->map_mflags))
36407c478bd9Sstevel@tonic-gate 		flags |= SM_LDAP_MATCHONLY;
364149218d4fSjbeck # if _FFR_LDAP_SINGLEDN
364249218d4fSjbeck 	if (bitset(MF_SINGLEDN, map->map_mflags))
364349218d4fSjbeck 		flags |= SM_LDAP_SINGLEDN;
364449218d4fSjbeck # endif /* _FFR_LDAP_SINGLEDN */
36457c478bd9Sstevel@tonic-gate 
36467c478bd9Sstevel@tonic-gate 	/* Create an rpool for search related memory usage */
36477c478bd9Sstevel@tonic-gate 	rpool = sm_rpool_new_x(NULL);
36487c478bd9Sstevel@tonic-gate 
36497c478bd9Sstevel@tonic-gate 	p = NULL;
36507c478bd9Sstevel@tonic-gate 	*statp = sm_ldap_results(lmap, msgid, flags, map->map_coldelim,
36517c478bd9Sstevel@tonic-gate 				 rpool, &p, &plen, &psize, NULL);
36527c478bd9Sstevel@tonic-gate 	save_errno = errno;
36537c478bd9Sstevel@tonic-gate 
36547c478bd9Sstevel@tonic-gate 	/* Copy result so rpool can be freed */
36557c478bd9Sstevel@tonic-gate 	if (*statp == EX_OK && p != NULL)
36567c478bd9Sstevel@tonic-gate 		vp = newstr(p);
36577c478bd9Sstevel@tonic-gate 	sm_rpool_free(rpool);
36587c478bd9Sstevel@tonic-gate 
36597c478bd9Sstevel@tonic-gate 	/* need to restart LDAP connection? */
36607c478bd9Sstevel@tonic-gate 	if (*statp == EX_RESTART)
36617c478bd9Sstevel@tonic-gate 	{
36627c478bd9Sstevel@tonic-gate 		*statp = EX_TEMPFAIL;
36637c478bd9Sstevel@tonic-gate 		ldapmap_close(map);
36647c478bd9Sstevel@tonic-gate 	}
36657c478bd9Sstevel@tonic-gate 
36667c478bd9Sstevel@tonic-gate 	errno = save_errno;
36677c478bd9Sstevel@tonic-gate 	if (*statp != EX_OK && *statp != EX_NOTFOUND)
36687c478bd9Sstevel@tonic-gate 	{
36697c478bd9Sstevel@tonic-gate 		if (!bitset(MF_OPTIONAL, map->map_mflags))
36707c478bd9Sstevel@tonic-gate 		{
36717c478bd9Sstevel@tonic-gate 			if (bitset(MF_NODEFER, map->map_mflags))
36727c478bd9Sstevel@tonic-gate 				syserr("Error getting LDAP results in map %s",
36737c478bd9Sstevel@tonic-gate 				       map->map_mname);
36747c478bd9Sstevel@tonic-gate 			else
36757c478bd9Sstevel@tonic-gate 				syserr("451 4.3.5 Error getting LDAP results in map %s",
36767c478bd9Sstevel@tonic-gate 				       map->map_mname);
36777c478bd9Sstevel@tonic-gate 		}
36787c478bd9Sstevel@tonic-gate 		errno = save_errno;
36797c478bd9Sstevel@tonic-gate 		return NULL;
36807c478bd9Sstevel@tonic-gate 	}
36817c478bd9Sstevel@tonic-gate 
36827c478bd9Sstevel@tonic-gate 	/* Did we match anything? */
36837c478bd9Sstevel@tonic-gate 	if (vp == NULL && !bitset(MF_MATCHONLY, map->map_mflags))
36847c478bd9Sstevel@tonic-gate 		return NULL;
36857c478bd9Sstevel@tonic-gate 
36867c478bd9Sstevel@tonic-gate 	if (*statp == EX_OK)
36877c478bd9Sstevel@tonic-gate 	{
36887c478bd9Sstevel@tonic-gate 		if (LogLevel > 9)
36897c478bd9Sstevel@tonic-gate 			sm_syslog(LOG_INFO, CurEnv->e_id,
36907c478bd9Sstevel@tonic-gate 				  "ldap %.100s => %s", name,
36917c478bd9Sstevel@tonic-gate 				  vp == NULL ? "<NULL>" : vp);
36927c478bd9Sstevel@tonic-gate 		if (bitset(MF_MATCHONLY, map->map_mflags))
36937c478bd9Sstevel@tonic-gate 			result = map_rewrite(map, name, strlen(name), NULL);
36947c478bd9Sstevel@tonic-gate 		else
36957c478bd9Sstevel@tonic-gate 		{
36967c478bd9Sstevel@tonic-gate 			/* vp != NULL according to test above */
36977c478bd9Sstevel@tonic-gate 			result = map_rewrite(map, vp, strlen(vp), av);
36987c478bd9Sstevel@tonic-gate 		}
36997c478bd9Sstevel@tonic-gate 		if (vp != NULL)
37007c478bd9Sstevel@tonic-gate 			sm_free(vp); /* XXX */
37017c478bd9Sstevel@tonic-gate 	}
37027c478bd9Sstevel@tonic-gate 	return result;
37037c478bd9Sstevel@tonic-gate }
37047c478bd9Sstevel@tonic-gate 
37057c478bd9Sstevel@tonic-gate /*
37067c478bd9Sstevel@tonic-gate **  LDAPMAP_FINDCONN -- find an LDAP connection to the server
37077c478bd9Sstevel@tonic-gate **
37087c478bd9Sstevel@tonic-gate **	Cache LDAP connections based on the host, port, bind DN,
37097c478bd9Sstevel@tonic-gate **	secret, and PID so we don't have multiple connections open to
37107c478bd9Sstevel@tonic-gate **	the same server for different maps.  Need a separate connection
37117c478bd9Sstevel@tonic-gate **	per PID since a parent process may close the map before the
37127c478bd9Sstevel@tonic-gate **	child is done with it.
37137c478bd9Sstevel@tonic-gate **
37147c478bd9Sstevel@tonic-gate **	Parameters:
37157c478bd9Sstevel@tonic-gate **		lmap -- LDAP map information
37167c478bd9Sstevel@tonic-gate **
37177c478bd9Sstevel@tonic-gate **	Returns:
37187c478bd9Sstevel@tonic-gate **		Symbol table entry for the LDAP connection.
37197c478bd9Sstevel@tonic-gate */
37207c478bd9Sstevel@tonic-gate 
37217c478bd9Sstevel@tonic-gate static STAB *
37227c478bd9Sstevel@tonic-gate ldapmap_findconn(lmap)
37237c478bd9Sstevel@tonic-gate 	SM_LDAP_STRUCT *lmap;
37247c478bd9Sstevel@tonic-gate {
37257c478bd9Sstevel@tonic-gate 	char *format;
37267c478bd9Sstevel@tonic-gate 	char *nbuf;
37277c478bd9Sstevel@tonic-gate 	char *id;
37287c478bd9Sstevel@tonic-gate 	STAB *SM_NONVOLATILE s = NULL;
37297c478bd9Sstevel@tonic-gate 
37307c478bd9Sstevel@tonic-gate 	if (lmap->ldap_host != NULL)
37317c478bd9Sstevel@tonic-gate 		id = lmap->ldap_host;
37327c478bd9Sstevel@tonic-gate 	else if (lmap->ldap_uri != NULL)
37337c478bd9Sstevel@tonic-gate 		id = lmap->ldap_uri;
37347c478bd9Sstevel@tonic-gate 	else
37357c478bd9Sstevel@tonic-gate 		id = "localhost";
37367c478bd9Sstevel@tonic-gate 
37377c478bd9Sstevel@tonic-gate 	format = "%s%c%d%c%d%c%s%c%s%d";
37387c478bd9Sstevel@tonic-gate 	nbuf = sm_stringf_x(format,
37397c478bd9Sstevel@tonic-gate 			    id,
37407c478bd9Sstevel@tonic-gate 			    CONDELSE,
37417c478bd9Sstevel@tonic-gate 			    lmap->ldap_port,
37427c478bd9Sstevel@tonic-gate 			    CONDELSE,
37437c478bd9Sstevel@tonic-gate 			    lmap->ldap_version,
37447c478bd9Sstevel@tonic-gate 			    CONDELSE,
37457c478bd9Sstevel@tonic-gate 			    (lmap->ldap_binddn == NULL ? ""
37467c478bd9Sstevel@tonic-gate 						       : lmap->ldap_binddn),
37477c478bd9Sstevel@tonic-gate 			    CONDELSE,
37487c478bd9Sstevel@tonic-gate 			    (lmap->ldap_secret == NULL ? ""
37497c478bd9Sstevel@tonic-gate 						       : lmap->ldap_secret),
37507c478bd9Sstevel@tonic-gate 			    (int) CurrentPid);
37517c478bd9Sstevel@tonic-gate 	SM_TRY
37527c478bd9Sstevel@tonic-gate 		s = stab(nbuf, ST_LMAP, ST_ENTER);
37537c478bd9Sstevel@tonic-gate 	SM_FINALLY
37547c478bd9Sstevel@tonic-gate 		sm_free(nbuf);
37557c478bd9Sstevel@tonic-gate 	SM_END_TRY
37567c478bd9Sstevel@tonic-gate 	return s;
37577c478bd9Sstevel@tonic-gate }
37587c478bd9Sstevel@tonic-gate /*
37597c478bd9Sstevel@tonic-gate **  LDAPMAP_PARSEARGS -- parse ldap map definition args.
37607c478bd9Sstevel@tonic-gate */
37617c478bd9Sstevel@tonic-gate 
37627c478bd9Sstevel@tonic-gate static struct lamvalues LDAPAuthMethods[] =
37637c478bd9Sstevel@tonic-gate {
37647c478bd9Sstevel@tonic-gate 	{	"none",		LDAP_AUTH_NONE		},
37657c478bd9Sstevel@tonic-gate 	{	"simple",	LDAP_AUTH_SIMPLE	},
37667c478bd9Sstevel@tonic-gate # ifdef LDAP_AUTH_KRBV4
37677c478bd9Sstevel@tonic-gate 	{	"krbv4",	LDAP_AUTH_KRBV4		},
37687c478bd9Sstevel@tonic-gate # endif /* LDAP_AUTH_KRBV4 */
37697c478bd9Sstevel@tonic-gate 	{	NULL,		0			}
37707c478bd9Sstevel@tonic-gate };
37717c478bd9Sstevel@tonic-gate 
37727c478bd9Sstevel@tonic-gate static struct ladvalues LDAPAliasDereference[] =
37737c478bd9Sstevel@tonic-gate {
37747c478bd9Sstevel@tonic-gate 	{	"never",	LDAP_DEREF_NEVER	},
37757c478bd9Sstevel@tonic-gate 	{	"always",	LDAP_DEREF_ALWAYS	},
37767c478bd9Sstevel@tonic-gate 	{	"search",	LDAP_DEREF_SEARCHING	},
37777c478bd9Sstevel@tonic-gate 	{	"find",		LDAP_DEREF_FINDING	},
37787c478bd9Sstevel@tonic-gate 	{	NULL,		0			}
37797c478bd9Sstevel@tonic-gate };
37807c478bd9Sstevel@tonic-gate 
37817c478bd9Sstevel@tonic-gate static struct lssvalues LDAPSearchScope[] =
37827c478bd9Sstevel@tonic-gate {
37837c478bd9Sstevel@tonic-gate 	{	"base",		LDAP_SCOPE_BASE		},
37847c478bd9Sstevel@tonic-gate 	{	"one",		LDAP_SCOPE_ONELEVEL	},
37857c478bd9Sstevel@tonic-gate 	{	"sub",		LDAP_SCOPE_SUBTREE	},
37867c478bd9Sstevel@tonic-gate 	{	NULL,		0			}
37877c478bd9Sstevel@tonic-gate };
37887c478bd9Sstevel@tonic-gate 
37897c478bd9Sstevel@tonic-gate bool
37907c478bd9Sstevel@tonic-gate ldapmap_parseargs(map, args)
37917c478bd9Sstevel@tonic-gate 	MAP *map;
37927c478bd9Sstevel@tonic-gate 	char *args;
37937c478bd9Sstevel@tonic-gate {
37947c478bd9Sstevel@tonic-gate 	bool secretread = true;
37957c478bd9Sstevel@tonic-gate 	bool attrssetup = false;
37967c478bd9Sstevel@tonic-gate 	int i;
37977c478bd9Sstevel@tonic-gate 	register char *p = args;
37987c478bd9Sstevel@tonic-gate 	SM_LDAP_STRUCT *lmap;
37997c478bd9Sstevel@tonic-gate 	struct lamvalues *lam;
38007c478bd9Sstevel@tonic-gate 	struct ladvalues *lad;
38017c478bd9Sstevel@tonic-gate 	struct lssvalues *lss;
38027c478bd9Sstevel@tonic-gate 	char ldapfilt[MAXLINE];
38037c478bd9Sstevel@tonic-gate 	char m_tmp[MAXPATHLEN + LDAPMAP_MAX_PASSWD];
38047c478bd9Sstevel@tonic-gate 
38057c478bd9Sstevel@tonic-gate 	/* Get ldap struct pointer from map */
38067c478bd9Sstevel@tonic-gate 	lmap = (SM_LDAP_STRUCT *) map->map_db1;
38077c478bd9Sstevel@tonic-gate 
38087c478bd9Sstevel@tonic-gate 	/* Check if setting the initial LDAP defaults */
38097c478bd9Sstevel@tonic-gate 	if (lmap == NULL || lmap != LDAPDefaults)
38107c478bd9Sstevel@tonic-gate 	{
38117c478bd9Sstevel@tonic-gate 		/* We need to alloc an SM_LDAP_STRUCT struct */
38127c478bd9Sstevel@tonic-gate 		lmap = (SM_LDAP_STRUCT *) xalloc(sizeof *lmap);
38137c478bd9Sstevel@tonic-gate 		if (LDAPDefaults == NULL)
38147c478bd9Sstevel@tonic-gate 			sm_ldap_clear(lmap);
38157c478bd9Sstevel@tonic-gate 		else
38167c478bd9Sstevel@tonic-gate 			STRUCTCOPY(*LDAPDefaults, *lmap);
38177c478bd9Sstevel@tonic-gate 	}
38187c478bd9Sstevel@tonic-gate 
38197c478bd9Sstevel@tonic-gate 	/* there is no check whether there is really an argument */
38207c478bd9Sstevel@tonic-gate 	map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL;
38217c478bd9Sstevel@tonic-gate 	map->map_spacesub = SpaceSub;	/* default value */
38227c478bd9Sstevel@tonic-gate 
38237c478bd9Sstevel@tonic-gate 	/* Check if setting up an alias or file class LDAP map */
38247c478bd9Sstevel@tonic-gate 	if (bitset(MF_ALIAS, map->map_mflags))
38257c478bd9Sstevel@tonic-gate 	{
38267c478bd9Sstevel@tonic-gate 		/* Comma separate if used as an alias file */
38277c478bd9Sstevel@tonic-gate 		map->map_coldelim = ',';
38287c478bd9Sstevel@tonic-gate 		if (*args == '\0')
38297c478bd9Sstevel@tonic-gate 		{
38307c478bd9Sstevel@tonic-gate 			int n;
38317c478bd9Sstevel@tonic-gate 			char *lc;
38327c478bd9Sstevel@tonic-gate 			char jbuf[MAXHOSTNAMELEN];
38337c478bd9Sstevel@tonic-gate 			char lcbuf[MAXLINE];
38347c478bd9Sstevel@tonic-gate 
38357c478bd9Sstevel@tonic-gate 			/* Get $j */
38367c478bd9Sstevel@tonic-gate 			expand("\201j", jbuf, sizeof jbuf, &BlankEnvelope);
38377c478bd9Sstevel@tonic-gate 			if (jbuf[0] == '\0')
38387c478bd9Sstevel@tonic-gate 			{
38397c478bd9Sstevel@tonic-gate 				(void) sm_strlcpy(jbuf, "localhost",
38407c478bd9Sstevel@tonic-gate 						  sizeof jbuf);
38417c478bd9Sstevel@tonic-gate 			}
38427c478bd9Sstevel@tonic-gate 
38437c478bd9Sstevel@tonic-gate 			lc = macvalue(macid("{sendmailMTACluster}"), CurEnv);
38447c478bd9Sstevel@tonic-gate 			if (lc == NULL)
38457c478bd9Sstevel@tonic-gate 				lc = "";
38467c478bd9Sstevel@tonic-gate 			else
38477c478bd9Sstevel@tonic-gate 			{
38487c478bd9Sstevel@tonic-gate 				expand(lc, lcbuf, sizeof lcbuf, CurEnv);
38497c478bd9Sstevel@tonic-gate 				lc = lcbuf;
38507c478bd9Sstevel@tonic-gate 			}
38517c478bd9Sstevel@tonic-gate 
38527c478bd9Sstevel@tonic-gate 			n = sm_snprintf(ldapfilt, sizeof ldapfilt,
38537c478bd9Sstevel@tonic-gate 					"(&(objectClass=sendmailMTAAliasObject)(sendmailMTAAliasGrouping=aliases)(|(sendmailMTACluster=%s)(sendmailMTAHost=%s))(sendmailMTAKey=%%0))",
38547c478bd9Sstevel@tonic-gate 					lc, jbuf);
38557c478bd9Sstevel@tonic-gate 			if (n >= sizeof ldapfilt)
38567c478bd9Sstevel@tonic-gate 			{
38577c478bd9Sstevel@tonic-gate 				syserr("%s: Default LDAP string too long",
38587c478bd9Sstevel@tonic-gate 				       map->map_mname);
38597c478bd9Sstevel@tonic-gate 				return false;
38607c478bd9Sstevel@tonic-gate 			}
38617c478bd9Sstevel@tonic-gate 
38627c478bd9Sstevel@tonic-gate 			/* default args for an alias LDAP entry */
38637c478bd9Sstevel@tonic-gate 			lmap->ldap_filter = ldapfilt;
38647c478bd9Sstevel@tonic-gate 			lmap->ldap_attr[0] = "objectClass";
38657c478bd9Sstevel@tonic-gate 			lmap->ldap_attr_type[0] = SM_LDAP_ATTR_OBJCLASS;
38667c478bd9Sstevel@tonic-gate 			lmap->ldap_attr_needobjclass[0] = NULL;
38677c478bd9Sstevel@tonic-gate 			lmap->ldap_attr[1] = "sendmailMTAAliasValue";
38687c478bd9Sstevel@tonic-gate 			lmap->ldap_attr_type[1] = SM_LDAP_ATTR_NORMAL;
38697c478bd9Sstevel@tonic-gate 			lmap->ldap_attr_needobjclass[1] = NULL;
38707c478bd9Sstevel@tonic-gate 			lmap->ldap_attr[2] = "sendmailMTAAliasSearch";
38717c478bd9Sstevel@tonic-gate 			lmap->ldap_attr_type[2] = SM_LDAP_ATTR_FILTER;
38727c478bd9Sstevel@tonic-gate 			lmap->ldap_attr_needobjclass[2] = "sendmailMTAMapObject";
38737c478bd9Sstevel@tonic-gate 			lmap->ldap_attr[3] = "sendmailMTAAliasURL";
38747c478bd9Sstevel@tonic-gate 			lmap->ldap_attr_type[3] = SM_LDAP_ATTR_URL;
38757c478bd9Sstevel@tonic-gate 			lmap->ldap_attr_needobjclass[3] = "sendmailMTAMapObject";
38767c478bd9Sstevel@tonic-gate 			lmap->ldap_attr[4] = NULL;
38777c478bd9Sstevel@tonic-gate 			lmap->ldap_attr_type[4] = SM_LDAP_ATTR_NONE;
38787c478bd9Sstevel@tonic-gate 			lmap->ldap_attr_needobjclass[4] = NULL;
38797c478bd9Sstevel@tonic-gate 			attrssetup = true;
38807c478bd9Sstevel@tonic-gate 		}
38817c478bd9Sstevel@tonic-gate 	}
38827c478bd9Sstevel@tonic-gate 	else if (bitset(MF_FILECLASS, map->map_mflags))
38837c478bd9Sstevel@tonic-gate 	{
38847c478bd9Sstevel@tonic-gate 		/* Space separate if used as a file class file */
38857c478bd9Sstevel@tonic-gate 		map->map_coldelim = ' ';
38867c478bd9Sstevel@tonic-gate 	}
38877c478bd9Sstevel@tonic-gate 
38887c478bd9Sstevel@tonic-gate 	for (;;)
38897c478bd9Sstevel@tonic-gate 	{
38907c478bd9Sstevel@tonic-gate 		while (isascii(*p) && isspace(*p))
38917c478bd9Sstevel@tonic-gate 			p++;
38927c478bd9Sstevel@tonic-gate 		if (*p != '-')
38937c478bd9Sstevel@tonic-gate 			break;
38947c478bd9Sstevel@tonic-gate 		switch (*++p)
38957c478bd9Sstevel@tonic-gate 		{
38967c478bd9Sstevel@tonic-gate 		  case 'N':
38977c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_INCLNULL;
38987c478bd9Sstevel@tonic-gate 			map->map_mflags &= ~MF_TRY0NULL;
38997c478bd9Sstevel@tonic-gate 			break;
39007c478bd9Sstevel@tonic-gate 
39017c478bd9Sstevel@tonic-gate 		  case 'O':
39027c478bd9Sstevel@tonic-gate 			map->map_mflags &= ~MF_TRY1NULL;
39037c478bd9Sstevel@tonic-gate 			break;
39047c478bd9Sstevel@tonic-gate 
39057c478bd9Sstevel@tonic-gate 		  case 'o':
39067c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_OPTIONAL;
39077c478bd9Sstevel@tonic-gate 			break;
39087c478bd9Sstevel@tonic-gate 
39097c478bd9Sstevel@tonic-gate 		  case 'f':
39107c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_NOFOLDCASE;
39117c478bd9Sstevel@tonic-gate 			break;
39127c478bd9Sstevel@tonic-gate 
39137c478bd9Sstevel@tonic-gate 		  case 'm':
39147c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_MATCHONLY;
39157c478bd9Sstevel@tonic-gate 			break;
39167c478bd9Sstevel@tonic-gate 
39177c478bd9Sstevel@tonic-gate 		  case 'A':
39187c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_APPEND;
39197c478bd9Sstevel@tonic-gate 			break;
39207c478bd9Sstevel@tonic-gate 
39217c478bd9Sstevel@tonic-gate 		  case 'q':
39227c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_KEEPQUOTES;
39237c478bd9Sstevel@tonic-gate 			break;
39247c478bd9Sstevel@tonic-gate 
39257c478bd9Sstevel@tonic-gate 		  case 'a':
39267c478bd9Sstevel@tonic-gate 			map->map_app = ++p;
39277c478bd9Sstevel@tonic-gate 			break;
39287c478bd9Sstevel@tonic-gate 
39297c478bd9Sstevel@tonic-gate 		  case 'T':
39307c478bd9Sstevel@tonic-gate 			map->map_tapp = ++p;
39317c478bd9Sstevel@tonic-gate 			break;
39327c478bd9Sstevel@tonic-gate 
39337c478bd9Sstevel@tonic-gate 		  case 't':
39347c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_NODEFER;
39357c478bd9Sstevel@tonic-gate 			break;
39367c478bd9Sstevel@tonic-gate 
39377c478bd9Sstevel@tonic-gate 		  case 'S':
39387c478bd9Sstevel@tonic-gate 			map->map_spacesub = *++p;
39397c478bd9Sstevel@tonic-gate 			break;
39407c478bd9Sstevel@tonic-gate 
39417c478bd9Sstevel@tonic-gate 		  case 'D':
39427c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_DEFER;
39437c478bd9Sstevel@tonic-gate 			break;
39447c478bd9Sstevel@tonic-gate 
39457c478bd9Sstevel@tonic-gate 		  case 'z':
39467c478bd9Sstevel@tonic-gate 			if (*++p != '\\')
39477c478bd9Sstevel@tonic-gate 				map->map_coldelim = *p;
39487c478bd9Sstevel@tonic-gate 			else
39497c478bd9Sstevel@tonic-gate 			{
39507c478bd9Sstevel@tonic-gate 				switch (*++p)
39517c478bd9Sstevel@tonic-gate 				{
39527c478bd9Sstevel@tonic-gate 				  case 'n':
39537c478bd9Sstevel@tonic-gate 					map->map_coldelim = '\n';
39547c478bd9Sstevel@tonic-gate 					break;
39557c478bd9Sstevel@tonic-gate 
39567c478bd9Sstevel@tonic-gate 				  case 't':
39577c478bd9Sstevel@tonic-gate 					map->map_coldelim = '\t';
39587c478bd9Sstevel@tonic-gate 					break;
39597c478bd9Sstevel@tonic-gate 
39607c478bd9Sstevel@tonic-gate 				  default:
39617c478bd9Sstevel@tonic-gate 					map->map_coldelim = '\\';
39627c478bd9Sstevel@tonic-gate 				}
39637c478bd9Sstevel@tonic-gate 			}
39647c478bd9Sstevel@tonic-gate 			break;
39657c478bd9Sstevel@tonic-gate 
39667c478bd9Sstevel@tonic-gate 			/* Start of ldapmap specific args */
39677c478bd9Sstevel@tonic-gate 		  case 'V':
39687c478bd9Sstevel@tonic-gate 			if (*++p != '\\')
39697c478bd9Sstevel@tonic-gate 				lmap->ldap_attrsep = *p;
39707c478bd9Sstevel@tonic-gate 			else
39717c478bd9Sstevel@tonic-gate 			{
39727c478bd9Sstevel@tonic-gate 				switch (*++p)
39737c478bd9Sstevel@tonic-gate 				{
39747c478bd9Sstevel@tonic-gate 				  case 'n':
39757c478bd9Sstevel@tonic-gate 					lmap->ldap_attrsep = '\n';
39767c478bd9Sstevel@tonic-gate 					break;
39777c478bd9Sstevel@tonic-gate 
39787c478bd9Sstevel@tonic-gate 				  case 't':
39797c478bd9Sstevel@tonic-gate 					lmap->ldap_attrsep = '\t';
39807c478bd9Sstevel@tonic-gate 					break;
39817c478bd9Sstevel@tonic-gate 
39827c478bd9Sstevel@tonic-gate 				  default:
39837c478bd9Sstevel@tonic-gate 					lmap->ldap_attrsep = '\\';
39847c478bd9Sstevel@tonic-gate 				}
39857c478bd9Sstevel@tonic-gate 			}
39867c478bd9Sstevel@tonic-gate 			break;
39877c478bd9Sstevel@tonic-gate 
39887c478bd9Sstevel@tonic-gate 		  case 'k':		/* search field */
39897c478bd9Sstevel@tonic-gate 			while (isascii(*++p) && isspace(*p))
39907c478bd9Sstevel@tonic-gate 				continue;
39917c478bd9Sstevel@tonic-gate 			lmap->ldap_filter = p;
39927c478bd9Sstevel@tonic-gate 			break;
39937c478bd9Sstevel@tonic-gate 
39947c478bd9Sstevel@tonic-gate 		  case 'v':		/* attr to return */
39957c478bd9Sstevel@tonic-gate 			while (isascii(*++p) && isspace(*p))
39967c478bd9Sstevel@tonic-gate 				continue;
39977c478bd9Sstevel@tonic-gate 			lmap->ldap_attr[0] = p;
39987c478bd9Sstevel@tonic-gate 			lmap->ldap_attr[1] = NULL;
39997c478bd9Sstevel@tonic-gate 			break;
40007c478bd9Sstevel@tonic-gate 
40017c478bd9Sstevel@tonic-gate 		  case '1':
40027c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_SINGLEMATCH;
40037c478bd9Sstevel@tonic-gate 			break;
40047c478bd9Sstevel@tonic-gate 
400549218d4fSjbeck # if _FFR_LDAP_SINGLEDN
400649218d4fSjbeck 		  case '2':
400749218d4fSjbeck 			map->map_mflags |= MF_SINGLEDN;
400849218d4fSjbeck 			break;
400949218d4fSjbeck # endif /* _FFR_LDAP_SINGLEDN */
401049218d4fSjbeck 
40117c478bd9Sstevel@tonic-gate 			/* args stolen from ldapsearch.c */
40127c478bd9Sstevel@tonic-gate 		  case 'R':		/* don't auto chase referrals */
40137c478bd9Sstevel@tonic-gate # ifdef LDAP_REFERRALS
40147c478bd9Sstevel@tonic-gate 			lmap->ldap_options &= ~LDAP_OPT_REFERRALS;
40157c478bd9Sstevel@tonic-gate # else /* LDAP_REFERRALS */
40167c478bd9Sstevel@tonic-gate 			syserr("compile with -DLDAP_REFERRALS for referral support");
40177c478bd9Sstevel@tonic-gate # endif /* LDAP_REFERRALS */
40187c478bd9Sstevel@tonic-gate 			break;
40197c478bd9Sstevel@tonic-gate 
40207c478bd9Sstevel@tonic-gate 		  case 'n':		/* retrieve attribute names only */
40217c478bd9Sstevel@tonic-gate 			lmap->ldap_attrsonly = LDAPMAP_TRUE;
40227c478bd9Sstevel@tonic-gate 			break;
40237c478bd9Sstevel@tonic-gate 
40247c478bd9Sstevel@tonic-gate 		  case 'r':		/* alias dereferencing */
40257c478bd9Sstevel@tonic-gate 			while (isascii(*++p) && isspace(*p))
40267c478bd9Sstevel@tonic-gate 				continue;
40277c478bd9Sstevel@tonic-gate 
40287c478bd9Sstevel@tonic-gate 			if (sm_strncasecmp(p, "LDAP_DEREF_", 11) == 0)
40297c478bd9Sstevel@tonic-gate 				p += 11;
40307c478bd9Sstevel@tonic-gate 
40317c478bd9Sstevel@tonic-gate 			for (lad = LDAPAliasDereference;
40327c478bd9Sstevel@tonic-gate 			     lad != NULL && lad->lad_name != NULL; lad++)
40337c478bd9Sstevel@tonic-gate 			{
40347c478bd9Sstevel@tonic-gate 				if (sm_strncasecmp(p, lad->lad_name,
40357c478bd9Sstevel@tonic-gate 						   strlen(lad->lad_name)) == 0)
40367c478bd9Sstevel@tonic-gate 					break;
40377c478bd9Sstevel@tonic-gate 			}
40387c478bd9Sstevel@tonic-gate 			if (lad->lad_name != NULL)
40397c478bd9Sstevel@tonic-gate 				lmap->ldap_deref = lad->lad_code;
40407c478bd9Sstevel@tonic-gate 			else
40417c478bd9Sstevel@tonic-gate 			{
40427c478bd9Sstevel@tonic-gate 				/* bad config line */
40437c478bd9Sstevel@tonic-gate 				if (!bitset(MCF_OPTFILE,
40447c478bd9Sstevel@tonic-gate 					    map->map_class->map_cflags))
40457c478bd9Sstevel@tonic-gate 				{
40467c478bd9Sstevel@tonic-gate 					char *ptr;
40477c478bd9Sstevel@tonic-gate 
40487c478bd9Sstevel@tonic-gate 					if ((ptr = strchr(p, ' ')) != NULL)
40497c478bd9Sstevel@tonic-gate 						*ptr = '\0';
40507c478bd9Sstevel@tonic-gate 					syserr("Deref must be [never|always|search|find] (not %s) in map %s",
40517c478bd9Sstevel@tonic-gate 						p, map->map_mname);
40527c478bd9Sstevel@tonic-gate 					if (ptr != NULL)
40537c478bd9Sstevel@tonic-gate 						*ptr = ' ';
40547c478bd9Sstevel@tonic-gate 					return false;
40557c478bd9Sstevel@tonic-gate 				}
40567c478bd9Sstevel@tonic-gate 			}
40577c478bd9Sstevel@tonic-gate 			break;
40587c478bd9Sstevel@tonic-gate 
40597c478bd9Sstevel@tonic-gate 		  case 's':		/* search scope */
40607c478bd9Sstevel@tonic-gate 			while (isascii(*++p) && isspace(*p))
40617c478bd9Sstevel@tonic-gate 				continue;
40627c478bd9Sstevel@tonic-gate 
40637c478bd9Sstevel@tonic-gate 			if (sm_strncasecmp(p, "LDAP_SCOPE_", 11) == 0)
40647c478bd9Sstevel@tonic-gate 				p += 11;
40657c478bd9Sstevel@tonic-gate 
40667c478bd9Sstevel@tonic-gate 			for (lss = LDAPSearchScope;
40677c478bd9Sstevel@tonic-gate 			     lss != NULL && lss->lss_name != NULL; lss++)
40687c478bd9Sstevel@tonic-gate 			{
40697c478bd9Sstevel@tonic-gate 				if (sm_strncasecmp(p, lss->lss_name,
40707c478bd9Sstevel@tonic-gate 						   strlen(lss->lss_name)) == 0)
40717c478bd9Sstevel@tonic-gate 					break;
40727c478bd9Sstevel@tonic-gate 			}
40737c478bd9Sstevel@tonic-gate 			if (lss->lss_name != NULL)
40747c478bd9Sstevel@tonic-gate 				lmap->ldap_scope = lss->lss_code;
40757c478bd9Sstevel@tonic-gate 			else
40767c478bd9Sstevel@tonic-gate 			{
40777c478bd9Sstevel@tonic-gate 				/* bad config line */
40787c478bd9Sstevel@tonic-gate 				if (!bitset(MCF_OPTFILE,
40797c478bd9Sstevel@tonic-gate 					    map->map_class->map_cflags))
40807c478bd9Sstevel@tonic-gate 				{
40817c478bd9Sstevel@tonic-gate 					char *ptr;
40827c478bd9Sstevel@tonic-gate 
40837c478bd9Sstevel@tonic-gate 					if ((ptr = strchr(p, ' ')) != NULL)
40847c478bd9Sstevel@tonic-gate 						*ptr = '\0';
40857c478bd9Sstevel@tonic-gate 					syserr("Scope must be [base|one|sub] (not %s) in map %s",
40867c478bd9Sstevel@tonic-gate 						p, map->map_mname);
40877c478bd9Sstevel@tonic-gate 					if (ptr != NULL)
40887c478bd9Sstevel@tonic-gate 						*ptr = ' ';
40897c478bd9Sstevel@tonic-gate 					return false;
40907c478bd9Sstevel@tonic-gate 				}
40917c478bd9Sstevel@tonic-gate 			}
40927c478bd9Sstevel@tonic-gate 			break;
40937c478bd9Sstevel@tonic-gate 
40947c478bd9Sstevel@tonic-gate 		  case 'h':		/* ldap host */
40957c478bd9Sstevel@tonic-gate 			while (isascii(*++p) && isspace(*p))
40967c478bd9Sstevel@tonic-gate 				continue;
40977c478bd9Sstevel@tonic-gate 			if (lmap->ldap_uri != NULL)
40987c478bd9Sstevel@tonic-gate 			{
40997c478bd9Sstevel@tonic-gate 				syserr("Can not specify both an LDAP host and an LDAP URI in map %s",
41007c478bd9Sstevel@tonic-gate 				       map->map_mname);
41017c478bd9Sstevel@tonic-gate 				return false;
41027c478bd9Sstevel@tonic-gate 			}
41037c478bd9Sstevel@tonic-gate 			lmap->ldap_host = p;
41047c478bd9Sstevel@tonic-gate 			break;
41057c478bd9Sstevel@tonic-gate 
41067c478bd9Sstevel@tonic-gate 		  case 'b':		/* search base */
41077c478bd9Sstevel@tonic-gate 			while (isascii(*++p) && isspace(*p))
41087c478bd9Sstevel@tonic-gate 				continue;
41097c478bd9Sstevel@tonic-gate 			lmap->ldap_base = p;
41107c478bd9Sstevel@tonic-gate 			break;
41117c478bd9Sstevel@tonic-gate 
41127c478bd9Sstevel@tonic-gate 		  case 'p':		/* ldap port */
41137c478bd9Sstevel@tonic-gate 			while (isascii(*++p) && isspace(*p))
41147c478bd9Sstevel@tonic-gate 				continue;
41157c478bd9Sstevel@tonic-gate 			lmap->ldap_port = atoi(p);
41167c478bd9Sstevel@tonic-gate 			break;
41177c478bd9Sstevel@tonic-gate 
41187c478bd9Sstevel@tonic-gate 		  case 'l':		/* time limit */
41197c478bd9Sstevel@tonic-gate 			while (isascii(*++p) && isspace(*p))
41207c478bd9Sstevel@tonic-gate 				continue;
41217c478bd9Sstevel@tonic-gate 			lmap->ldap_timelimit = atoi(p);
41227c478bd9Sstevel@tonic-gate 			lmap->ldap_timeout.tv_sec = lmap->ldap_timelimit;
41237c478bd9Sstevel@tonic-gate 			break;
41247c478bd9Sstevel@tonic-gate 
41257c478bd9Sstevel@tonic-gate 		  case 'Z':
41267c478bd9Sstevel@tonic-gate 			while (isascii(*++p) && isspace(*p))
41277c478bd9Sstevel@tonic-gate 				continue;
41287c478bd9Sstevel@tonic-gate 			lmap->ldap_sizelimit = atoi(p);
41297c478bd9Sstevel@tonic-gate 			break;
41307c478bd9Sstevel@tonic-gate 
41317c478bd9Sstevel@tonic-gate 		  case 'd':		/* Dn to bind to server as */
41327c478bd9Sstevel@tonic-gate 			while (isascii(*++p) && isspace(*p))
41337c478bd9Sstevel@tonic-gate 				continue;
41347c478bd9Sstevel@tonic-gate 			lmap->ldap_binddn = p;
41357c478bd9Sstevel@tonic-gate 			break;
41367c478bd9Sstevel@tonic-gate 
41377c478bd9Sstevel@tonic-gate 		  case 'M':		/* Method for binding */
41387c478bd9Sstevel@tonic-gate 			while (isascii(*++p) && isspace(*p))
41397c478bd9Sstevel@tonic-gate 				continue;
41407c478bd9Sstevel@tonic-gate 
41417c478bd9Sstevel@tonic-gate 			if (sm_strncasecmp(p, "LDAP_AUTH_", 10) == 0)
41427c478bd9Sstevel@tonic-gate 				p += 10;
41437c478bd9Sstevel@tonic-gate 
41447c478bd9Sstevel@tonic-gate 			for (lam = LDAPAuthMethods;
41457c478bd9Sstevel@tonic-gate 			     lam != NULL && lam->lam_name != NULL; lam++)
41467c478bd9Sstevel@tonic-gate 			{
41477c478bd9Sstevel@tonic-gate 				if (sm_strncasecmp(p, lam->lam_name,
41487c478bd9Sstevel@tonic-gate 						   strlen(lam->lam_name)) == 0)
41497c478bd9Sstevel@tonic-gate 					break;
41507c478bd9Sstevel@tonic-gate 			}
41517c478bd9Sstevel@tonic-gate 			if (lam->lam_name != NULL)
41527c478bd9Sstevel@tonic-gate 				lmap->ldap_method = lam->lam_code;
41537c478bd9Sstevel@tonic-gate 			else
41547c478bd9Sstevel@tonic-gate 			{
41557c478bd9Sstevel@tonic-gate 				/* bad config line */
41567c478bd9Sstevel@tonic-gate 				if (!bitset(MCF_OPTFILE,
41577c478bd9Sstevel@tonic-gate 					    map->map_class->map_cflags))
41587c478bd9Sstevel@tonic-gate 				{
41597c478bd9Sstevel@tonic-gate 					char *ptr;
41607c478bd9Sstevel@tonic-gate 
41617c478bd9Sstevel@tonic-gate 					if ((ptr = strchr(p, ' ')) != NULL)
41627c478bd9Sstevel@tonic-gate 						*ptr = '\0';
41637c478bd9Sstevel@tonic-gate 					syserr("Method for binding must be [none|simple|krbv4] (not %s) in map %s",
41647c478bd9Sstevel@tonic-gate 						p, map->map_mname);
41657c478bd9Sstevel@tonic-gate 					if (ptr != NULL)
41667c478bd9Sstevel@tonic-gate 						*ptr = ' ';
41677c478bd9Sstevel@tonic-gate 					return false;
41687c478bd9Sstevel@tonic-gate 				}
41697c478bd9Sstevel@tonic-gate 			}
41707c478bd9Sstevel@tonic-gate 
41717c478bd9Sstevel@tonic-gate 			break;
41727c478bd9Sstevel@tonic-gate 
41737c478bd9Sstevel@tonic-gate 			/*
41747c478bd9Sstevel@tonic-gate 			**  This is a string that is dependent on the
41757c478bd9Sstevel@tonic-gate 			**  method used defined above.
41767c478bd9Sstevel@tonic-gate 			*/
41777c478bd9Sstevel@tonic-gate 
41787c478bd9Sstevel@tonic-gate 		  case 'P':		/* Secret password for binding */
41797c478bd9Sstevel@tonic-gate 			 while (isascii(*++p) && isspace(*p))
41807c478bd9Sstevel@tonic-gate 				continue;
41817c478bd9Sstevel@tonic-gate 			lmap->ldap_secret = p;
41827c478bd9Sstevel@tonic-gate 			secretread = false;
41837c478bd9Sstevel@tonic-gate 			break;
41847c478bd9Sstevel@tonic-gate 
41857c478bd9Sstevel@tonic-gate 		  case 'H':		/* Use LDAP URI */
41867c478bd9Sstevel@tonic-gate #  if !USE_LDAP_INIT
41877c478bd9Sstevel@tonic-gate 			syserr("Must compile with -DUSE_LDAP_INIT to use LDAP URIs (-H) in map %s",
41887c478bd9Sstevel@tonic-gate 			       map->map_mname);
41897c478bd9Sstevel@tonic-gate 			return false;
41907c478bd9Sstevel@tonic-gate #   else /* !USE_LDAP_INIT */
41917c478bd9Sstevel@tonic-gate 			if (lmap->ldap_host != NULL)
41927c478bd9Sstevel@tonic-gate 			{
41937c478bd9Sstevel@tonic-gate 				syserr("Can not specify both an LDAP host and an LDAP URI in map %s",
41947c478bd9Sstevel@tonic-gate 				       map->map_mname);
41957c478bd9Sstevel@tonic-gate 				return false;
41967c478bd9Sstevel@tonic-gate 			}
41977c478bd9Sstevel@tonic-gate 			while (isascii(*++p) && isspace(*p))
41987c478bd9Sstevel@tonic-gate 				continue;
41997c478bd9Sstevel@tonic-gate 			lmap->ldap_uri = p;
42007c478bd9Sstevel@tonic-gate 			break;
42017c478bd9Sstevel@tonic-gate #  endif /* !USE_LDAP_INIT */
42027c478bd9Sstevel@tonic-gate 
42037c478bd9Sstevel@tonic-gate 		  case 'w':
42047c478bd9Sstevel@tonic-gate 			/* -w should be for passwd, -P should be for version */
42057c478bd9Sstevel@tonic-gate 			while (isascii(*++p) && isspace(*p))
42067c478bd9Sstevel@tonic-gate 				continue;
42077c478bd9Sstevel@tonic-gate 			lmap->ldap_version = atoi(p);
42087c478bd9Sstevel@tonic-gate # ifdef LDAP_VERSION_MAX
42097c478bd9Sstevel@tonic-gate 			if (lmap->ldap_version > LDAP_VERSION_MAX)
42107c478bd9Sstevel@tonic-gate 			{
42117c478bd9Sstevel@tonic-gate 				syserr("LDAP version %d exceeds max of %d in map %s",
42127c478bd9Sstevel@tonic-gate 				       lmap->ldap_version, LDAP_VERSION_MAX,
42137c478bd9Sstevel@tonic-gate 				       map->map_mname);
42147c478bd9Sstevel@tonic-gate 				return false;
42157c478bd9Sstevel@tonic-gate 			}
42167c478bd9Sstevel@tonic-gate # endif /* LDAP_VERSION_MAX */
42177c478bd9Sstevel@tonic-gate # ifdef LDAP_VERSION_MIN
42187c478bd9Sstevel@tonic-gate 			if (lmap->ldap_version < LDAP_VERSION_MIN)
42197c478bd9Sstevel@tonic-gate 			{
42207c478bd9Sstevel@tonic-gate 				syserr("LDAP version %d is lower than min of %d in map %s",
42217c478bd9Sstevel@tonic-gate 				       lmap->ldap_version, LDAP_VERSION_MIN,
42227c478bd9Sstevel@tonic-gate 				       map->map_mname);
42237c478bd9Sstevel@tonic-gate 				return false;
42247c478bd9Sstevel@tonic-gate 			}
42257c478bd9Sstevel@tonic-gate # endif /* LDAP_VERSION_MIN */
42267c478bd9Sstevel@tonic-gate 			break;
42277c478bd9Sstevel@tonic-gate 
42287c478bd9Sstevel@tonic-gate 		  default:
42297c478bd9Sstevel@tonic-gate 			syserr("Illegal option %c map %s", *p, map->map_mname);
42307c478bd9Sstevel@tonic-gate 			break;
42317c478bd9Sstevel@tonic-gate 		}
42327c478bd9Sstevel@tonic-gate 
42337c478bd9Sstevel@tonic-gate 		/* need to account for quoted strings here */
42347c478bd9Sstevel@tonic-gate 		while (*p != '\0' && !(isascii(*p) && isspace(*p)))
42357c478bd9Sstevel@tonic-gate 		{
42367c478bd9Sstevel@tonic-gate 			if (*p == '"')
42377c478bd9Sstevel@tonic-gate 			{
42387c478bd9Sstevel@tonic-gate 				while (*++p != '"' && *p != '\0')
42397c478bd9Sstevel@tonic-gate 					continue;
42407c478bd9Sstevel@tonic-gate 				if (*p != '\0')
42417c478bd9Sstevel@tonic-gate 					p++;
42427c478bd9Sstevel@tonic-gate 			}
42437c478bd9Sstevel@tonic-gate 			else
42447c478bd9Sstevel@tonic-gate 				p++;
42457c478bd9Sstevel@tonic-gate 		}
42467c478bd9Sstevel@tonic-gate 
42477c478bd9Sstevel@tonic-gate 		if (*p != '\0')
42487c478bd9Sstevel@tonic-gate 			*p++ = '\0';
42497c478bd9Sstevel@tonic-gate 	}
42507c478bd9Sstevel@tonic-gate 
42517c478bd9Sstevel@tonic-gate 	if (map->map_app != NULL)
42527c478bd9Sstevel@tonic-gate 		map->map_app = newstr(ldapmap_dequote(map->map_app));
42537c478bd9Sstevel@tonic-gate 	if (map->map_tapp != NULL)
42547c478bd9Sstevel@tonic-gate 		map->map_tapp = newstr(ldapmap_dequote(map->map_tapp));
42557c478bd9Sstevel@tonic-gate 
42567c478bd9Sstevel@tonic-gate 	/*
42577c478bd9Sstevel@tonic-gate 	**  We need to swallow up all the stuff into a struct
42587c478bd9Sstevel@tonic-gate 	**  and dump it into map->map_dbptr1
42597c478bd9Sstevel@tonic-gate 	*/
42607c478bd9Sstevel@tonic-gate 
42617c478bd9Sstevel@tonic-gate 	if (lmap->ldap_host != NULL &&
42627c478bd9Sstevel@tonic-gate 	    (LDAPDefaults == NULL ||
42637c478bd9Sstevel@tonic-gate 	     LDAPDefaults == lmap ||
42647c478bd9Sstevel@tonic-gate 	     LDAPDefaults->ldap_host != lmap->ldap_host))
42657c478bd9Sstevel@tonic-gate 		lmap->ldap_host = newstr(ldapmap_dequote(lmap->ldap_host));
42667c478bd9Sstevel@tonic-gate 	map->map_domain = lmap->ldap_host;
42677c478bd9Sstevel@tonic-gate 
42687c478bd9Sstevel@tonic-gate 	if (lmap->ldap_uri != NULL &&
42697c478bd9Sstevel@tonic-gate 	    (LDAPDefaults == NULL ||
42707c478bd9Sstevel@tonic-gate 	     LDAPDefaults == lmap ||
42717c478bd9Sstevel@tonic-gate 	     LDAPDefaults->ldap_uri != lmap->ldap_uri))
42727c478bd9Sstevel@tonic-gate 		lmap->ldap_uri = newstr(ldapmap_dequote(lmap->ldap_uri));
42737c478bd9Sstevel@tonic-gate 	map->map_domain = lmap->ldap_uri;
42747c478bd9Sstevel@tonic-gate 
42757c478bd9Sstevel@tonic-gate 	if (lmap->ldap_binddn != NULL &&
42767c478bd9Sstevel@tonic-gate 	    (LDAPDefaults == NULL ||
42777c478bd9Sstevel@tonic-gate 	     LDAPDefaults == lmap ||
42787c478bd9Sstevel@tonic-gate 	     LDAPDefaults->ldap_binddn != lmap->ldap_binddn))
42797c478bd9Sstevel@tonic-gate 		lmap->ldap_binddn = newstr(ldapmap_dequote(lmap->ldap_binddn));
42807c478bd9Sstevel@tonic-gate 
42817c478bd9Sstevel@tonic-gate 	if (lmap->ldap_secret != NULL &&
42827c478bd9Sstevel@tonic-gate 	    (LDAPDefaults == NULL ||
42837c478bd9Sstevel@tonic-gate 	     LDAPDefaults == lmap ||
42847c478bd9Sstevel@tonic-gate 	     LDAPDefaults->ldap_secret != lmap->ldap_secret))
42857c478bd9Sstevel@tonic-gate 	{
42867c478bd9Sstevel@tonic-gate 		SM_FILE_T *sfd;
42877c478bd9Sstevel@tonic-gate 		long sff = SFF_OPENASROOT|SFF_ROOTOK|SFF_NOWLINK|SFF_NOWWFILES|SFF_NOGWFILES;
42887c478bd9Sstevel@tonic-gate 
42897c478bd9Sstevel@tonic-gate 		if (DontLockReadFiles)
42907c478bd9Sstevel@tonic-gate 			sff |= SFF_NOLOCK;
42917c478bd9Sstevel@tonic-gate 
42927c478bd9Sstevel@tonic-gate 		/* need to use method to map secret to passwd string */
42937c478bd9Sstevel@tonic-gate 		switch (lmap->ldap_method)
42947c478bd9Sstevel@tonic-gate 		{
42957c478bd9Sstevel@tonic-gate 		  case LDAP_AUTH_NONE:
42967c478bd9Sstevel@tonic-gate 			/* Do nothing */
42977c478bd9Sstevel@tonic-gate 			break;
42987c478bd9Sstevel@tonic-gate 
42997c478bd9Sstevel@tonic-gate 		  case LDAP_AUTH_SIMPLE:
43007c478bd9Sstevel@tonic-gate 
43017c478bd9Sstevel@tonic-gate 			/*
43027c478bd9Sstevel@tonic-gate 			**  Secret is the name of a file with
43037c478bd9Sstevel@tonic-gate 			**  the first line as the password.
43047c478bd9Sstevel@tonic-gate 			*/
43057c478bd9Sstevel@tonic-gate 
43067c478bd9Sstevel@tonic-gate 			/* Already read in the secret? */
43077c478bd9Sstevel@tonic-gate 			if (secretread)
43087c478bd9Sstevel@tonic-gate 				break;
43097c478bd9Sstevel@tonic-gate 
43107c478bd9Sstevel@tonic-gate 			sfd = safefopen(ldapmap_dequote(lmap->ldap_secret),
43117c478bd9Sstevel@tonic-gate 					O_RDONLY, 0, sff);
43127c478bd9Sstevel@tonic-gate 			if (sfd == NULL)
43137c478bd9Sstevel@tonic-gate 			{
43147c478bd9Sstevel@tonic-gate 				syserr("LDAP map: cannot open secret %s",
43157c478bd9Sstevel@tonic-gate 				       ldapmap_dequote(lmap->ldap_secret));
43167c478bd9Sstevel@tonic-gate 				return false;
43177c478bd9Sstevel@tonic-gate 			}
43187c478bd9Sstevel@tonic-gate 			lmap->ldap_secret = sfgets(m_tmp, sizeof m_tmp,
43197c478bd9Sstevel@tonic-gate 						   sfd, TimeOuts.to_fileopen,
43207c478bd9Sstevel@tonic-gate 						   "ldapmap_parseargs");
43217c478bd9Sstevel@tonic-gate 			(void) sm_io_close(sfd, SM_TIME_DEFAULT);
43227c478bd9Sstevel@tonic-gate 			if (strlen(m_tmp) > LDAPMAP_MAX_PASSWD)
43237c478bd9Sstevel@tonic-gate 			{
43247c478bd9Sstevel@tonic-gate 				syserr("LDAP map: secret in %s too long",
43257c478bd9Sstevel@tonic-gate 				       ldapmap_dequote(lmap->ldap_secret));
43267c478bd9Sstevel@tonic-gate 				return false;
43277c478bd9Sstevel@tonic-gate 			}
43287c478bd9Sstevel@tonic-gate 			if (lmap->ldap_secret != NULL &&
43297c478bd9Sstevel@tonic-gate 			    strlen(m_tmp) > 0)
43307c478bd9Sstevel@tonic-gate 			{
43317c478bd9Sstevel@tonic-gate 				/* chomp newline */
43327c478bd9Sstevel@tonic-gate 				if (m_tmp[strlen(m_tmp) - 1] == '\n')
43337c478bd9Sstevel@tonic-gate 					m_tmp[strlen(m_tmp) - 1] = '\0';
43347c478bd9Sstevel@tonic-gate 
43357c478bd9Sstevel@tonic-gate 				lmap->ldap_secret = m_tmp;
43367c478bd9Sstevel@tonic-gate 			}
43377c478bd9Sstevel@tonic-gate 			break;
43387c478bd9Sstevel@tonic-gate 
43397c478bd9Sstevel@tonic-gate # ifdef LDAP_AUTH_KRBV4
43407c478bd9Sstevel@tonic-gate 		  case LDAP_AUTH_KRBV4:
43417c478bd9Sstevel@tonic-gate 
43427c478bd9Sstevel@tonic-gate 			/*
43437c478bd9Sstevel@tonic-gate 			**  Secret is where the ticket file is
43447c478bd9Sstevel@tonic-gate 			**  stashed
43457c478bd9Sstevel@tonic-gate 			*/
43467c478bd9Sstevel@tonic-gate 
43477c478bd9Sstevel@tonic-gate 			(void) sm_snprintf(m_tmp, sizeof m_tmp,
43487c478bd9Sstevel@tonic-gate 				"KRBTKFILE=%s",
43497c478bd9Sstevel@tonic-gate 				ldapmap_dequote(lmap->ldap_secret));
43507c478bd9Sstevel@tonic-gate 			lmap->ldap_secret = m_tmp;
43517c478bd9Sstevel@tonic-gate 			break;
43527c478bd9Sstevel@tonic-gate # endif /* LDAP_AUTH_KRBV4 */
43537c478bd9Sstevel@tonic-gate 
43547c478bd9Sstevel@tonic-gate 		  default:	       /* Should NEVER get here */
43557c478bd9Sstevel@tonic-gate 			syserr("LDAP map: Illegal value in lmap method");
43567c478bd9Sstevel@tonic-gate 			return false;
43577c478bd9Sstevel@tonic-gate 			/* NOTREACHED */
43587c478bd9Sstevel@tonic-gate 			break;
43597c478bd9Sstevel@tonic-gate 		}
43607c478bd9Sstevel@tonic-gate 	}
43617c478bd9Sstevel@tonic-gate 
43627c478bd9Sstevel@tonic-gate 	if (lmap->ldap_secret != NULL &&
43637c478bd9Sstevel@tonic-gate 	    (LDAPDefaults == NULL ||
43647c478bd9Sstevel@tonic-gate 	     LDAPDefaults == lmap ||
43657c478bd9Sstevel@tonic-gate 	     LDAPDefaults->ldap_secret != lmap->ldap_secret))
43667c478bd9Sstevel@tonic-gate 		lmap->ldap_secret = newstr(ldapmap_dequote(lmap->ldap_secret));
43677c478bd9Sstevel@tonic-gate 
43687c478bd9Sstevel@tonic-gate 	if (lmap->ldap_base != NULL &&
43697c478bd9Sstevel@tonic-gate 	    (LDAPDefaults == NULL ||
43707c478bd9Sstevel@tonic-gate 	     LDAPDefaults == lmap ||
43717c478bd9Sstevel@tonic-gate 	     LDAPDefaults->ldap_base != lmap->ldap_base))
43727c478bd9Sstevel@tonic-gate 		lmap->ldap_base = newstr(ldapmap_dequote(lmap->ldap_base));
43737c478bd9Sstevel@tonic-gate 
43747c478bd9Sstevel@tonic-gate 	/*
43757c478bd9Sstevel@tonic-gate 	**  Save the server from extra work.  If request is for a single
43767c478bd9Sstevel@tonic-gate 	**  match, tell the server to only return enough records to
43777c478bd9Sstevel@tonic-gate 	**  determine if there is a single match or not.  This can not
43787c478bd9Sstevel@tonic-gate 	**  be one since the server would only return one and we wouldn't
43797c478bd9Sstevel@tonic-gate 	**  know if there were others available.
43807c478bd9Sstevel@tonic-gate 	*/
43817c478bd9Sstevel@tonic-gate 
43827c478bd9Sstevel@tonic-gate 	if (bitset(MF_SINGLEMATCH, map->map_mflags))
43837c478bd9Sstevel@tonic-gate 		lmap->ldap_sizelimit = 2;
43847c478bd9Sstevel@tonic-gate 
43857c478bd9Sstevel@tonic-gate 	/* If setting defaults, don't process ldap_filter and ldap_attr */
43867c478bd9Sstevel@tonic-gate 	if (lmap == LDAPDefaults)
43877c478bd9Sstevel@tonic-gate 		return true;
43887c478bd9Sstevel@tonic-gate 
43897c478bd9Sstevel@tonic-gate 	if (lmap->ldap_filter != NULL)
43907c478bd9Sstevel@tonic-gate 		lmap->ldap_filter = newstr(ldapmap_dequote(lmap->ldap_filter));
43917c478bd9Sstevel@tonic-gate 	else
43927c478bd9Sstevel@tonic-gate 	{
43937c478bd9Sstevel@tonic-gate 		if (!bitset(MCF_OPTFILE, map->map_class->map_cflags))
43947c478bd9Sstevel@tonic-gate 		{
43957c478bd9Sstevel@tonic-gate 			syserr("No filter given in map %s", map->map_mname);
43967c478bd9Sstevel@tonic-gate 			return false;
43977c478bd9Sstevel@tonic-gate 		}
43987c478bd9Sstevel@tonic-gate 	}
43997c478bd9Sstevel@tonic-gate 
44007c478bd9Sstevel@tonic-gate 	if (!attrssetup && lmap->ldap_attr[0] != NULL)
44017c478bd9Sstevel@tonic-gate 	{
44027c478bd9Sstevel@tonic-gate 		bool recurse = false;
44037c478bd9Sstevel@tonic-gate 		bool normalseen = false;
44047c478bd9Sstevel@tonic-gate 
44057c478bd9Sstevel@tonic-gate 		i = 0;
44067c478bd9Sstevel@tonic-gate 		p = ldapmap_dequote(lmap->ldap_attr[0]);
44077c478bd9Sstevel@tonic-gate 		lmap->ldap_attr[0] = NULL;
44087c478bd9Sstevel@tonic-gate 
44097c478bd9Sstevel@tonic-gate 		/* Prime the attr list with the objectClass attribute */
44107c478bd9Sstevel@tonic-gate 		lmap->ldap_attr[i] = "objectClass";
44117c478bd9Sstevel@tonic-gate 		lmap->ldap_attr_type[i] = SM_LDAP_ATTR_OBJCLASS;
44127c478bd9Sstevel@tonic-gate 		lmap->ldap_attr_needobjclass[i] = NULL;
44137c478bd9Sstevel@tonic-gate 		i++;
44147c478bd9Sstevel@tonic-gate 
44157c478bd9Sstevel@tonic-gate 		while (p != NULL)
44167c478bd9Sstevel@tonic-gate 		{
44177c478bd9Sstevel@tonic-gate 			char *v;
44187c478bd9Sstevel@tonic-gate 
44197c478bd9Sstevel@tonic-gate 			while (isascii(*p) && isspace(*p))
44207c478bd9Sstevel@tonic-gate 				p++;
44217c478bd9Sstevel@tonic-gate 			if (*p == '\0')
44227c478bd9Sstevel@tonic-gate 				break;
44237c478bd9Sstevel@tonic-gate 			v = p;
44247c478bd9Sstevel@tonic-gate 			p = strchr(v, ',');
44257c478bd9Sstevel@tonic-gate 			if (p != NULL)
44267c478bd9Sstevel@tonic-gate 				*p++ = '\0';
44277c478bd9Sstevel@tonic-gate 
44287c478bd9Sstevel@tonic-gate 			if (i >= LDAPMAP_MAX_ATTR)
44297c478bd9Sstevel@tonic-gate 			{
44307c478bd9Sstevel@tonic-gate 				syserr("Too many return attributes in %s (max %d)",
44317c478bd9Sstevel@tonic-gate 				       map->map_mname, LDAPMAP_MAX_ATTR);
44327c478bd9Sstevel@tonic-gate 				return false;
44337c478bd9Sstevel@tonic-gate 			}
44347c478bd9Sstevel@tonic-gate 			if (*v != '\0')
44357c478bd9Sstevel@tonic-gate 			{
44367c478bd9Sstevel@tonic-gate 				int j;
44377c478bd9Sstevel@tonic-gate 				int use;
44387c478bd9Sstevel@tonic-gate 				char *type;
44397c478bd9Sstevel@tonic-gate 				char *needobjclass;
44407c478bd9Sstevel@tonic-gate 
44417c478bd9Sstevel@tonic-gate 				type = strchr(v, ':');
44427c478bd9Sstevel@tonic-gate 				if (type != NULL)
44437c478bd9Sstevel@tonic-gate 				{
44447c478bd9Sstevel@tonic-gate 					*type++ = '\0';
44457c478bd9Sstevel@tonic-gate 					needobjclass = strchr(type, ':');
44467c478bd9Sstevel@tonic-gate 					if (needobjclass != NULL)
44477c478bd9Sstevel@tonic-gate 						*needobjclass++ = '\0';
44487c478bd9Sstevel@tonic-gate 				}
44497c478bd9Sstevel@tonic-gate 				else
44507c478bd9Sstevel@tonic-gate 				{
44517c478bd9Sstevel@tonic-gate 					needobjclass = NULL;
44527c478bd9Sstevel@tonic-gate 				}
44537c478bd9Sstevel@tonic-gate 
44547c478bd9Sstevel@tonic-gate 				use = i;
44557c478bd9Sstevel@tonic-gate 
44567c478bd9Sstevel@tonic-gate 				/* allow override on "objectClass" type */
44577c478bd9Sstevel@tonic-gate 				if (sm_strcasecmp(v, "objectClass") == 0 &&
44587c478bd9Sstevel@tonic-gate 				    lmap->ldap_attr_type[0] == SM_LDAP_ATTR_OBJCLASS)
44597c478bd9Sstevel@tonic-gate 				{
44607c478bd9Sstevel@tonic-gate 					use = 0;
44617c478bd9Sstevel@tonic-gate 				}
44627c478bd9Sstevel@tonic-gate 				else
44637c478bd9Sstevel@tonic-gate 				{
44647c478bd9Sstevel@tonic-gate 					/*
44657c478bd9Sstevel@tonic-gate 					**  Don't add something to attribute
44667c478bd9Sstevel@tonic-gate 					**  list twice.
44677c478bd9Sstevel@tonic-gate 					*/
44687c478bd9Sstevel@tonic-gate 
44697c478bd9Sstevel@tonic-gate 					for (j = 1; j < i; j++)
44707c478bd9Sstevel@tonic-gate 					{
44717c478bd9Sstevel@tonic-gate 						if (sm_strcasecmp(v, lmap->ldap_attr[j]) == 0)
44727c478bd9Sstevel@tonic-gate 						{
44737c478bd9Sstevel@tonic-gate 							syserr("Duplicate attribute (%s) in %s",
44747c478bd9Sstevel@tonic-gate 							       v, map->map_mname);
44757c478bd9Sstevel@tonic-gate 							return false;
44767c478bd9Sstevel@tonic-gate 						}
44777c478bd9Sstevel@tonic-gate 					}
44787c478bd9Sstevel@tonic-gate 
44797c478bd9Sstevel@tonic-gate 					lmap->ldap_attr[use] = newstr(v);
44807c478bd9Sstevel@tonic-gate 					if (needobjclass != NULL &&
44817c478bd9Sstevel@tonic-gate 					    *needobjclass != '\0' &&
44827c478bd9Sstevel@tonic-gate 					    *needobjclass != '*')
44837c478bd9Sstevel@tonic-gate 					{
44847c478bd9Sstevel@tonic-gate 						lmap->ldap_attr_needobjclass[use] = newstr(needobjclass);
44857c478bd9Sstevel@tonic-gate 					}
44867c478bd9Sstevel@tonic-gate 					else
44877c478bd9Sstevel@tonic-gate 					{
44887c478bd9Sstevel@tonic-gate 						lmap->ldap_attr_needobjclass[use] = NULL;
44897c478bd9Sstevel@tonic-gate 					}
44907c478bd9Sstevel@tonic-gate 
44917c478bd9Sstevel@tonic-gate 				}
44927c478bd9Sstevel@tonic-gate 
44937c478bd9Sstevel@tonic-gate 				if (type != NULL && *type != '\0')
44947c478bd9Sstevel@tonic-gate 				{
44957c478bd9Sstevel@tonic-gate 					if (sm_strcasecmp(type, "dn") == 0)
44967c478bd9Sstevel@tonic-gate 					{
44977c478bd9Sstevel@tonic-gate 						recurse = true;
44987c478bd9Sstevel@tonic-gate 						lmap->ldap_attr_type[use] = SM_LDAP_ATTR_DN;
44997c478bd9Sstevel@tonic-gate 					}
45007c478bd9Sstevel@tonic-gate 					else if (sm_strcasecmp(type, "filter") == 0)
45017c478bd9Sstevel@tonic-gate 					{
45027c478bd9Sstevel@tonic-gate 						recurse = true;
45037c478bd9Sstevel@tonic-gate 						lmap->ldap_attr_type[use] = SM_LDAP_ATTR_FILTER;
45047c478bd9Sstevel@tonic-gate 					}
45057c478bd9Sstevel@tonic-gate 					else if (sm_strcasecmp(type, "url") == 0)
45067c478bd9Sstevel@tonic-gate 					{
45077c478bd9Sstevel@tonic-gate 						recurse = true;
45087c478bd9Sstevel@tonic-gate 						lmap->ldap_attr_type[use] = SM_LDAP_ATTR_URL;
45097c478bd9Sstevel@tonic-gate 					}
45107c478bd9Sstevel@tonic-gate 					else if (sm_strcasecmp(type, "normal") == 0)
45117c478bd9Sstevel@tonic-gate 					{
45127c478bd9Sstevel@tonic-gate 						lmap->ldap_attr_type[use] = SM_LDAP_ATTR_NORMAL;
45137c478bd9Sstevel@tonic-gate 						normalseen = true;
45147c478bd9Sstevel@tonic-gate 					}
45157c478bd9Sstevel@tonic-gate 					else
45167c478bd9Sstevel@tonic-gate 					{
45177c478bd9Sstevel@tonic-gate 						syserr("Unknown attribute type (%s) in %s",
45187c478bd9Sstevel@tonic-gate 						       type, map->map_mname);
45197c478bd9Sstevel@tonic-gate 						return false;
45207c478bd9Sstevel@tonic-gate 					}
45217c478bd9Sstevel@tonic-gate 				}
45227c478bd9Sstevel@tonic-gate 				else
45237c478bd9Sstevel@tonic-gate 				{
45247c478bd9Sstevel@tonic-gate 					lmap->ldap_attr_type[use] = SM_LDAP_ATTR_NORMAL;
45257c478bd9Sstevel@tonic-gate 					normalseen = true;
45267c478bd9Sstevel@tonic-gate 				}
45277c478bd9Sstevel@tonic-gate 				i++;
45287c478bd9Sstevel@tonic-gate 			}
45297c478bd9Sstevel@tonic-gate 		}
45307c478bd9Sstevel@tonic-gate 		lmap->ldap_attr[i] = NULL;
45317c478bd9Sstevel@tonic-gate 
45327c478bd9Sstevel@tonic-gate 		/* Set in case needed in future code */
45337c478bd9Sstevel@tonic-gate 		attrssetup = true;
45347c478bd9Sstevel@tonic-gate 
45357c478bd9Sstevel@tonic-gate 		if (recurse && !normalseen)
45367c478bd9Sstevel@tonic-gate 		{
45377c478bd9Sstevel@tonic-gate 			syserr("LDAP recursion requested in %s but no returnable attribute given",
45387c478bd9Sstevel@tonic-gate 			       map->map_mname);
45397c478bd9Sstevel@tonic-gate 			return false;
45407c478bd9Sstevel@tonic-gate 		}
45417c478bd9Sstevel@tonic-gate 		if (recurse && lmap->ldap_attrsonly == LDAPMAP_TRUE)
45427c478bd9Sstevel@tonic-gate 		{
45437c478bd9Sstevel@tonic-gate 			syserr("LDAP recursion requested in %s can not be used with -n",
45447c478bd9Sstevel@tonic-gate 			       map->map_mname);
45457c478bd9Sstevel@tonic-gate 			return false;
45467c478bd9Sstevel@tonic-gate 		}
45477c478bd9Sstevel@tonic-gate 	}
45487c478bd9Sstevel@tonic-gate 	map->map_db1 = (ARBPTR_T) lmap;
45497c478bd9Sstevel@tonic-gate 	return true;
45507c478bd9Sstevel@tonic-gate }
45517c478bd9Sstevel@tonic-gate 
45527c478bd9Sstevel@tonic-gate /*
45537c478bd9Sstevel@tonic-gate **  LDAPMAP_SET_DEFAULTS -- Read default map spec from LDAPDefaults in .cf
45547c478bd9Sstevel@tonic-gate **
45557c478bd9Sstevel@tonic-gate **	Parameters:
45567c478bd9Sstevel@tonic-gate **		spec -- map argument string from LDAPDefaults option
45577c478bd9Sstevel@tonic-gate **
45587c478bd9Sstevel@tonic-gate **	Returns:
45597c478bd9Sstevel@tonic-gate **		None.
45607c478bd9Sstevel@tonic-gate */
45617c478bd9Sstevel@tonic-gate 
45627c478bd9Sstevel@tonic-gate void
45637c478bd9Sstevel@tonic-gate ldapmap_set_defaults(spec)
45647c478bd9Sstevel@tonic-gate 	char *spec;
45657c478bd9Sstevel@tonic-gate {
45667c478bd9Sstevel@tonic-gate 	STAB *class;
45677c478bd9Sstevel@tonic-gate 	MAP map;
45687c478bd9Sstevel@tonic-gate 
45697c478bd9Sstevel@tonic-gate 	/* Allocate and set the default values */
45707c478bd9Sstevel@tonic-gate 	if (LDAPDefaults == NULL)
45717c478bd9Sstevel@tonic-gate 		LDAPDefaults = (SM_LDAP_STRUCT *) xalloc(sizeof *LDAPDefaults);
45727c478bd9Sstevel@tonic-gate 	sm_ldap_clear(LDAPDefaults);
45737c478bd9Sstevel@tonic-gate 
45747c478bd9Sstevel@tonic-gate 	memset(&map, '\0', sizeof map);
45757c478bd9Sstevel@tonic-gate 
45767c478bd9Sstevel@tonic-gate 	/* look up the class */
45777c478bd9Sstevel@tonic-gate 	class = stab("ldap", ST_MAPCLASS, ST_FIND);
45787c478bd9Sstevel@tonic-gate 	if (class == NULL)
45797c478bd9Sstevel@tonic-gate 	{
45807c478bd9Sstevel@tonic-gate 		syserr("readcf: LDAPDefaultSpec: class ldap not available");
45817c478bd9Sstevel@tonic-gate 		return;
45827c478bd9Sstevel@tonic-gate 	}
45837c478bd9Sstevel@tonic-gate 	map.map_class = &class->s_mapclass;
45847c478bd9Sstevel@tonic-gate 	map.map_db1 = (ARBPTR_T) LDAPDefaults;
45857c478bd9Sstevel@tonic-gate 	map.map_mname = "O LDAPDefaultSpec";
45867c478bd9Sstevel@tonic-gate 
45877c478bd9Sstevel@tonic-gate 	(void) ldapmap_parseargs(&map, spec);
45887c478bd9Sstevel@tonic-gate 
45897c478bd9Sstevel@tonic-gate 	/* These should never be set in LDAPDefaults */
45907c478bd9Sstevel@tonic-gate 	if (map.map_mflags != (MF_TRY0NULL|MF_TRY1NULL) ||
45917c478bd9Sstevel@tonic-gate 	    map.map_spacesub != SpaceSub ||
45927c478bd9Sstevel@tonic-gate 	    map.map_app != NULL ||
45937c478bd9Sstevel@tonic-gate 	    map.map_tapp != NULL)
45947c478bd9Sstevel@tonic-gate 	{
45957c478bd9Sstevel@tonic-gate 		syserr("readcf: option LDAPDefaultSpec: Do not set non-LDAP specific flags");
45967c478bd9Sstevel@tonic-gate 		SM_FREE_CLR(map.map_app);
45977c478bd9Sstevel@tonic-gate 		SM_FREE_CLR(map.map_tapp);
45987c478bd9Sstevel@tonic-gate 	}
45997c478bd9Sstevel@tonic-gate 
46007c478bd9Sstevel@tonic-gate 	if (LDAPDefaults->ldap_filter != NULL)
46017c478bd9Sstevel@tonic-gate 	{
46027c478bd9Sstevel@tonic-gate 		syserr("readcf: option LDAPDefaultSpec: Do not set the LDAP search filter");
46037c478bd9Sstevel@tonic-gate 
46047c478bd9Sstevel@tonic-gate 		/* don't free, it isn't malloc'ed in parseargs */
46057c478bd9Sstevel@tonic-gate 		LDAPDefaults->ldap_filter = NULL;
46067c478bd9Sstevel@tonic-gate 	}
46077c478bd9Sstevel@tonic-gate 
46087c478bd9Sstevel@tonic-gate 	if (LDAPDefaults->ldap_attr[0] != NULL)
46097c478bd9Sstevel@tonic-gate 	{
46107c478bd9Sstevel@tonic-gate 		syserr("readcf: option LDAPDefaultSpec: Do not set the requested LDAP attributes");
46117c478bd9Sstevel@tonic-gate 		/* don't free, they aren't malloc'ed in parseargs */
46127c478bd9Sstevel@tonic-gate 		LDAPDefaults->ldap_attr[0] = NULL;
46137c478bd9Sstevel@tonic-gate 	}
46147c478bd9Sstevel@tonic-gate }
46157c478bd9Sstevel@tonic-gate #endif /* LDAPMAP */
46167c478bd9Sstevel@tonic-gate /*
46177c478bd9Sstevel@tonic-gate **  PH map
46187c478bd9Sstevel@tonic-gate */
46197c478bd9Sstevel@tonic-gate 
46207c478bd9Sstevel@tonic-gate #if PH_MAP
46217c478bd9Sstevel@tonic-gate 
46227c478bd9Sstevel@tonic-gate /*
46237c478bd9Sstevel@tonic-gate **  Support for the CCSO Nameserver (ph/qi).
46247c478bd9Sstevel@tonic-gate **  This code is intended to replace the so-called "ph mailer".
46257c478bd9Sstevel@tonic-gate **  Contributed by Mark D. Roth <roth@uiuc.edu>.  Contact him for support.
46267c478bd9Sstevel@tonic-gate */
46277c478bd9Sstevel@tonic-gate 
46287c478bd9Sstevel@tonic-gate /* what version of the ph map code we're running */
46297c478bd9Sstevel@tonic-gate static char phmap_id[128];
46307c478bd9Sstevel@tonic-gate 
46317c478bd9Sstevel@tonic-gate /* sendmail version for phmap id string */
46327c478bd9Sstevel@tonic-gate extern const char Version[];
46337c478bd9Sstevel@tonic-gate 
46347c478bd9Sstevel@tonic-gate /* assume we're using nph-1.2.x if not specified */
46357c478bd9Sstevel@tonic-gate # ifndef NPH_VERSION
46367c478bd9Sstevel@tonic-gate #  define NPH_VERSION		10200
46377c478bd9Sstevel@tonic-gate # endif
46387c478bd9Sstevel@tonic-gate 
46397c478bd9Sstevel@tonic-gate /* compatibility for versions older than nph-1.2.0 */
46407c478bd9Sstevel@tonic-gate # if NPH_VERSION < 10200
46417c478bd9Sstevel@tonic-gate #  define PH_OPEN_ROUNDROBIN	PH_ROUNDROBIN
46427c478bd9Sstevel@tonic-gate #  define PH_OPEN_DONTID	PH_DONTID
46437c478bd9Sstevel@tonic-gate #  define PH_CLOSE_FAST		PH_FASTCLOSE
46447c478bd9Sstevel@tonic-gate #  define PH_ERR_DATAERR	PH_DATAERR
46457c478bd9Sstevel@tonic-gate #  define PH_ERR_NOMATCH	PH_NOMATCH
46467c478bd9Sstevel@tonic-gate # endif /* NPH_VERSION < 10200 */
46477c478bd9Sstevel@tonic-gate 
46487c478bd9Sstevel@tonic-gate /*
46497c478bd9Sstevel@tonic-gate **  PH_MAP_PARSEARGS -- parse ph map definition args.
46507c478bd9Sstevel@tonic-gate */
46517c478bd9Sstevel@tonic-gate 
46527c478bd9Sstevel@tonic-gate bool
46537c478bd9Sstevel@tonic-gate ph_map_parseargs(map, args)
46547c478bd9Sstevel@tonic-gate 	MAP *map;
46557c478bd9Sstevel@tonic-gate 	char *args;
46567c478bd9Sstevel@tonic-gate {
46577c478bd9Sstevel@tonic-gate 	register bool done;
46587c478bd9Sstevel@tonic-gate 	register char *p = args;
46597c478bd9Sstevel@tonic-gate 	PH_MAP_STRUCT *pmap = NULL;
46607c478bd9Sstevel@tonic-gate 
46617c478bd9Sstevel@tonic-gate 	/* initialize version string */
46627c478bd9Sstevel@tonic-gate 	(void) sm_snprintf(phmap_id, sizeof phmap_id,
46637c478bd9Sstevel@tonic-gate 			   "sendmail-%s phmap-20010529 libphclient-%s",
46647c478bd9Sstevel@tonic-gate 			   Version, libphclient_version);
46657c478bd9Sstevel@tonic-gate 
46667c478bd9Sstevel@tonic-gate 	pmap = (PH_MAP_STRUCT *) xalloc(sizeof *pmap);
46677c478bd9Sstevel@tonic-gate 
46687c478bd9Sstevel@tonic-gate 	/* defaults */
46697c478bd9Sstevel@tonic-gate 	pmap->ph_servers = NULL;
46707c478bd9Sstevel@tonic-gate 	pmap->ph_field_list = NULL;
46717c478bd9Sstevel@tonic-gate 	pmap->ph = NULL;
46727c478bd9Sstevel@tonic-gate 	pmap->ph_timeout = 0;
46737c478bd9Sstevel@tonic-gate 	pmap->ph_fastclose = 0;
46747c478bd9Sstevel@tonic-gate 
46757c478bd9Sstevel@tonic-gate 	map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL;
46767c478bd9Sstevel@tonic-gate 	for (;;)
46777c478bd9Sstevel@tonic-gate 	{
46787c478bd9Sstevel@tonic-gate 		while (isascii(*p) && isspace(*p))
46797c478bd9Sstevel@tonic-gate 			p++;
46807c478bd9Sstevel@tonic-gate 		if (*p != '-')
46817c478bd9Sstevel@tonic-gate 			break;
46827c478bd9Sstevel@tonic-gate 		switch (*++p)
46837c478bd9Sstevel@tonic-gate 		{
46847c478bd9Sstevel@tonic-gate 		  case 'N':
46857c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_INCLNULL;
46867c478bd9Sstevel@tonic-gate 			map->map_mflags &= ~MF_TRY0NULL;
46877c478bd9Sstevel@tonic-gate 			break;
46887c478bd9Sstevel@tonic-gate 
46897c478bd9Sstevel@tonic-gate 		  case 'O':
46907c478bd9Sstevel@tonic-gate 			map->map_mflags &= ~MF_TRY1NULL;
46917c478bd9Sstevel@tonic-gate 			break;
46927c478bd9Sstevel@tonic-gate 
46937c478bd9Sstevel@tonic-gate 		  case 'o':
46947c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_OPTIONAL;
46957c478bd9Sstevel@tonic-gate 			break;
46967c478bd9Sstevel@tonic-gate 
46977c478bd9Sstevel@tonic-gate 		  case 'f':
46987c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_NOFOLDCASE;
46997c478bd9Sstevel@tonic-gate 			break;
47007c478bd9Sstevel@tonic-gate 
47017c478bd9Sstevel@tonic-gate 		  case 'm':
47027c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_MATCHONLY;
47037c478bd9Sstevel@tonic-gate 			break;
47047c478bd9Sstevel@tonic-gate 
47057c478bd9Sstevel@tonic-gate 		  case 'A':
47067c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_APPEND;
47077c478bd9Sstevel@tonic-gate 			break;
47087c478bd9Sstevel@tonic-gate 
47097c478bd9Sstevel@tonic-gate 		  case 'q':
47107c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_KEEPQUOTES;
47117c478bd9Sstevel@tonic-gate 			break;
47127c478bd9Sstevel@tonic-gate 
47137c478bd9Sstevel@tonic-gate 		  case 't':
47147c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_NODEFER;
47157c478bd9Sstevel@tonic-gate 			break;
47167c478bd9Sstevel@tonic-gate 
47177c478bd9Sstevel@tonic-gate 		  case 'a':
47187c478bd9Sstevel@tonic-gate 			map->map_app = ++p;
47197c478bd9Sstevel@tonic-gate 			break;
47207c478bd9Sstevel@tonic-gate 
47217c478bd9Sstevel@tonic-gate 		  case 'T':
47227c478bd9Sstevel@tonic-gate 			map->map_tapp = ++p;
47237c478bd9Sstevel@tonic-gate 			break;
47247c478bd9Sstevel@tonic-gate 
47257c478bd9Sstevel@tonic-gate 		  case 'l':
47267c478bd9Sstevel@tonic-gate 			while (isascii(*++p) && isspace(*p))
47277c478bd9Sstevel@tonic-gate 				continue;
47287c478bd9Sstevel@tonic-gate 			pmap->ph_timeout = atoi(p);
47297c478bd9Sstevel@tonic-gate 			break;
47307c478bd9Sstevel@tonic-gate 
47317c478bd9Sstevel@tonic-gate 		  case 'S':
47327c478bd9Sstevel@tonic-gate 			map->map_spacesub = *++p;
47337c478bd9Sstevel@tonic-gate 			break;
47347c478bd9Sstevel@tonic-gate 
47357c478bd9Sstevel@tonic-gate 		  case 'D':
47367c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_DEFER;
47377c478bd9Sstevel@tonic-gate 			break;
47387c478bd9Sstevel@tonic-gate 
47397c478bd9Sstevel@tonic-gate 		  case 'h':		/* PH server list */
47407c478bd9Sstevel@tonic-gate 			while (isascii(*++p) && isspace(*p))
47417c478bd9Sstevel@tonic-gate 				continue;
47427c478bd9Sstevel@tonic-gate 			pmap->ph_servers = p;
47437c478bd9Sstevel@tonic-gate 			break;
47447c478bd9Sstevel@tonic-gate 
47457c478bd9Sstevel@tonic-gate 		  case 'k':		/* fields to search for */
47467c478bd9Sstevel@tonic-gate 			while (isascii(*++p) && isspace(*p))
47477c478bd9Sstevel@tonic-gate 				continue;
47487c478bd9Sstevel@tonic-gate 			pmap->ph_field_list = p;
47497c478bd9Sstevel@tonic-gate 			break;
47507c478bd9Sstevel@tonic-gate 
47517c478bd9Sstevel@tonic-gate 		  default:
47527c478bd9Sstevel@tonic-gate 			syserr("ph_map_parseargs: unknown option -%c", *p);
47537c478bd9Sstevel@tonic-gate 		}
47547c478bd9Sstevel@tonic-gate 
47557c478bd9Sstevel@tonic-gate 		/* try to account for quoted strings */
47567c478bd9Sstevel@tonic-gate 		done = isascii(*p) && isspace(*p);
47577c478bd9Sstevel@tonic-gate 		while (*p != '\0' && !done)
47587c478bd9Sstevel@tonic-gate 		{
47597c478bd9Sstevel@tonic-gate 			if (*p == '"')
47607c478bd9Sstevel@tonic-gate 			{
47617c478bd9Sstevel@tonic-gate 				while (*++p != '"' && *p != '\0')
47627c478bd9Sstevel@tonic-gate 					continue;
47637c478bd9Sstevel@tonic-gate 				if (*p != '\0')
47647c478bd9Sstevel@tonic-gate 					p++;
47657c478bd9Sstevel@tonic-gate 			}
47667c478bd9Sstevel@tonic-gate 			else
47677c478bd9Sstevel@tonic-gate 				p++;
47687c478bd9Sstevel@tonic-gate 			done = isascii(*p) && isspace(*p);
47697c478bd9Sstevel@tonic-gate 		}
47707c478bd9Sstevel@tonic-gate 
47717c478bd9Sstevel@tonic-gate 		if (*p != '\0')
47727c478bd9Sstevel@tonic-gate 			*p++ = '\0';
47737c478bd9Sstevel@tonic-gate 	}
47747c478bd9Sstevel@tonic-gate 
47757c478bd9Sstevel@tonic-gate 	if (map->map_app != NULL)
47767c478bd9Sstevel@tonic-gate 		map->map_app = newstr(ph_map_dequote(map->map_app));
47777c478bd9Sstevel@tonic-gate 	if (map->map_tapp != NULL)
47787c478bd9Sstevel@tonic-gate 		map->map_tapp = newstr(ph_map_dequote(map->map_tapp));
47797c478bd9Sstevel@tonic-gate 
47807c478bd9Sstevel@tonic-gate 	if (pmap->ph_field_list != NULL)
47817c478bd9Sstevel@tonic-gate 		pmap->ph_field_list = newstr(ph_map_dequote(pmap->ph_field_list));
47827c478bd9Sstevel@tonic-gate 
47837c478bd9Sstevel@tonic-gate 	if (pmap->ph_servers != NULL)
47847c478bd9Sstevel@tonic-gate 		pmap->ph_servers = newstr(ph_map_dequote(pmap->ph_servers));
47857c478bd9Sstevel@tonic-gate 	else
47867c478bd9Sstevel@tonic-gate 	{
47877c478bd9Sstevel@tonic-gate 		syserr("ph_map_parseargs: -h flag is required");
47887c478bd9Sstevel@tonic-gate 		return false;
47897c478bd9Sstevel@tonic-gate 	}
47907c478bd9Sstevel@tonic-gate 
47917c478bd9Sstevel@tonic-gate 	map->map_db1 = (ARBPTR_T) pmap;
47927c478bd9Sstevel@tonic-gate 	return true;
47937c478bd9Sstevel@tonic-gate }
47947c478bd9Sstevel@tonic-gate 
47957c478bd9Sstevel@tonic-gate /*
47967c478bd9Sstevel@tonic-gate **  PH_MAP_CLOSE -- close the connection to the ph server
47977c478bd9Sstevel@tonic-gate */
47987c478bd9Sstevel@tonic-gate 
47997c478bd9Sstevel@tonic-gate void
48007c478bd9Sstevel@tonic-gate ph_map_close(map)
48017c478bd9Sstevel@tonic-gate 	MAP *map;
48027c478bd9Sstevel@tonic-gate {
48037c478bd9Sstevel@tonic-gate 	PH_MAP_STRUCT *pmap;
48047c478bd9Sstevel@tonic-gate 
48057c478bd9Sstevel@tonic-gate 	pmap = (PH_MAP_STRUCT *)map->map_db1;
48067c478bd9Sstevel@tonic-gate 	if (tTd(38, 9))
48077c478bd9Sstevel@tonic-gate 		sm_dprintf("ph_map_close(%s): pmap->ph_fastclose=%d\n",
48087c478bd9Sstevel@tonic-gate 			   map->map_mname, pmap->ph_fastclose);
48097c478bd9Sstevel@tonic-gate 
48107c478bd9Sstevel@tonic-gate 
48117c478bd9Sstevel@tonic-gate 	if (pmap->ph != NULL)
48127c478bd9Sstevel@tonic-gate 	{
48137c478bd9Sstevel@tonic-gate 		ph_set_sendhook(pmap->ph, NULL);
48147c478bd9Sstevel@tonic-gate 		ph_set_recvhook(pmap->ph, NULL);
48157c478bd9Sstevel@tonic-gate 		ph_close(pmap->ph, pmap->ph_fastclose);
48167c478bd9Sstevel@tonic-gate 	}
48177c478bd9Sstevel@tonic-gate 
48187c478bd9Sstevel@tonic-gate 	map->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
48197c478bd9Sstevel@tonic-gate }
48207c478bd9Sstevel@tonic-gate 
48217c478bd9Sstevel@tonic-gate static jmp_buf  PHTimeout;
48227c478bd9Sstevel@tonic-gate 
48237c478bd9Sstevel@tonic-gate /* ARGSUSED */
48247c478bd9Sstevel@tonic-gate static void
48257c478bd9Sstevel@tonic-gate ph_timeout(unused)
48267c478bd9Sstevel@tonic-gate 	int unused;
48277c478bd9Sstevel@tonic-gate {
48287c478bd9Sstevel@tonic-gate 	/*
48297c478bd9Sstevel@tonic-gate 	**  NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
48307c478bd9Sstevel@tonic-gate 	**	ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
48317c478bd9Sstevel@tonic-gate 	**	DOING.
48327c478bd9Sstevel@tonic-gate 	*/
48337c478bd9Sstevel@tonic-gate 
48347c478bd9Sstevel@tonic-gate 	errno = ETIMEDOUT;
48357c478bd9Sstevel@tonic-gate 	longjmp(PHTimeout, 1);
48367c478bd9Sstevel@tonic-gate }
48377c478bd9Sstevel@tonic-gate 
48387c478bd9Sstevel@tonic-gate static void
48397c478bd9Sstevel@tonic-gate #if NPH_VERSION >= 10200
48407c478bd9Sstevel@tonic-gate ph_map_send_debug(appdata, text)
48417c478bd9Sstevel@tonic-gate 	void *appdata;
48427c478bd9Sstevel@tonic-gate #else
48437c478bd9Sstevel@tonic-gate ph_map_send_debug(text)
48447c478bd9Sstevel@tonic-gate #endif
48457c478bd9Sstevel@tonic-gate 	char *text;
48467c478bd9Sstevel@tonic-gate {
48477c478bd9Sstevel@tonic-gate 	if (LogLevel > 9)
48487c478bd9Sstevel@tonic-gate 		sm_syslog(LOG_NOTICE, CurEnv->e_id,
48497c478bd9Sstevel@tonic-gate 			  "ph_map_send_debug: ==> %s", text);
48507c478bd9Sstevel@tonic-gate 	if (tTd(38, 20))
48517c478bd9Sstevel@tonic-gate 		sm_dprintf("ph_map_send_debug: ==> %s\n", text);
48527c478bd9Sstevel@tonic-gate }
48537c478bd9Sstevel@tonic-gate 
48547c478bd9Sstevel@tonic-gate static void
48557c478bd9Sstevel@tonic-gate #if NPH_VERSION >= 10200
48567c478bd9Sstevel@tonic-gate ph_map_recv_debug(appdata, text)
48577c478bd9Sstevel@tonic-gate 	void *appdata;
48587c478bd9Sstevel@tonic-gate #else
48597c478bd9Sstevel@tonic-gate ph_map_recv_debug(text)
48607c478bd9Sstevel@tonic-gate #endif
48617c478bd9Sstevel@tonic-gate 	char *text;
48627c478bd9Sstevel@tonic-gate {
48637c478bd9Sstevel@tonic-gate 	if (LogLevel > 10)
48647c478bd9Sstevel@tonic-gate 		sm_syslog(LOG_NOTICE, CurEnv->e_id,
48657c478bd9Sstevel@tonic-gate 			  "ph_map_recv_debug: <== %s", text);
48667c478bd9Sstevel@tonic-gate 	if (tTd(38, 21))
48677c478bd9Sstevel@tonic-gate 		sm_dprintf("ph_map_recv_debug: <== %s\n", text);
48687c478bd9Sstevel@tonic-gate }
48697c478bd9Sstevel@tonic-gate 
48707c478bd9Sstevel@tonic-gate /*
48717c478bd9Sstevel@tonic-gate **  PH_MAP_OPEN -- sub for opening PH map
48727c478bd9Sstevel@tonic-gate */
48737c478bd9Sstevel@tonic-gate bool
48747c478bd9Sstevel@tonic-gate ph_map_open(map, mode)
48757c478bd9Sstevel@tonic-gate 	MAP *map;
48767c478bd9Sstevel@tonic-gate 	int mode;
48777c478bd9Sstevel@tonic-gate {
48787c478bd9Sstevel@tonic-gate 	PH_MAP_STRUCT *pmap;
48797c478bd9Sstevel@tonic-gate 	register SM_EVENT *ev = NULL;
48807c478bd9Sstevel@tonic-gate 	int save_errno = 0;
48817c478bd9Sstevel@tonic-gate 	char *hostlist, *host;
48827c478bd9Sstevel@tonic-gate 
48837c478bd9Sstevel@tonic-gate 	if (tTd(38, 2))
48847c478bd9Sstevel@tonic-gate 		sm_dprintf("ph_map_open(%s)\n", map->map_mname);
48857c478bd9Sstevel@tonic-gate 
48867c478bd9Sstevel@tonic-gate 	mode &= O_ACCMODE;
48877c478bd9Sstevel@tonic-gate 	if (mode != O_RDONLY)
48887c478bd9Sstevel@tonic-gate 	{
48897c478bd9Sstevel@tonic-gate 		/* issue a pseudo-error message */
48907c478bd9Sstevel@tonic-gate 		errno = SM_EMAPCANTWRITE;
48917c478bd9Sstevel@tonic-gate 		return false;
48927c478bd9Sstevel@tonic-gate 	}
48937c478bd9Sstevel@tonic-gate 
48947c478bd9Sstevel@tonic-gate 	if (CurEnv != NULL && CurEnv->e_sendmode == SM_DEFER &&
48957c478bd9Sstevel@tonic-gate 	    bitset(MF_DEFER, map->map_mflags))
48967c478bd9Sstevel@tonic-gate 	{
48977c478bd9Sstevel@tonic-gate 		if (tTd(9, 1))
48987c478bd9Sstevel@tonic-gate 			sm_dprintf("ph_map_open(%s) => DEFERRED\n",
48997c478bd9Sstevel@tonic-gate 				   map->map_mname);
49007c478bd9Sstevel@tonic-gate 
49017c478bd9Sstevel@tonic-gate 		/*
49027c478bd9Sstevel@tonic-gate 		**  Unset MF_DEFER here so that map_lookup() returns
49037c478bd9Sstevel@tonic-gate 		**  a temporary failure using the bogus map and
49047c478bd9Sstevel@tonic-gate 		**  map->map_tapp instead of the default permanent error.
49057c478bd9Sstevel@tonic-gate 		*/
49067c478bd9Sstevel@tonic-gate 
49077c478bd9Sstevel@tonic-gate 		map->map_mflags &= ~MF_DEFER;
49087c478bd9Sstevel@tonic-gate 		return false;
49097c478bd9Sstevel@tonic-gate 	}
49107c478bd9Sstevel@tonic-gate 
49117c478bd9Sstevel@tonic-gate 	pmap = (PH_MAP_STRUCT *)map->map_db1;
49127c478bd9Sstevel@tonic-gate 	pmap->ph_fastclose = 0;		/* refresh field for reopen */
49137c478bd9Sstevel@tonic-gate 
49147c478bd9Sstevel@tonic-gate 	/* try each host in the list */
49157c478bd9Sstevel@tonic-gate 	hostlist = newstr(pmap->ph_servers);
49167c478bd9Sstevel@tonic-gate 	for (host = strtok(hostlist, " ");
49177c478bd9Sstevel@tonic-gate 	     host != NULL;
49187c478bd9Sstevel@tonic-gate 	     host = strtok(NULL, " "))
49197c478bd9Sstevel@tonic-gate 	{
49207c478bd9Sstevel@tonic-gate 		/* set timeout */
49217c478bd9Sstevel@tonic-gate 		if (pmap->ph_timeout != 0)
49227c478bd9Sstevel@tonic-gate 		{
49237c478bd9Sstevel@tonic-gate 			if (setjmp(PHTimeout) != 0)
49247c478bd9Sstevel@tonic-gate 			{
49257c478bd9Sstevel@tonic-gate 				ev = NULL;
49267c478bd9Sstevel@tonic-gate 				if (LogLevel > 1)
49277c478bd9Sstevel@tonic-gate 					sm_syslog(LOG_NOTICE, CurEnv->e_id,
49287c478bd9Sstevel@tonic-gate 						  "timeout connecting to PH server %.100s",
49297c478bd9Sstevel@tonic-gate 						  host);
49307c478bd9Sstevel@tonic-gate 				errno = ETIMEDOUT;
49317c478bd9Sstevel@tonic-gate 				goto ph_map_open_abort;
49327c478bd9Sstevel@tonic-gate 			}
49337c478bd9Sstevel@tonic-gate 			ev = sm_setevent(pmap->ph_timeout, ph_timeout, 0);
49347c478bd9Sstevel@tonic-gate 		}
49357c478bd9Sstevel@tonic-gate 
49367c478bd9Sstevel@tonic-gate 		/* open connection to server */
49377c478bd9Sstevel@tonic-gate 		if (ph_open(&(pmap->ph), host,
49387c478bd9Sstevel@tonic-gate 			    PH_OPEN_ROUNDROBIN|PH_OPEN_DONTID,
49397c478bd9Sstevel@tonic-gate 			    ph_map_send_debug, ph_map_recv_debug
49407c478bd9Sstevel@tonic-gate #if NPH_VERSION >= 10200
49417c478bd9Sstevel@tonic-gate 			    , NULL
49427c478bd9Sstevel@tonic-gate #endif
49437c478bd9Sstevel@tonic-gate 			    ) == 0
49447c478bd9Sstevel@tonic-gate 		    && ph_id(pmap->ph, phmap_id) == 0)
49457c478bd9Sstevel@tonic-gate 		{
49467c478bd9Sstevel@tonic-gate 			if (ev != NULL)
49477c478bd9Sstevel@tonic-gate 				sm_clrevent(ev);
49487c478bd9Sstevel@tonic-gate 			sm_free(hostlist); /* XXX */
49497c478bd9Sstevel@tonic-gate 			return true;
49507c478bd9Sstevel@tonic-gate 		}
49517c478bd9Sstevel@tonic-gate 
49527c478bd9Sstevel@tonic-gate   ph_map_open_abort:
49537c478bd9Sstevel@tonic-gate 		save_errno = errno;
49547c478bd9Sstevel@tonic-gate 		if (ev != NULL)
49557c478bd9Sstevel@tonic-gate 			sm_clrevent(ev);
49567c478bd9Sstevel@tonic-gate 		pmap->ph_fastclose = PH_CLOSE_FAST;
49577c478bd9Sstevel@tonic-gate 		ph_map_close(map);
49587c478bd9Sstevel@tonic-gate 		errno = save_errno;
49597c478bd9Sstevel@tonic-gate 	}
49607c478bd9Sstevel@tonic-gate 
49617c478bd9Sstevel@tonic-gate 	if (bitset(MF_NODEFER, map->map_mflags))
49627c478bd9Sstevel@tonic-gate 	{
49637c478bd9Sstevel@tonic-gate 		if (errno == 0)
49647c478bd9Sstevel@tonic-gate 			errno = EAGAIN;
49657c478bd9Sstevel@tonic-gate 		syserr("ph_map_open: %s: cannot connect to PH server",
49667c478bd9Sstevel@tonic-gate 		       map->map_mname);
49677c478bd9Sstevel@tonic-gate 	}
49687c478bd9Sstevel@tonic-gate 	else if (!bitset(MF_OPTIONAL, map->map_mflags) && LogLevel > 1)
49697c478bd9Sstevel@tonic-gate 		sm_syslog(LOG_NOTICE, CurEnv->e_id,
49707c478bd9Sstevel@tonic-gate 			  "ph_map_open: %s: cannot connect to PH server",
49717c478bd9Sstevel@tonic-gate 			  map->map_mname);
49727c478bd9Sstevel@tonic-gate 	sm_free(hostlist); /* XXX */
49737c478bd9Sstevel@tonic-gate 	return false;
49747c478bd9Sstevel@tonic-gate }
49757c478bd9Sstevel@tonic-gate 
49767c478bd9Sstevel@tonic-gate /*
49777c478bd9Sstevel@tonic-gate **  PH_MAP_LOOKUP -- look up key from ph server
49787c478bd9Sstevel@tonic-gate */
49797c478bd9Sstevel@tonic-gate 
49807c478bd9Sstevel@tonic-gate char *
49817c478bd9Sstevel@tonic-gate ph_map_lookup(map, key, args, pstat)
49827c478bd9Sstevel@tonic-gate 	MAP *map;
49837c478bd9Sstevel@tonic-gate 	char *key;
49847c478bd9Sstevel@tonic-gate 	char **args;
49857c478bd9Sstevel@tonic-gate 	int *pstat;
49867c478bd9Sstevel@tonic-gate {
49877c478bd9Sstevel@tonic-gate 	int i, save_errno = 0;
49887c478bd9Sstevel@tonic-gate 	register SM_EVENT *ev = NULL;
49897c478bd9Sstevel@tonic-gate 	PH_MAP_STRUCT *pmap;
49907c478bd9Sstevel@tonic-gate 	char *value = NULL;
49917c478bd9Sstevel@tonic-gate 
49927c478bd9Sstevel@tonic-gate 	pmap = (PH_MAP_STRUCT *)map->map_db1;
49937c478bd9Sstevel@tonic-gate 
49947c478bd9Sstevel@tonic-gate 	*pstat = EX_OK;
49957c478bd9Sstevel@tonic-gate 
49967c478bd9Sstevel@tonic-gate 	/* set timeout */
49977c478bd9Sstevel@tonic-gate 	if (pmap->ph_timeout != 0)
49987c478bd9Sstevel@tonic-gate 	{
49997c478bd9Sstevel@tonic-gate 		if (setjmp(PHTimeout) != 0)
50007c478bd9Sstevel@tonic-gate 		{
50017c478bd9Sstevel@tonic-gate 			ev = NULL;
50027c478bd9Sstevel@tonic-gate 			if (LogLevel > 1)
50037c478bd9Sstevel@tonic-gate 				sm_syslog(LOG_NOTICE, CurEnv->e_id,
50047c478bd9Sstevel@tonic-gate 					  "timeout during PH lookup of %.100s",
50057c478bd9Sstevel@tonic-gate 					  key);
50067c478bd9Sstevel@tonic-gate 			errno = ETIMEDOUT;
50077c478bd9Sstevel@tonic-gate 			*pstat = EX_TEMPFAIL;
50087c478bd9Sstevel@tonic-gate 			goto ph_map_lookup_abort;
50097c478bd9Sstevel@tonic-gate 		}
50107c478bd9Sstevel@tonic-gate 		ev = sm_setevent(pmap->ph_timeout, ph_timeout, 0);
50117c478bd9Sstevel@tonic-gate 	}
50127c478bd9Sstevel@tonic-gate 
50137c478bd9Sstevel@tonic-gate 	/* perform lookup */
50147c478bd9Sstevel@tonic-gate 	i = ph_email_resolve(pmap->ph, key, pmap->ph_field_list, &value);
50157c478bd9Sstevel@tonic-gate 	if (i == -1)
50167c478bd9Sstevel@tonic-gate 		*pstat = EX_TEMPFAIL;
50177c478bd9Sstevel@tonic-gate 	else if (i == PH_ERR_NOMATCH || i == PH_ERR_DATAERR)
50187c478bd9Sstevel@tonic-gate 		*pstat = EX_UNAVAILABLE;
50197c478bd9Sstevel@tonic-gate 
50207c478bd9Sstevel@tonic-gate   ph_map_lookup_abort:
50217c478bd9Sstevel@tonic-gate 	if (ev != NULL)
50227c478bd9Sstevel@tonic-gate 		sm_clrevent(ev);
50237c478bd9Sstevel@tonic-gate 
50247c478bd9Sstevel@tonic-gate 	/*
50257c478bd9Sstevel@tonic-gate 	**  Close the connection if the timer popped
50267c478bd9Sstevel@tonic-gate 	**  or we got a temporary PH error
50277c478bd9Sstevel@tonic-gate 	*/
50287c478bd9Sstevel@tonic-gate 
50297c478bd9Sstevel@tonic-gate 	if (*pstat == EX_TEMPFAIL)
50307c478bd9Sstevel@tonic-gate 	{
50317c478bd9Sstevel@tonic-gate 		save_errno = errno;
50327c478bd9Sstevel@tonic-gate 		pmap->ph_fastclose = PH_CLOSE_FAST;
50337c478bd9Sstevel@tonic-gate 		ph_map_close(map);
50347c478bd9Sstevel@tonic-gate 		errno = save_errno;
50357c478bd9Sstevel@tonic-gate 	}
50367c478bd9Sstevel@tonic-gate 
50377c478bd9Sstevel@tonic-gate 	if (*pstat == EX_OK)
50387c478bd9Sstevel@tonic-gate 	{
50397c478bd9Sstevel@tonic-gate 		if (tTd(38,20))
50407c478bd9Sstevel@tonic-gate 			sm_dprintf("ph_map_lookup: %s => %s\n", key, value);
50417c478bd9Sstevel@tonic-gate 
50427c478bd9Sstevel@tonic-gate 		if (bitset(MF_MATCHONLY, map->map_mflags))
50437c478bd9Sstevel@tonic-gate 			return map_rewrite(map, key, strlen(key), NULL);
50447c478bd9Sstevel@tonic-gate 		else
50457c478bd9Sstevel@tonic-gate 			return map_rewrite(map, value, strlen(value), args);
50467c478bd9Sstevel@tonic-gate 	}
50477c478bd9Sstevel@tonic-gate 
50487c478bd9Sstevel@tonic-gate 	return NULL;
50497c478bd9Sstevel@tonic-gate }
50507c478bd9Sstevel@tonic-gate #endif /* PH_MAP */
50517c478bd9Sstevel@tonic-gate /*
50527c478bd9Sstevel@tonic-gate **  syslog map
50537c478bd9Sstevel@tonic-gate */
50547c478bd9Sstevel@tonic-gate 
50557c478bd9Sstevel@tonic-gate #define map_prio	map_lockfd	/* overload field */
50567c478bd9Sstevel@tonic-gate 
50577c478bd9Sstevel@tonic-gate /*
50587c478bd9Sstevel@tonic-gate **  SYSLOG_MAP_PARSEARGS -- check for priority level to syslog messages.
50597c478bd9Sstevel@tonic-gate */
50607c478bd9Sstevel@tonic-gate 
50617c478bd9Sstevel@tonic-gate bool
50627c478bd9Sstevel@tonic-gate syslog_map_parseargs(map, args)
50637c478bd9Sstevel@tonic-gate 	MAP *map;
50647c478bd9Sstevel@tonic-gate 	char *args;
50657c478bd9Sstevel@tonic-gate {
50667c478bd9Sstevel@tonic-gate 	char *p = args;
50677c478bd9Sstevel@tonic-gate 	char *priority = NULL;
50687c478bd9Sstevel@tonic-gate 
50697c478bd9Sstevel@tonic-gate 	/* there is no check whether there is really an argument */
50707c478bd9Sstevel@tonic-gate 	while (*p != '\0')
50717c478bd9Sstevel@tonic-gate 	{
50727c478bd9Sstevel@tonic-gate 		while (isascii(*p) && isspace(*p))
50737c478bd9Sstevel@tonic-gate 			p++;
50747c478bd9Sstevel@tonic-gate 		if (*p != '-')
50757c478bd9Sstevel@tonic-gate 			break;
50767c478bd9Sstevel@tonic-gate 		++p;
50777c478bd9Sstevel@tonic-gate 		if (*p == 'D')
50787c478bd9Sstevel@tonic-gate 		{
50797c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_DEFER;
50807c478bd9Sstevel@tonic-gate 			++p;
50817c478bd9Sstevel@tonic-gate 		}
50827c478bd9Sstevel@tonic-gate 		else if (*p == 'S')
50837c478bd9Sstevel@tonic-gate 		{
50847c478bd9Sstevel@tonic-gate 			map->map_spacesub = *++p;
50857c478bd9Sstevel@tonic-gate 			if (*p != '\0')
50867c478bd9Sstevel@tonic-gate 				p++;
50877c478bd9Sstevel@tonic-gate 		}
50887c478bd9Sstevel@tonic-gate 		else if (*p == 'L')
50897c478bd9Sstevel@tonic-gate 		{
50907c478bd9Sstevel@tonic-gate 			while (*++p != '\0' && isascii(*p) && isspace(*p))
50917c478bd9Sstevel@tonic-gate 				continue;
50927c478bd9Sstevel@tonic-gate 			if (*p == '\0')
50937c478bd9Sstevel@tonic-gate 				break;
50947c478bd9Sstevel@tonic-gate 			priority = p;
50957c478bd9Sstevel@tonic-gate 			while (*p != '\0' && !(isascii(*p) && isspace(*p)))
50967c478bd9Sstevel@tonic-gate 				p++;
50977c478bd9Sstevel@tonic-gate 			if (*p != '\0')
50987c478bd9Sstevel@tonic-gate 				*p++ = '\0';
50997c478bd9Sstevel@tonic-gate 		}
51007c478bd9Sstevel@tonic-gate 		else
51017c478bd9Sstevel@tonic-gate 		{
51027c478bd9Sstevel@tonic-gate 			syserr("Illegal option %c map syslog", *p);
51037c478bd9Sstevel@tonic-gate 			++p;
51047c478bd9Sstevel@tonic-gate 		}
51057c478bd9Sstevel@tonic-gate 	}
51067c478bd9Sstevel@tonic-gate 
51077c478bd9Sstevel@tonic-gate 	if (priority == NULL)
51087c478bd9Sstevel@tonic-gate 		map->map_prio = LOG_INFO;
51097c478bd9Sstevel@tonic-gate 	else
51107c478bd9Sstevel@tonic-gate 	{
51117c478bd9Sstevel@tonic-gate 		if (sm_strncasecmp("LOG_", priority, 4) == 0)
51127c478bd9Sstevel@tonic-gate 			priority += 4;
51137c478bd9Sstevel@tonic-gate 
51147c478bd9Sstevel@tonic-gate #ifdef LOG_EMERG
51157c478bd9Sstevel@tonic-gate 		if (sm_strcasecmp("EMERG", priority) == 0)
51167c478bd9Sstevel@tonic-gate 			map->map_prio = LOG_EMERG;
51177c478bd9Sstevel@tonic-gate 		else
51187c478bd9Sstevel@tonic-gate #endif /* LOG_EMERG */
51197c478bd9Sstevel@tonic-gate #ifdef LOG_ALERT
51207c478bd9Sstevel@tonic-gate 		if (sm_strcasecmp("ALERT", priority) == 0)
51217c478bd9Sstevel@tonic-gate 			map->map_prio = LOG_ALERT;
51227c478bd9Sstevel@tonic-gate 		else
51237c478bd9Sstevel@tonic-gate #endif /* LOG_ALERT */
51247c478bd9Sstevel@tonic-gate #ifdef LOG_CRIT
51257c478bd9Sstevel@tonic-gate 		if (sm_strcasecmp("CRIT", priority) == 0)
51267c478bd9Sstevel@tonic-gate 			map->map_prio = LOG_CRIT;
51277c478bd9Sstevel@tonic-gate 		else
51287c478bd9Sstevel@tonic-gate #endif /* LOG_CRIT */
51297c478bd9Sstevel@tonic-gate #ifdef LOG_ERR
51307c478bd9Sstevel@tonic-gate 		if (sm_strcasecmp("ERR", priority) == 0)
51317c478bd9Sstevel@tonic-gate 			map->map_prio = LOG_ERR;
51327c478bd9Sstevel@tonic-gate 		else
51337c478bd9Sstevel@tonic-gate #endif /* LOG_ERR */
51347c478bd9Sstevel@tonic-gate #ifdef LOG_WARNING
51357c478bd9Sstevel@tonic-gate 		if (sm_strcasecmp("WARNING", priority) == 0)
51367c478bd9Sstevel@tonic-gate 			map->map_prio = LOG_WARNING;
51377c478bd9Sstevel@tonic-gate 		else
51387c478bd9Sstevel@tonic-gate #endif /* LOG_WARNING */
51397c478bd9Sstevel@tonic-gate #ifdef LOG_NOTICE
51407c478bd9Sstevel@tonic-gate 		if (sm_strcasecmp("NOTICE", priority) == 0)
51417c478bd9Sstevel@tonic-gate 			map->map_prio = LOG_NOTICE;
51427c478bd9Sstevel@tonic-gate 		else
51437c478bd9Sstevel@tonic-gate #endif /* LOG_NOTICE */
51447c478bd9Sstevel@tonic-gate #ifdef LOG_INFO
51457c478bd9Sstevel@tonic-gate 		if (sm_strcasecmp("INFO", priority) == 0)
51467c478bd9Sstevel@tonic-gate 			map->map_prio = LOG_INFO;
51477c478bd9Sstevel@tonic-gate 		else
51487c478bd9Sstevel@tonic-gate #endif /* LOG_INFO */
51497c478bd9Sstevel@tonic-gate #ifdef LOG_DEBUG
51507c478bd9Sstevel@tonic-gate 		if (sm_strcasecmp("DEBUG", priority) == 0)
51517c478bd9Sstevel@tonic-gate 			map->map_prio = LOG_DEBUG;
51527c478bd9Sstevel@tonic-gate 		else
51537c478bd9Sstevel@tonic-gate #endif /* LOG_DEBUG */
51547c478bd9Sstevel@tonic-gate 		{
51557c478bd9Sstevel@tonic-gate 			syserr("syslog_map_parseargs: Unknown priority %s",
51567c478bd9Sstevel@tonic-gate 			       priority);
51577c478bd9Sstevel@tonic-gate 			return false;
51587c478bd9Sstevel@tonic-gate 		}
51597c478bd9Sstevel@tonic-gate 	}
51607c478bd9Sstevel@tonic-gate 	return true;
51617c478bd9Sstevel@tonic-gate }
51627c478bd9Sstevel@tonic-gate 
51637c478bd9Sstevel@tonic-gate /*
51647c478bd9Sstevel@tonic-gate **  SYSLOG_MAP_LOOKUP -- rewrite and syslog message.  Always return empty string
51657c478bd9Sstevel@tonic-gate */
51667c478bd9Sstevel@tonic-gate 
51677c478bd9Sstevel@tonic-gate char *
51687c478bd9Sstevel@tonic-gate syslog_map_lookup(map, string, args, statp)
51697c478bd9Sstevel@tonic-gate 	MAP *map;
51707c478bd9Sstevel@tonic-gate 	char *string;
51717c478bd9Sstevel@tonic-gate 	char **args;
51727c478bd9Sstevel@tonic-gate 	int *statp;
51737c478bd9Sstevel@tonic-gate {
51747c478bd9Sstevel@tonic-gate 	char *ptr = map_rewrite(map, string, strlen(string), args);
51757c478bd9Sstevel@tonic-gate 
51767c478bd9Sstevel@tonic-gate 	if (ptr != NULL)
51777c478bd9Sstevel@tonic-gate 	{
51787c478bd9Sstevel@tonic-gate 		if (tTd(38, 20))
51797c478bd9Sstevel@tonic-gate 			sm_dprintf("syslog_map_lookup(%s (priority %d): %s\n",
51807c478bd9Sstevel@tonic-gate 				map->map_mname, map->map_prio, ptr);
51817c478bd9Sstevel@tonic-gate 
51827c478bd9Sstevel@tonic-gate 		sm_syslog(map->map_prio, CurEnv->e_id, "%s", ptr);
51837c478bd9Sstevel@tonic-gate 	}
51847c478bd9Sstevel@tonic-gate 
51857c478bd9Sstevel@tonic-gate 	*statp = EX_OK;
51867c478bd9Sstevel@tonic-gate 	return "";
51877c478bd9Sstevel@tonic-gate }
51887c478bd9Sstevel@tonic-gate 
51897c478bd9Sstevel@tonic-gate /*
51907c478bd9Sstevel@tonic-gate **  HESIOD Modules
51917c478bd9Sstevel@tonic-gate */
51927c478bd9Sstevel@tonic-gate 
51937c478bd9Sstevel@tonic-gate #if HESIOD
51947c478bd9Sstevel@tonic-gate 
51957c478bd9Sstevel@tonic-gate bool
51967c478bd9Sstevel@tonic-gate hes_map_open(map, mode)
51977c478bd9Sstevel@tonic-gate 	MAP *map;
51987c478bd9Sstevel@tonic-gate 	int mode;
51997c478bd9Sstevel@tonic-gate {
52007c478bd9Sstevel@tonic-gate 	if (tTd(38, 2))
52017c478bd9Sstevel@tonic-gate 		sm_dprintf("hes_map_open(%s, %s, %d)\n",
52027c478bd9Sstevel@tonic-gate 			map->map_mname, map->map_file, mode);
52037c478bd9Sstevel@tonic-gate 
52047c478bd9Sstevel@tonic-gate 	if (mode != O_RDONLY)
52057c478bd9Sstevel@tonic-gate 	{
52067c478bd9Sstevel@tonic-gate 		/* issue a pseudo-error message */
52077c478bd9Sstevel@tonic-gate 		errno = SM_EMAPCANTWRITE;
52087c478bd9Sstevel@tonic-gate 		return false;
52097c478bd9Sstevel@tonic-gate 	}
52107c478bd9Sstevel@tonic-gate 
52117c478bd9Sstevel@tonic-gate # ifdef HESIOD_INIT
52127c478bd9Sstevel@tonic-gate 	if (HesiodContext != NULL || hesiod_init(&HesiodContext) == 0)
52137c478bd9Sstevel@tonic-gate 		return true;
52147c478bd9Sstevel@tonic-gate 
52157c478bd9Sstevel@tonic-gate 	if (!bitset(MF_OPTIONAL, map->map_mflags))
52167c478bd9Sstevel@tonic-gate 		syserr("451 4.3.5 cannot initialize Hesiod map (%s)",
52177c478bd9Sstevel@tonic-gate 			sm_errstring(errno));
52187c478bd9Sstevel@tonic-gate 	return false;
52197c478bd9Sstevel@tonic-gate # else /* HESIOD_INIT */
52207c478bd9Sstevel@tonic-gate 	if (hes_error() == HES_ER_UNINIT)
52217c478bd9Sstevel@tonic-gate 		hes_init();
52227c478bd9Sstevel@tonic-gate 	switch (hes_error())
52237c478bd9Sstevel@tonic-gate 	{
52247c478bd9Sstevel@tonic-gate 	  case HES_ER_OK:
52257c478bd9Sstevel@tonic-gate 	  case HES_ER_NOTFOUND:
52267c478bd9Sstevel@tonic-gate 		return true;
52277c478bd9Sstevel@tonic-gate 	}
52287c478bd9Sstevel@tonic-gate 
52297c478bd9Sstevel@tonic-gate 	if (!bitset(MF_OPTIONAL, map->map_mflags))
52307c478bd9Sstevel@tonic-gate 		syserr("451 4.3.5 cannot initialize Hesiod map (%d)", hes_error());
52317c478bd9Sstevel@tonic-gate 
52327c478bd9Sstevel@tonic-gate 	return false;
52337c478bd9Sstevel@tonic-gate # endif /* HESIOD_INIT */
52347c478bd9Sstevel@tonic-gate }
52357c478bd9Sstevel@tonic-gate 
52367c478bd9Sstevel@tonic-gate char *
52377c478bd9Sstevel@tonic-gate hes_map_lookup(map, name, av, statp)
52387c478bd9Sstevel@tonic-gate 	MAP *map;
52397c478bd9Sstevel@tonic-gate 	char *name;
52407c478bd9Sstevel@tonic-gate 	char **av;
52417c478bd9Sstevel@tonic-gate 	int *statp;
52427c478bd9Sstevel@tonic-gate {
52437c478bd9Sstevel@tonic-gate 	char **hp;
52447c478bd9Sstevel@tonic-gate 
52457c478bd9Sstevel@tonic-gate 	if (tTd(38, 20))
52467c478bd9Sstevel@tonic-gate 		sm_dprintf("hes_map_lookup(%s, %s)\n", map->map_file, name);
52477c478bd9Sstevel@tonic-gate 
52487c478bd9Sstevel@tonic-gate 	if (name[0] == '\\')
52497c478bd9Sstevel@tonic-gate 	{
52507c478bd9Sstevel@tonic-gate 		char *np;
52517c478bd9Sstevel@tonic-gate 		int nl;
52527c478bd9Sstevel@tonic-gate 		int save_errno;
52537c478bd9Sstevel@tonic-gate 		char nbuf[MAXNAME];
52547c478bd9Sstevel@tonic-gate 
52557c478bd9Sstevel@tonic-gate 		nl = strlen(name);
52567c478bd9Sstevel@tonic-gate 		if (nl < sizeof nbuf - 1)
52577c478bd9Sstevel@tonic-gate 			np = nbuf;
52587c478bd9Sstevel@tonic-gate 		else
52597c478bd9Sstevel@tonic-gate 			np = xalloc(strlen(name) + 2);
52607c478bd9Sstevel@tonic-gate 		np[0] = '\\';
52617c478bd9Sstevel@tonic-gate 		(void) sm_strlcpy(&np[1], name, (sizeof nbuf) - 1);
52627c478bd9Sstevel@tonic-gate # ifdef HESIOD_INIT
52637c478bd9Sstevel@tonic-gate 		hp = hesiod_resolve(HesiodContext, np, map->map_file);
52647c478bd9Sstevel@tonic-gate # else /* HESIOD_INIT */
52657c478bd9Sstevel@tonic-gate 		hp = hes_resolve(np, map->map_file);
52667c478bd9Sstevel@tonic-gate # endif /* HESIOD_INIT */
52677c478bd9Sstevel@tonic-gate 		save_errno = errno;
52687c478bd9Sstevel@tonic-gate 		if (np != nbuf)
52697c478bd9Sstevel@tonic-gate 			sm_free(np); /* XXX */
52707c478bd9Sstevel@tonic-gate 		errno = save_errno;
52717c478bd9Sstevel@tonic-gate 	}
52727c478bd9Sstevel@tonic-gate 	else
52737c478bd9Sstevel@tonic-gate 	{
52747c478bd9Sstevel@tonic-gate # ifdef HESIOD_INIT
52757c478bd9Sstevel@tonic-gate 		hp = hesiod_resolve(HesiodContext, name, map->map_file);
52767c478bd9Sstevel@tonic-gate # else /* HESIOD_INIT */
52777c478bd9Sstevel@tonic-gate 		hp = hes_resolve(name, map->map_file);
52787c478bd9Sstevel@tonic-gate # endif /* HESIOD_INIT */
52797c478bd9Sstevel@tonic-gate 	}
52807c478bd9Sstevel@tonic-gate # ifdef HESIOD_INIT
52817c478bd9Sstevel@tonic-gate 	if (hp == NULL || *hp == NULL)
52827c478bd9Sstevel@tonic-gate 	{
52837c478bd9Sstevel@tonic-gate 		switch (errno)
52847c478bd9Sstevel@tonic-gate 		{
52857c478bd9Sstevel@tonic-gate 		  case ENOENT:
52867c478bd9Sstevel@tonic-gate 			  *statp = EX_NOTFOUND;
52877c478bd9Sstevel@tonic-gate 			  break;
52887c478bd9Sstevel@tonic-gate 		  case ECONNREFUSED:
52897c478bd9Sstevel@tonic-gate 			  *statp = EX_TEMPFAIL;
52907c478bd9Sstevel@tonic-gate 			  break;
52917c478bd9Sstevel@tonic-gate 		  case EMSGSIZE:
52927c478bd9Sstevel@tonic-gate 		  case ENOMEM:
52937c478bd9Sstevel@tonic-gate 		  default:
52947c478bd9Sstevel@tonic-gate 			  *statp = EX_UNAVAILABLE;
52957c478bd9Sstevel@tonic-gate 			  break;
52967c478bd9Sstevel@tonic-gate 		}
52977c478bd9Sstevel@tonic-gate 		if (hp != NULL)
52987c478bd9Sstevel@tonic-gate 			hesiod_free_list(HesiodContext, hp);
52997c478bd9Sstevel@tonic-gate 		return NULL;
53007c478bd9Sstevel@tonic-gate 	}
53017c478bd9Sstevel@tonic-gate # else /* HESIOD_INIT */
53027c478bd9Sstevel@tonic-gate 	if (hp == NULL || hp[0] == NULL)
53037c478bd9Sstevel@tonic-gate 	{
53047c478bd9Sstevel@tonic-gate 		switch (hes_error())
53057c478bd9Sstevel@tonic-gate 		{
53067c478bd9Sstevel@tonic-gate 		  case HES_ER_OK:
53077c478bd9Sstevel@tonic-gate 			*statp = EX_OK;
53087c478bd9Sstevel@tonic-gate 			break;
53097c478bd9Sstevel@tonic-gate 
53107c478bd9Sstevel@tonic-gate 		  case HES_ER_NOTFOUND:
53117c478bd9Sstevel@tonic-gate 			*statp = EX_NOTFOUND;
53127c478bd9Sstevel@tonic-gate 			break;
53137c478bd9Sstevel@tonic-gate 
53147c478bd9Sstevel@tonic-gate 		  case HES_ER_CONFIG:
53157c478bd9Sstevel@tonic-gate 			*statp = EX_UNAVAILABLE;
53167c478bd9Sstevel@tonic-gate 			break;
53177c478bd9Sstevel@tonic-gate 
53187c478bd9Sstevel@tonic-gate 		  case HES_ER_NET:
53197c478bd9Sstevel@tonic-gate 			*statp = EX_TEMPFAIL;
53207c478bd9Sstevel@tonic-gate 			break;
53217c478bd9Sstevel@tonic-gate 		}
53227c478bd9Sstevel@tonic-gate 		return NULL;
53237c478bd9Sstevel@tonic-gate 	}
53247c478bd9Sstevel@tonic-gate # endif /* HESIOD_INIT */
53257c478bd9Sstevel@tonic-gate 
53267c478bd9Sstevel@tonic-gate 	if (bitset(MF_MATCHONLY, map->map_mflags))
53277c478bd9Sstevel@tonic-gate 		return map_rewrite(map, name, strlen(name), NULL);
53287c478bd9Sstevel@tonic-gate 	else
53297c478bd9Sstevel@tonic-gate 		return map_rewrite(map, hp[0], strlen(hp[0]), av);
53307c478bd9Sstevel@tonic-gate }
53317c478bd9Sstevel@tonic-gate 
53327c478bd9Sstevel@tonic-gate /*
53337c478bd9Sstevel@tonic-gate **  HES_MAP_CLOSE -- free the Hesiod context
53347c478bd9Sstevel@tonic-gate */
53357c478bd9Sstevel@tonic-gate 
53367c478bd9Sstevel@tonic-gate void
53377c478bd9Sstevel@tonic-gate hes_map_close(map)
53387c478bd9Sstevel@tonic-gate 	MAP *map;
53397c478bd9Sstevel@tonic-gate {
53407c478bd9Sstevel@tonic-gate 	if (tTd(38, 20))
53417c478bd9Sstevel@tonic-gate 		sm_dprintf("hes_map_close(%s)\n", map->map_file);
53427c478bd9Sstevel@tonic-gate 
53437c478bd9Sstevel@tonic-gate # ifdef HESIOD_INIT
53447c478bd9Sstevel@tonic-gate 	/* Free the hesiod context */
53457c478bd9Sstevel@tonic-gate 	if (HesiodContext != NULL)
53467c478bd9Sstevel@tonic-gate 	{
53477c478bd9Sstevel@tonic-gate 		hesiod_end(HesiodContext);
53487c478bd9Sstevel@tonic-gate 		HesiodContext = NULL;
53497c478bd9Sstevel@tonic-gate 	}
53507c478bd9Sstevel@tonic-gate # endif /* HESIOD_INIT */
53517c478bd9Sstevel@tonic-gate }
53527c478bd9Sstevel@tonic-gate 
53537c478bd9Sstevel@tonic-gate #endif /* HESIOD */
53547c478bd9Sstevel@tonic-gate /*
53557c478bd9Sstevel@tonic-gate **  NeXT NETINFO Modules
53567c478bd9Sstevel@tonic-gate */
53577c478bd9Sstevel@tonic-gate 
53587c478bd9Sstevel@tonic-gate #if NETINFO
53597c478bd9Sstevel@tonic-gate 
53607c478bd9Sstevel@tonic-gate # define NETINFO_DEFAULT_DIR		"/aliases"
53617c478bd9Sstevel@tonic-gate # define NETINFO_DEFAULT_PROPERTY	"members"
53627c478bd9Sstevel@tonic-gate 
53637c478bd9Sstevel@tonic-gate /*
53647c478bd9Sstevel@tonic-gate **  NI_MAP_OPEN -- open NetInfo Aliases
53657c478bd9Sstevel@tonic-gate */
53667c478bd9Sstevel@tonic-gate 
53677c478bd9Sstevel@tonic-gate bool
53687c478bd9Sstevel@tonic-gate ni_map_open(map, mode)
53697c478bd9Sstevel@tonic-gate 	MAP *map;
53707c478bd9Sstevel@tonic-gate 	int mode;
53717c478bd9Sstevel@tonic-gate {
53727c478bd9Sstevel@tonic-gate 	if (tTd(38, 2))
53737c478bd9Sstevel@tonic-gate 		sm_dprintf("ni_map_open(%s, %s, %d)\n",
53747c478bd9Sstevel@tonic-gate 			map->map_mname, map->map_file, mode);
53757c478bd9Sstevel@tonic-gate 	mode &= O_ACCMODE;
53767c478bd9Sstevel@tonic-gate 
53777c478bd9Sstevel@tonic-gate 	if (*map->map_file == '\0')
53787c478bd9Sstevel@tonic-gate 		map->map_file = NETINFO_DEFAULT_DIR;
53797c478bd9Sstevel@tonic-gate 
53807c478bd9Sstevel@tonic-gate 	if (map->map_valcolnm == NULL)
53817c478bd9Sstevel@tonic-gate 		map->map_valcolnm = NETINFO_DEFAULT_PROPERTY;
53827c478bd9Sstevel@tonic-gate 
53837c478bd9Sstevel@tonic-gate 	if (map->map_coldelim == '\0')
53847c478bd9Sstevel@tonic-gate 	{
53857c478bd9Sstevel@tonic-gate 		if (bitset(MF_ALIAS, map->map_mflags))
53867c478bd9Sstevel@tonic-gate 			map->map_coldelim = ',';
53877c478bd9Sstevel@tonic-gate 		else if (bitset(MF_FILECLASS, map->map_mflags))
53887c478bd9Sstevel@tonic-gate 			map->map_coldelim = ' ';
53897c478bd9Sstevel@tonic-gate 	}
53907c478bd9Sstevel@tonic-gate 	return true;
53917c478bd9Sstevel@tonic-gate }
53927c478bd9Sstevel@tonic-gate 
53937c478bd9Sstevel@tonic-gate 
53947c478bd9Sstevel@tonic-gate /*
53957c478bd9Sstevel@tonic-gate **  NI_MAP_LOOKUP -- look up a datum in NetInfo
53967c478bd9Sstevel@tonic-gate */
53977c478bd9Sstevel@tonic-gate 
53987c478bd9Sstevel@tonic-gate char *
53997c478bd9Sstevel@tonic-gate ni_map_lookup(map, name, av, statp)
54007c478bd9Sstevel@tonic-gate 	MAP *map;
54017c478bd9Sstevel@tonic-gate 	char *name;
54027c478bd9Sstevel@tonic-gate 	char **av;
54037c478bd9Sstevel@tonic-gate 	int *statp;
54047c478bd9Sstevel@tonic-gate {
54057c478bd9Sstevel@tonic-gate 	char *res;
54067c478bd9Sstevel@tonic-gate 	char *propval;
54077c478bd9Sstevel@tonic-gate 
54087c478bd9Sstevel@tonic-gate 	if (tTd(38, 20))
54097c478bd9Sstevel@tonic-gate 		sm_dprintf("ni_map_lookup(%s, %s)\n", map->map_mname, name);
54107c478bd9Sstevel@tonic-gate 
54117c478bd9Sstevel@tonic-gate 	propval = ni_propval(map->map_file, map->map_keycolnm, name,
54127c478bd9Sstevel@tonic-gate 			     map->map_valcolnm, map->map_coldelim);
54137c478bd9Sstevel@tonic-gate 
54147c478bd9Sstevel@tonic-gate 	if (propval == NULL)
54157c478bd9Sstevel@tonic-gate 		return NULL;
54167c478bd9Sstevel@tonic-gate 
54177c478bd9Sstevel@tonic-gate 	SM_TRY
54187c478bd9Sstevel@tonic-gate 		if (bitset(MF_MATCHONLY, map->map_mflags))
54197c478bd9Sstevel@tonic-gate 			res = map_rewrite(map, name, strlen(name), NULL);
54207c478bd9Sstevel@tonic-gate 		else
54217c478bd9Sstevel@tonic-gate 			res = map_rewrite(map, propval, strlen(propval), av);
54227c478bd9Sstevel@tonic-gate 	SM_FINALLY
54237c478bd9Sstevel@tonic-gate 		sm_free(propval);
54247c478bd9Sstevel@tonic-gate 	SM_END_TRY
54257c478bd9Sstevel@tonic-gate 	return res;
54267c478bd9Sstevel@tonic-gate }
54277c478bd9Sstevel@tonic-gate 
54287c478bd9Sstevel@tonic-gate 
54297c478bd9Sstevel@tonic-gate static bool
54307c478bd9Sstevel@tonic-gate ni_getcanonname(name, hbsize, statp)
54317c478bd9Sstevel@tonic-gate 	char *name;
54327c478bd9Sstevel@tonic-gate 	int hbsize;
54337c478bd9Sstevel@tonic-gate 	int *statp;
54347c478bd9Sstevel@tonic-gate {
54357c478bd9Sstevel@tonic-gate 	char *vptr;
54367c478bd9Sstevel@tonic-gate 	char *ptr;
54377c478bd9Sstevel@tonic-gate 	char nbuf[MAXNAME + 1];
54387c478bd9Sstevel@tonic-gate 
54397c478bd9Sstevel@tonic-gate 	if (tTd(38, 20))
54407c478bd9Sstevel@tonic-gate 		sm_dprintf("ni_getcanonname(%s)\n", name);
54417c478bd9Sstevel@tonic-gate 
54427c478bd9Sstevel@tonic-gate 	if (sm_strlcpy(nbuf, name, sizeof nbuf) >= sizeof nbuf)
54437c478bd9Sstevel@tonic-gate 	{
54447c478bd9Sstevel@tonic-gate 		*statp = EX_UNAVAILABLE;
54457c478bd9Sstevel@tonic-gate 		return false;
54467c478bd9Sstevel@tonic-gate 	}
54477c478bd9Sstevel@tonic-gate 	(void) shorten_hostname(nbuf);
54487c478bd9Sstevel@tonic-gate 
54497c478bd9Sstevel@tonic-gate 	/* we only accept single token search key */
54507c478bd9Sstevel@tonic-gate 	if (strchr(nbuf, '.'))
54517c478bd9Sstevel@tonic-gate 	{
54527c478bd9Sstevel@tonic-gate 		*statp = EX_NOHOST;
54537c478bd9Sstevel@tonic-gate 		return false;
54547c478bd9Sstevel@tonic-gate 	}
54557c478bd9Sstevel@tonic-gate 
54567c478bd9Sstevel@tonic-gate 	/* Do the search */
54577c478bd9Sstevel@tonic-gate 	vptr = ni_propval("/machines", NULL, nbuf, "name", '\n');
54587c478bd9Sstevel@tonic-gate 
54597c478bd9Sstevel@tonic-gate 	if (vptr == NULL)
54607c478bd9Sstevel@tonic-gate 	{
54617c478bd9Sstevel@tonic-gate 		*statp = EX_NOHOST;
54627c478bd9Sstevel@tonic-gate 		return false;
54637c478bd9Sstevel@tonic-gate 	}
54647c478bd9Sstevel@tonic-gate 
54657c478bd9Sstevel@tonic-gate 	/* Only want the first machine name */
54667c478bd9Sstevel@tonic-gate 	if ((ptr = strchr(vptr, '\n')) != NULL)
54677c478bd9Sstevel@tonic-gate 		*ptr = '\0';
54687c478bd9Sstevel@tonic-gate 
54697c478bd9Sstevel@tonic-gate 	if (sm_strlcpy(name, vptr, hbsize) >= hbsize)
54707c478bd9Sstevel@tonic-gate 	{
54717c478bd9Sstevel@tonic-gate 		sm_free(vptr);
54727c478bd9Sstevel@tonic-gate 		*statp = EX_UNAVAILABLE;
54737c478bd9Sstevel@tonic-gate 		return true;
54747c478bd9Sstevel@tonic-gate 	}
54757c478bd9Sstevel@tonic-gate 	sm_free(vptr);
54767c478bd9Sstevel@tonic-gate 	*statp = EX_OK;
54777c478bd9Sstevel@tonic-gate 	return false;
54787c478bd9Sstevel@tonic-gate }
54797c478bd9Sstevel@tonic-gate #endif /* NETINFO */
54807c478bd9Sstevel@tonic-gate /*
54817c478bd9Sstevel@tonic-gate **  TEXT (unindexed text file) Modules
54827c478bd9Sstevel@tonic-gate **
54837c478bd9Sstevel@tonic-gate **	This code donated by Sun Microsystems.
54847c478bd9Sstevel@tonic-gate */
54857c478bd9Sstevel@tonic-gate 
54867c478bd9Sstevel@tonic-gate #define map_sff		map_lockfd	/* overload field */
54877c478bd9Sstevel@tonic-gate 
54887c478bd9Sstevel@tonic-gate 
54897c478bd9Sstevel@tonic-gate /*
54907c478bd9Sstevel@tonic-gate **  TEXT_MAP_OPEN -- open text table
54917c478bd9Sstevel@tonic-gate */
54927c478bd9Sstevel@tonic-gate 
54937c478bd9Sstevel@tonic-gate bool
54947c478bd9Sstevel@tonic-gate text_map_open(map, mode)
54957c478bd9Sstevel@tonic-gate 	MAP *map;
54967c478bd9Sstevel@tonic-gate 	int mode;
54977c478bd9Sstevel@tonic-gate {
54987c478bd9Sstevel@tonic-gate 	long sff;
54997c478bd9Sstevel@tonic-gate 	int i;
55007c478bd9Sstevel@tonic-gate 
55017c478bd9Sstevel@tonic-gate 	if (tTd(38, 2))
55027c478bd9Sstevel@tonic-gate 		sm_dprintf("text_map_open(%s, %s, %d)\n",
55037c478bd9Sstevel@tonic-gate 			map->map_mname, map->map_file, mode);
55047c478bd9Sstevel@tonic-gate 
55057c478bd9Sstevel@tonic-gate 	mode &= O_ACCMODE;
55067c478bd9Sstevel@tonic-gate 	if (mode != O_RDONLY)
55077c478bd9Sstevel@tonic-gate 	{
55087c478bd9Sstevel@tonic-gate 		errno = EPERM;
55097c478bd9Sstevel@tonic-gate 		return false;
55107c478bd9Sstevel@tonic-gate 	}
55117c478bd9Sstevel@tonic-gate 
55127c478bd9Sstevel@tonic-gate 	if (*map->map_file == '\0')
55137c478bd9Sstevel@tonic-gate 	{
55147c478bd9Sstevel@tonic-gate 		syserr("text map \"%s\": file name required",
55157c478bd9Sstevel@tonic-gate 			map->map_mname);
55167c478bd9Sstevel@tonic-gate 		return false;
55177c478bd9Sstevel@tonic-gate 	}
55187c478bd9Sstevel@tonic-gate 
55197c478bd9Sstevel@tonic-gate 	if (map->map_file[0] != '/')
55207c478bd9Sstevel@tonic-gate 	{
55217c478bd9Sstevel@tonic-gate 		syserr("text map \"%s\": file name must be fully qualified",
55227c478bd9Sstevel@tonic-gate 			map->map_mname);
55237c478bd9Sstevel@tonic-gate 		return false;
55247c478bd9Sstevel@tonic-gate 	}
55257c478bd9Sstevel@tonic-gate 
55267c478bd9Sstevel@tonic-gate 	sff = SFF_ROOTOK|SFF_REGONLY;
55277c478bd9Sstevel@tonic-gate 	if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail))
55287c478bd9Sstevel@tonic-gate 		sff |= SFF_NOWLINK;
55297c478bd9Sstevel@tonic-gate 	if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail))
55307c478bd9Sstevel@tonic-gate 		sff |= SFF_SAFEDIRPATH;
55317c478bd9Sstevel@tonic-gate 	if ((i = safefile(map->map_file, RunAsUid, RunAsGid, RunAsUserName,
55327c478bd9Sstevel@tonic-gate 			  sff, S_IRUSR, NULL)) != 0)
55337c478bd9Sstevel@tonic-gate 	{
55347c478bd9Sstevel@tonic-gate 		int save_errno = errno;
55357c478bd9Sstevel@tonic-gate 
55367c478bd9Sstevel@tonic-gate 		/* cannot open this map */
55377c478bd9Sstevel@tonic-gate 		if (tTd(38, 2))
55387c478bd9Sstevel@tonic-gate 			sm_dprintf("\tunsafe map file: %d\n", i);
55397c478bd9Sstevel@tonic-gate 		errno = save_errno;
55407c478bd9Sstevel@tonic-gate 		if (!bitset(MF_OPTIONAL, map->map_mflags))
55417c478bd9Sstevel@tonic-gate 			syserr("text map \"%s\": unsafe map file %s",
55427c478bd9Sstevel@tonic-gate 				map->map_mname, map->map_file);
55437c478bd9Sstevel@tonic-gate 		return false;
55447c478bd9Sstevel@tonic-gate 	}
55457c478bd9Sstevel@tonic-gate 
55467c478bd9Sstevel@tonic-gate 	if (map->map_keycolnm == NULL)
55477c478bd9Sstevel@tonic-gate 		map->map_keycolno = 0;
55487c478bd9Sstevel@tonic-gate 	else
55497c478bd9Sstevel@tonic-gate 	{
55507c478bd9Sstevel@tonic-gate 		if (!(isascii(*map->map_keycolnm) && isdigit(*map->map_keycolnm)))
55517c478bd9Sstevel@tonic-gate 		{
55527c478bd9Sstevel@tonic-gate 			syserr("text map \"%s\", file %s: -k should specify a number, not %s",
55537c478bd9Sstevel@tonic-gate 				map->map_mname, map->map_file,
55547c478bd9Sstevel@tonic-gate 				map->map_keycolnm);
55557c478bd9Sstevel@tonic-gate 			return false;
55567c478bd9Sstevel@tonic-gate 		}
55577c478bd9Sstevel@tonic-gate 		map->map_keycolno = atoi(map->map_keycolnm);
55587c478bd9Sstevel@tonic-gate 	}
55597c478bd9Sstevel@tonic-gate 
55607c478bd9Sstevel@tonic-gate 	if (map->map_valcolnm == NULL)
55617c478bd9Sstevel@tonic-gate 		map->map_valcolno = 0;
55627c478bd9Sstevel@tonic-gate 	else
55637c478bd9Sstevel@tonic-gate 	{
55647c478bd9Sstevel@tonic-gate 		if (!(isascii(*map->map_valcolnm) && isdigit(*map->map_valcolnm)))
55657c478bd9Sstevel@tonic-gate 		{
55667c478bd9Sstevel@tonic-gate 			syserr("text map \"%s\", file %s: -v should specify a number, not %s",
55677c478bd9Sstevel@tonic-gate 					map->map_mname, map->map_file,
55687c478bd9Sstevel@tonic-gate 					map->map_valcolnm);
55697c478bd9Sstevel@tonic-gate 			return false;
55707c478bd9Sstevel@tonic-gate 		}
55717c478bd9Sstevel@tonic-gate 		map->map_valcolno = atoi(map->map_valcolnm);
55727c478bd9Sstevel@tonic-gate 	}
55737c478bd9Sstevel@tonic-gate 
55747c478bd9Sstevel@tonic-gate 	if (tTd(38, 2))
55757c478bd9Sstevel@tonic-gate 	{
55767c478bd9Sstevel@tonic-gate 		sm_dprintf("text_map_open(%s, %s): delimiter = ",
55777c478bd9Sstevel@tonic-gate 			map->map_mname, map->map_file);
55787c478bd9Sstevel@tonic-gate 		if (map->map_coldelim == '\0')
55797c478bd9Sstevel@tonic-gate 			sm_dprintf("(white space)\n");
55807c478bd9Sstevel@tonic-gate 		else
55817c478bd9Sstevel@tonic-gate 			sm_dprintf("%c\n", map->map_coldelim);
55827c478bd9Sstevel@tonic-gate 	}
55837c478bd9Sstevel@tonic-gate 
55847c478bd9Sstevel@tonic-gate 	map->map_sff = sff;
55857c478bd9Sstevel@tonic-gate 	return true;
55867c478bd9Sstevel@tonic-gate }
55877c478bd9Sstevel@tonic-gate 
55887c478bd9Sstevel@tonic-gate 
55897c478bd9Sstevel@tonic-gate /*
55907c478bd9Sstevel@tonic-gate **  TEXT_MAP_LOOKUP -- look up a datum in a TEXT table
55917c478bd9Sstevel@tonic-gate */
55927c478bd9Sstevel@tonic-gate 
55937c478bd9Sstevel@tonic-gate char *
55947c478bd9Sstevel@tonic-gate text_map_lookup(map, name, av, statp)
55957c478bd9Sstevel@tonic-gate 	MAP *map;
55967c478bd9Sstevel@tonic-gate 	char *name;
55977c478bd9Sstevel@tonic-gate 	char **av;
55987c478bd9Sstevel@tonic-gate 	int *statp;
55997c478bd9Sstevel@tonic-gate {
56007c478bd9Sstevel@tonic-gate 	char *vp;
56017c478bd9Sstevel@tonic-gate 	auto int vsize;
56027c478bd9Sstevel@tonic-gate 	int buflen;
56037c478bd9Sstevel@tonic-gate 	SM_FILE_T *f;
56047c478bd9Sstevel@tonic-gate 	char delim;
56057c478bd9Sstevel@tonic-gate 	int key_idx;
56067c478bd9Sstevel@tonic-gate 	bool found_it;
56077c478bd9Sstevel@tonic-gate 	long sff = map->map_sff;
56087c478bd9Sstevel@tonic-gate 	char search_key[MAXNAME + 1];
56097c478bd9Sstevel@tonic-gate 	char linebuf[MAXLINE];
56107c478bd9Sstevel@tonic-gate 	char buf[MAXNAME + 1];
56117c478bd9Sstevel@tonic-gate 
56127c478bd9Sstevel@tonic-gate 	found_it = false;
56137c478bd9Sstevel@tonic-gate 	if (tTd(38, 20))
56147c478bd9Sstevel@tonic-gate 		sm_dprintf("text_map_lookup(%s, %s)\n", map->map_mname,  name);
56157c478bd9Sstevel@tonic-gate 
56167c478bd9Sstevel@tonic-gate 	buflen = strlen(name);
56177c478bd9Sstevel@tonic-gate 	if (buflen > sizeof search_key - 1)
56187c478bd9Sstevel@tonic-gate 		buflen = sizeof search_key - 1;	/* XXX just cut if off? */
56197c478bd9Sstevel@tonic-gate 	memmove(search_key, name, buflen);
56207c478bd9Sstevel@tonic-gate 	search_key[buflen] = '\0';
56217c478bd9Sstevel@tonic-gate 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
56227c478bd9Sstevel@tonic-gate 		makelower(search_key);
56237c478bd9Sstevel@tonic-gate 
56247c478bd9Sstevel@tonic-gate 	f = safefopen(map->map_file, O_RDONLY, FileMode, sff);
56257c478bd9Sstevel@tonic-gate 	if (f == NULL)
56267c478bd9Sstevel@tonic-gate 	{
56277c478bd9Sstevel@tonic-gate 		map->map_mflags &= ~(MF_VALID|MF_OPEN);
56287c478bd9Sstevel@tonic-gate 		*statp = EX_UNAVAILABLE;
56297c478bd9Sstevel@tonic-gate 		return NULL;
56307c478bd9Sstevel@tonic-gate 	}
56317c478bd9Sstevel@tonic-gate 	key_idx = map->map_keycolno;
56327c478bd9Sstevel@tonic-gate 	delim = map->map_coldelim;
56337c478bd9Sstevel@tonic-gate 	while (sm_io_fgets(f, SM_TIME_DEFAULT,
56347c478bd9Sstevel@tonic-gate 			   linebuf, sizeof linebuf) != NULL)
56357c478bd9Sstevel@tonic-gate 	{
56367c478bd9Sstevel@tonic-gate 		char *p;
56377c478bd9Sstevel@tonic-gate 
56387c478bd9Sstevel@tonic-gate 		/* skip comment line */
56397c478bd9Sstevel@tonic-gate 		if (linebuf[0] == '#')
56407c478bd9Sstevel@tonic-gate 			continue;
56417c478bd9Sstevel@tonic-gate 		p = strchr(linebuf, '\n');
56427c478bd9Sstevel@tonic-gate 		if (p != NULL)
56437c478bd9Sstevel@tonic-gate 			*p = '\0';
56447c478bd9Sstevel@tonic-gate 		p = get_column(linebuf, key_idx, delim, buf, sizeof buf);
56457c478bd9Sstevel@tonic-gate 		if (p != NULL && sm_strcasecmp(search_key, p) == 0)
56467c478bd9Sstevel@tonic-gate 		{
56477c478bd9Sstevel@tonic-gate 			found_it = true;
56487c478bd9Sstevel@tonic-gate 			break;
56497c478bd9Sstevel@tonic-gate 		}
56507c478bd9Sstevel@tonic-gate 	}
56517c478bd9Sstevel@tonic-gate 	(void) sm_io_close(f, SM_TIME_DEFAULT);
56527c478bd9Sstevel@tonic-gate 	if (!found_it)
56537c478bd9Sstevel@tonic-gate 	{
56547c478bd9Sstevel@tonic-gate 		*statp = EX_NOTFOUND;
56557c478bd9Sstevel@tonic-gate 		return NULL;
56567c478bd9Sstevel@tonic-gate 	}
56577c478bd9Sstevel@tonic-gate 	vp = get_column(linebuf, map->map_valcolno, delim, buf, sizeof buf);
56587c478bd9Sstevel@tonic-gate 	if (vp == NULL)
56597c478bd9Sstevel@tonic-gate 	{
56607c478bd9Sstevel@tonic-gate 		*statp = EX_NOTFOUND;
56617c478bd9Sstevel@tonic-gate 		return NULL;
56627c478bd9Sstevel@tonic-gate 	}
56637c478bd9Sstevel@tonic-gate 	vsize = strlen(vp);
56647c478bd9Sstevel@tonic-gate 	*statp = EX_OK;
56657c478bd9Sstevel@tonic-gate 	if (bitset(MF_MATCHONLY, map->map_mflags))
56667c478bd9Sstevel@tonic-gate 		return map_rewrite(map, name, strlen(name), NULL);
56677c478bd9Sstevel@tonic-gate 	else
56687c478bd9Sstevel@tonic-gate 		return map_rewrite(map, vp, vsize, av);
56697c478bd9Sstevel@tonic-gate }
56707c478bd9Sstevel@tonic-gate 
56717c478bd9Sstevel@tonic-gate /*
56727c478bd9Sstevel@tonic-gate **  TEXT_GETCANONNAME -- look up canonical name in hosts file
56737c478bd9Sstevel@tonic-gate */
56747c478bd9Sstevel@tonic-gate 
56757c478bd9Sstevel@tonic-gate static bool
56767c478bd9Sstevel@tonic-gate text_getcanonname(name, hbsize, statp)
56777c478bd9Sstevel@tonic-gate 	char *name;
56787c478bd9Sstevel@tonic-gate 	int hbsize;
56797c478bd9Sstevel@tonic-gate 	int *statp;
56807c478bd9Sstevel@tonic-gate {
56817c478bd9Sstevel@tonic-gate 	bool found;
56827c478bd9Sstevel@tonic-gate 	char *dot;
56837c478bd9Sstevel@tonic-gate 	SM_FILE_T *f;
56847c478bd9Sstevel@tonic-gate 	char linebuf[MAXLINE];
56857c478bd9Sstevel@tonic-gate 	char cbuf[MAXNAME + 1];
56867c478bd9Sstevel@tonic-gate 	char nbuf[MAXNAME + 1];
56877c478bd9Sstevel@tonic-gate 
56887c478bd9Sstevel@tonic-gate 	if (tTd(38, 20))
56897c478bd9Sstevel@tonic-gate 		sm_dprintf("text_getcanonname(%s)\n", name);
56907c478bd9Sstevel@tonic-gate 
56917c478bd9Sstevel@tonic-gate 	if (sm_strlcpy(nbuf, name, sizeof nbuf) >= sizeof nbuf)
56927c478bd9Sstevel@tonic-gate 	{
56937c478bd9Sstevel@tonic-gate 		*statp = EX_UNAVAILABLE;
56947c478bd9Sstevel@tonic-gate 		return false;
56957c478bd9Sstevel@tonic-gate 	}
56967c478bd9Sstevel@tonic-gate 	dot = shorten_hostname(nbuf);
56977c478bd9Sstevel@tonic-gate 
56987c478bd9Sstevel@tonic-gate 	f = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, HostsFile, SM_IO_RDONLY,
56997c478bd9Sstevel@tonic-gate 		       NULL);
57007c478bd9Sstevel@tonic-gate 	if (f == NULL)
57017c478bd9Sstevel@tonic-gate 	{
57027c478bd9Sstevel@tonic-gate 		*statp = EX_UNAVAILABLE;
57037c478bd9Sstevel@tonic-gate 		return false;
57047c478bd9Sstevel@tonic-gate 	}
57057c478bd9Sstevel@tonic-gate 	found = false;
57067c478bd9Sstevel@tonic-gate 	while (!found &&
57077c478bd9Sstevel@tonic-gate 		sm_io_fgets(f, SM_TIME_DEFAULT,
57087c478bd9Sstevel@tonic-gate 			    linebuf, sizeof linebuf) != NULL)
57097c478bd9Sstevel@tonic-gate 	{
57107c478bd9Sstevel@tonic-gate 		char *p = strpbrk(linebuf, "#\n");
57117c478bd9Sstevel@tonic-gate 
57127c478bd9Sstevel@tonic-gate 		if (p != NULL)
57137c478bd9Sstevel@tonic-gate 			*p = '\0';
57147c478bd9Sstevel@tonic-gate 		if (linebuf[0] != '\0')
57157c478bd9Sstevel@tonic-gate 			found = extract_canonname(nbuf, dot, linebuf,
57167c478bd9Sstevel@tonic-gate 						  cbuf, sizeof cbuf);
57177c478bd9Sstevel@tonic-gate 	}
57187c478bd9Sstevel@tonic-gate 	(void) sm_io_close(f, SM_TIME_DEFAULT);
57197c478bd9Sstevel@tonic-gate 	if (!found)
57207c478bd9Sstevel@tonic-gate 	{
57217c478bd9Sstevel@tonic-gate 		*statp = EX_NOHOST;
57227c478bd9Sstevel@tonic-gate 		return false;
57237c478bd9Sstevel@tonic-gate 	}
57247c478bd9Sstevel@tonic-gate 
57257c478bd9Sstevel@tonic-gate 	if (sm_strlcpy(name, cbuf, hbsize) >= hbsize)
57267c478bd9Sstevel@tonic-gate 	{
57277c478bd9Sstevel@tonic-gate 		*statp = EX_UNAVAILABLE;
57287c478bd9Sstevel@tonic-gate 		return false;
57297c478bd9Sstevel@tonic-gate 	}
57307c478bd9Sstevel@tonic-gate 	*statp = EX_OK;
57317c478bd9Sstevel@tonic-gate 	return true;
57327c478bd9Sstevel@tonic-gate }
57337c478bd9Sstevel@tonic-gate /*
57347c478bd9Sstevel@tonic-gate **  STAB (Symbol Table) Modules
57357c478bd9Sstevel@tonic-gate */
57367c478bd9Sstevel@tonic-gate 
57377c478bd9Sstevel@tonic-gate 
57387c478bd9Sstevel@tonic-gate /*
57397c478bd9Sstevel@tonic-gate **  STAB_MAP_LOOKUP -- look up alias in symbol table
57407c478bd9Sstevel@tonic-gate */
57417c478bd9Sstevel@tonic-gate 
57427c478bd9Sstevel@tonic-gate /* ARGSUSED2 */
57437c478bd9Sstevel@tonic-gate char *
57447c478bd9Sstevel@tonic-gate stab_map_lookup(map, name, av, pstat)
57457c478bd9Sstevel@tonic-gate 	register MAP *map;
57467c478bd9Sstevel@tonic-gate 	char *name;
57477c478bd9Sstevel@tonic-gate 	char **av;
57487c478bd9Sstevel@tonic-gate 	int *pstat;
57497c478bd9Sstevel@tonic-gate {
57507c478bd9Sstevel@tonic-gate 	register STAB *s;
57517c478bd9Sstevel@tonic-gate 
57527c478bd9Sstevel@tonic-gate 	if (tTd(38, 20))
57537c478bd9Sstevel@tonic-gate 		sm_dprintf("stab_lookup(%s, %s)\n",
57547c478bd9Sstevel@tonic-gate 			map->map_mname, name);
57557c478bd9Sstevel@tonic-gate 
57567c478bd9Sstevel@tonic-gate 	s = stab(name, ST_ALIAS, ST_FIND);
57577c478bd9Sstevel@tonic-gate 	if (s == NULL)
57587c478bd9Sstevel@tonic-gate 		return NULL;
57597c478bd9Sstevel@tonic-gate 	if (bitset(MF_MATCHONLY, map->map_mflags))
57607c478bd9Sstevel@tonic-gate 		return map_rewrite(map, name, strlen(name), NULL);
57617c478bd9Sstevel@tonic-gate 	else
57627c478bd9Sstevel@tonic-gate 		return map_rewrite(map, s->s_alias, strlen(s->s_alias), av);
57637c478bd9Sstevel@tonic-gate }
57647c478bd9Sstevel@tonic-gate 
57657c478bd9Sstevel@tonic-gate /*
57667c478bd9Sstevel@tonic-gate **  STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild)
57677c478bd9Sstevel@tonic-gate */
57687c478bd9Sstevel@tonic-gate 
57697c478bd9Sstevel@tonic-gate void
57707c478bd9Sstevel@tonic-gate stab_map_store(map, lhs, rhs)
57717c478bd9Sstevel@tonic-gate 	register MAP *map;
57727c478bd9Sstevel@tonic-gate 	char *lhs;
57737c478bd9Sstevel@tonic-gate 	char *rhs;
57747c478bd9Sstevel@tonic-gate {
57757c478bd9Sstevel@tonic-gate 	register STAB *s;
57767c478bd9Sstevel@tonic-gate 
57777c478bd9Sstevel@tonic-gate 	s = stab(lhs, ST_ALIAS, ST_ENTER);
57787c478bd9Sstevel@tonic-gate 	s->s_alias = newstr(rhs);
57797c478bd9Sstevel@tonic-gate }
57807c478bd9Sstevel@tonic-gate 
57817c478bd9Sstevel@tonic-gate 
57827c478bd9Sstevel@tonic-gate /*
57837c478bd9Sstevel@tonic-gate **  STAB_MAP_OPEN -- initialize (reads data file)
57847c478bd9Sstevel@tonic-gate **
57857c478bd9Sstevel@tonic-gate **	This is a wierd case -- it is only intended as a fallback for
57867c478bd9Sstevel@tonic-gate **	aliases.  For this reason, opens for write (only during a
57877c478bd9Sstevel@tonic-gate **	"newaliases") always fails, and opens for read open the
57887c478bd9Sstevel@tonic-gate **	actual underlying text file instead of the database.
57897c478bd9Sstevel@tonic-gate */
57907c478bd9Sstevel@tonic-gate 
57917c478bd9Sstevel@tonic-gate bool
57927c478bd9Sstevel@tonic-gate stab_map_open(map, mode)
57937c478bd9Sstevel@tonic-gate 	register MAP *map;
57947c478bd9Sstevel@tonic-gate 	int mode;
57957c478bd9Sstevel@tonic-gate {
57967c478bd9Sstevel@tonic-gate 	SM_FILE_T *af;
57977c478bd9Sstevel@tonic-gate 	long sff;
57987c478bd9Sstevel@tonic-gate 	struct stat st;
57997c478bd9Sstevel@tonic-gate 
58007c478bd9Sstevel@tonic-gate 	if (tTd(38, 2))
58017c478bd9Sstevel@tonic-gate 		sm_dprintf("stab_map_open(%s, %s, %d)\n",
58027c478bd9Sstevel@tonic-gate 			map->map_mname, map->map_file, mode);
58037c478bd9Sstevel@tonic-gate 
58047c478bd9Sstevel@tonic-gate 	mode &= O_ACCMODE;
58057c478bd9Sstevel@tonic-gate 	if (mode != O_RDONLY)
58067c478bd9Sstevel@tonic-gate 	{
58077c478bd9Sstevel@tonic-gate 		errno = EPERM;
58087c478bd9Sstevel@tonic-gate 		return false;
58097c478bd9Sstevel@tonic-gate 	}
58107c478bd9Sstevel@tonic-gate 
58117c478bd9Sstevel@tonic-gate 	sff = SFF_ROOTOK|SFF_REGONLY;
58127c478bd9Sstevel@tonic-gate 	if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail))
58137c478bd9Sstevel@tonic-gate 		sff |= SFF_NOWLINK;
58147c478bd9Sstevel@tonic-gate 	if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail))
58157c478bd9Sstevel@tonic-gate 		sff |= SFF_SAFEDIRPATH;
58167c478bd9Sstevel@tonic-gate 	af = safefopen(map->map_file, O_RDONLY, 0444, sff);
58177c478bd9Sstevel@tonic-gate 	if (af == NULL)
58187c478bd9Sstevel@tonic-gate 		return false;
58197c478bd9Sstevel@tonic-gate 	readaliases(map, af, false, false);
58207c478bd9Sstevel@tonic-gate 
58217c478bd9Sstevel@tonic-gate 	if (fstat(sm_io_getinfo(af, SM_IO_WHAT_FD, NULL), &st) >= 0)
58227c478bd9Sstevel@tonic-gate 		map->map_mtime = st.st_mtime;
58237c478bd9Sstevel@tonic-gate 	(void) sm_io_close(af, SM_TIME_DEFAULT);
58247c478bd9Sstevel@tonic-gate 
58257c478bd9Sstevel@tonic-gate 	return true;
58267c478bd9Sstevel@tonic-gate }
58277c478bd9Sstevel@tonic-gate /*
58287c478bd9Sstevel@tonic-gate **  Implicit Modules
58297c478bd9Sstevel@tonic-gate **
58307c478bd9Sstevel@tonic-gate **	Tries several types.  For back compatibility of aliases.
58317c478bd9Sstevel@tonic-gate */
58327c478bd9Sstevel@tonic-gate 
58337c478bd9Sstevel@tonic-gate 
58347c478bd9Sstevel@tonic-gate /*
58357c478bd9Sstevel@tonic-gate **  IMPL_MAP_LOOKUP -- lookup in best open database
58367c478bd9Sstevel@tonic-gate */
58377c478bd9Sstevel@tonic-gate 
58387c478bd9Sstevel@tonic-gate char *
58397c478bd9Sstevel@tonic-gate impl_map_lookup(map, name, av, pstat)
58407c478bd9Sstevel@tonic-gate 	MAP *map;
58417c478bd9Sstevel@tonic-gate 	char *name;
58427c478bd9Sstevel@tonic-gate 	char **av;
58437c478bd9Sstevel@tonic-gate 	int *pstat;
58447c478bd9Sstevel@tonic-gate {
58457c478bd9Sstevel@tonic-gate 	if (tTd(38, 20))
58467c478bd9Sstevel@tonic-gate 		sm_dprintf("impl_map_lookup(%s, %s)\n",
58477c478bd9Sstevel@tonic-gate 			map->map_mname, name);
58487c478bd9Sstevel@tonic-gate 
58497c478bd9Sstevel@tonic-gate #if NEWDB
58507c478bd9Sstevel@tonic-gate 	if (bitset(MF_IMPL_HASH, map->map_mflags))
58517c478bd9Sstevel@tonic-gate 		return db_map_lookup(map, name, av, pstat);
58527c478bd9Sstevel@tonic-gate #endif /* NEWDB */
58537c478bd9Sstevel@tonic-gate #if NDBM
58547c478bd9Sstevel@tonic-gate 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
58557c478bd9Sstevel@tonic-gate 		return ndbm_map_lookup(map, name, av, pstat);
58567c478bd9Sstevel@tonic-gate #endif /* NDBM */
58577c478bd9Sstevel@tonic-gate 	return stab_map_lookup(map, name, av, pstat);
58587c478bd9Sstevel@tonic-gate }
58597c478bd9Sstevel@tonic-gate 
58607c478bd9Sstevel@tonic-gate /*
58617c478bd9Sstevel@tonic-gate **  IMPL_MAP_STORE -- store in open databases
58627c478bd9Sstevel@tonic-gate */
58637c478bd9Sstevel@tonic-gate 
58647c478bd9Sstevel@tonic-gate void
58657c478bd9Sstevel@tonic-gate impl_map_store(map, lhs, rhs)
58667c478bd9Sstevel@tonic-gate 	MAP *map;
58677c478bd9Sstevel@tonic-gate 	char *lhs;
58687c478bd9Sstevel@tonic-gate 	char *rhs;
58697c478bd9Sstevel@tonic-gate {
58707c478bd9Sstevel@tonic-gate 	if (tTd(38, 12))
58717c478bd9Sstevel@tonic-gate 		sm_dprintf("impl_map_store(%s, %s, %s)\n",
58727c478bd9Sstevel@tonic-gate 			map->map_mname, lhs, rhs);
58737c478bd9Sstevel@tonic-gate #if NEWDB
58747c478bd9Sstevel@tonic-gate 	if (bitset(MF_IMPL_HASH, map->map_mflags))
58757c478bd9Sstevel@tonic-gate 		db_map_store(map, lhs, rhs);
58767c478bd9Sstevel@tonic-gate #endif /* NEWDB */
58777c478bd9Sstevel@tonic-gate #if NDBM
58787c478bd9Sstevel@tonic-gate 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
58797c478bd9Sstevel@tonic-gate 		ndbm_map_store(map, lhs, rhs);
58807c478bd9Sstevel@tonic-gate #endif /* NDBM */
58817c478bd9Sstevel@tonic-gate 	stab_map_store(map, lhs, rhs);
58827c478bd9Sstevel@tonic-gate }
58837c478bd9Sstevel@tonic-gate 
58847c478bd9Sstevel@tonic-gate /*
58857c478bd9Sstevel@tonic-gate **  IMPL_MAP_OPEN -- implicit database open
58867c478bd9Sstevel@tonic-gate */
58877c478bd9Sstevel@tonic-gate 
58887c478bd9Sstevel@tonic-gate bool
58897c478bd9Sstevel@tonic-gate impl_map_open(map, mode)
58907c478bd9Sstevel@tonic-gate 	MAP *map;
58917c478bd9Sstevel@tonic-gate 	int mode;
58927c478bd9Sstevel@tonic-gate {
58937c478bd9Sstevel@tonic-gate 	if (tTd(38, 2))
58947c478bd9Sstevel@tonic-gate 		sm_dprintf("impl_map_open(%s, %s, %d)\n",
58957c478bd9Sstevel@tonic-gate 			map->map_mname, map->map_file, mode);
58967c478bd9Sstevel@tonic-gate 
58977c478bd9Sstevel@tonic-gate 	mode &= O_ACCMODE;
58987c478bd9Sstevel@tonic-gate #if NEWDB
58997c478bd9Sstevel@tonic-gate 	map->map_mflags |= MF_IMPL_HASH;
59007c478bd9Sstevel@tonic-gate 	if (hash_map_open(map, mode))
59017c478bd9Sstevel@tonic-gate 	{
59027c478bd9Sstevel@tonic-gate # ifdef NDBM_YP_COMPAT
59037c478bd9Sstevel@tonic-gate 		if (mode == O_RDONLY || strstr(map->map_file, "/yp/") == NULL)
59047c478bd9Sstevel@tonic-gate # endif /* NDBM_YP_COMPAT */
59057c478bd9Sstevel@tonic-gate 			return true;
59067c478bd9Sstevel@tonic-gate 	}
59077c478bd9Sstevel@tonic-gate 	else
59087c478bd9Sstevel@tonic-gate 		map->map_mflags &= ~MF_IMPL_HASH;
59097c478bd9Sstevel@tonic-gate #endif /* NEWDB */
59107c478bd9Sstevel@tonic-gate #if NDBM
59117c478bd9Sstevel@tonic-gate 	map->map_mflags |= MF_IMPL_NDBM;
59127c478bd9Sstevel@tonic-gate 	if (ndbm_map_open(map, mode))
59137c478bd9Sstevel@tonic-gate 	{
59147c478bd9Sstevel@tonic-gate 		return true;
59157c478bd9Sstevel@tonic-gate 	}
59167c478bd9Sstevel@tonic-gate 	else
59177c478bd9Sstevel@tonic-gate 		map->map_mflags &= ~MF_IMPL_NDBM;
59187c478bd9Sstevel@tonic-gate #endif /* NDBM */
59197c478bd9Sstevel@tonic-gate 
59207c478bd9Sstevel@tonic-gate #if defined(NEWDB) || defined(NDBM)
59217c478bd9Sstevel@tonic-gate 	if (Verbose)
59227c478bd9Sstevel@tonic-gate 		message("WARNING: cannot open alias database %s%s",
59237c478bd9Sstevel@tonic-gate 			map->map_file,
59247c478bd9Sstevel@tonic-gate 			mode == O_RDONLY ? "; reading text version" : "");
59257c478bd9Sstevel@tonic-gate #else /* defined(NEWDB) || defined(NDBM) */
59267c478bd9Sstevel@tonic-gate 	if (mode != O_RDONLY)
59277c478bd9Sstevel@tonic-gate 		usrerr("Cannot rebuild aliases: no database format defined");
59287c478bd9Sstevel@tonic-gate #endif /* defined(NEWDB) || defined(NDBM) */
59297c478bd9Sstevel@tonic-gate 
59307c478bd9Sstevel@tonic-gate 	if (mode == O_RDONLY)
59317c478bd9Sstevel@tonic-gate 		return stab_map_open(map, mode);
59327c478bd9Sstevel@tonic-gate 	else
59337c478bd9Sstevel@tonic-gate 		return false;
59347c478bd9Sstevel@tonic-gate }
59357c478bd9Sstevel@tonic-gate 
59367c478bd9Sstevel@tonic-gate 
59377c478bd9Sstevel@tonic-gate /*
59387c478bd9Sstevel@tonic-gate **  IMPL_MAP_CLOSE -- close any open database(s)
59397c478bd9Sstevel@tonic-gate */
59407c478bd9Sstevel@tonic-gate 
59417c478bd9Sstevel@tonic-gate void
59427c478bd9Sstevel@tonic-gate impl_map_close(map)
59437c478bd9Sstevel@tonic-gate 	MAP *map;
59447c478bd9Sstevel@tonic-gate {
59457c478bd9Sstevel@tonic-gate 	if (tTd(38, 9))
59467c478bd9Sstevel@tonic-gate 		sm_dprintf("impl_map_close(%s, %s, %lx)\n",
59477c478bd9Sstevel@tonic-gate 			map->map_mname, map->map_file, map->map_mflags);
59487c478bd9Sstevel@tonic-gate #if NEWDB
59497c478bd9Sstevel@tonic-gate 	if (bitset(MF_IMPL_HASH, map->map_mflags))
59507c478bd9Sstevel@tonic-gate 	{
59517c478bd9Sstevel@tonic-gate 		db_map_close(map);
59527c478bd9Sstevel@tonic-gate 		map->map_mflags &= ~MF_IMPL_HASH;
59537c478bd9Sstevel@tonic-gate 	}
59547c478bd9Sstevel@tonic-gate #endif /* NEWDB */
59557c478bd9Sstevel@tonic-gate 
59567c478bd9Sstevel@tonic-gate #if NDBM
59577c478bd9Sstevel@tonic-gate 	if (bitset(MF_IMPL_NDBM, map->map_mflags))
59587c478bd9Sstevel@tonic-gate 	{
59597c478bd9Sstevel@tonic-gate 		ndbm_map_close(map);
59607c478bd9Sstevel@tonic-gate 		map->map_mflags &= ~MF_IMPL_NDBM;
59617c478bd9Sstevel@tonic-gate 	}
59627c478bd9Sstevel@tonic-gate #endif /* NDBM */
59637c478bd9Sstevel@tonic-gate }
59647c478bd9Sstevel@tonic-gate /*
59657c478bd9Sstevel@tonic-gate **  User map class.
59667c478bd9Sstevel@tonic-gate **
59677c478bd9Sstevel@tonic-gate **	Provides access to the system password file.
59687c478bd9Sstevel@tonic-gate */
59697c478bd9Sstevel@tonic-gate 
59707c478bd9Sstevel@tonic-gate /*
59717c478bd9Sstevel@tonic-gate **  USER_MAP_OPEN -- open user map
59727c478bd9Sstevel@tonic-gate **
59737c478bd9Sstevel@tonic-gate **	Really just binds field names to field numbers.
59747c478bd9Sstevel@tonic-gate */
59757c478bd9Sstevel@tonic-gate 
59767c478bd9Sstevel@tonic-gate bool
59777c478bd9Sstevel@tonic-gate user_map_open(map, mode)
59787c478bd9Sstevel@tonic-gate 	MAP *map;
59797c478bd9Sstevel@tonic-gate 	int mode;
59807c478bd9Sstevel@tonic-gate {
59817c478bd9Sstevel@tonic-gate 	if (tTd(38, 2))
59827c478bd9Sstevel@tonic-gate 		sm_dprintf("user_map_open(%s, %d)\n",
59837c478bd9Sstevel@tonic-gate 			map->map_mname, mode);
59847c478bd9Sstevel@tonic-gate 
59857c478bd9Sstevel@tonic-gate 	mode &= O_ACCMODE;
59867c478bd9Sstevel@tonic-gate 	if (mode != O_RDONLY)
59877c478bd9Sstevel@tonic-gate 	{
59887c478bd9Sstevel@tonic-gate 		/* issue a pseudo-error message */
59897c478bd9Sstevel@tonic-gate 		errno = SM_EMAPCANTWRITE;
59907c478bd9Sstevel@tonic-gate 		return false;
59917c478bd9Sstevel@tonic-gate 	}
59927c478bd9Sstevel@tonic-gate 	if (map->map_valcolnm == NULL)
59937c478bd9Sstevel@tonic-gate 		/* EMPTY */
59947c478bd9Sstevel@tonic-gate 		/* nothing */ ;
59957c478bd9Sstevel@tonic-gate 	else if (sm_strcasecmp(map->map_valcolnm, "name") == 0)
59967c478bd9Sstevel@tonic-gate 		map->map_valcolno = 1;
59977c478bd9Sstevel@tonic-gate 	else if (sm_strcasecmp(map->map_valcolnm, "passwd") == 0)
59987c478bd9Sstevel@tonic-gate 		map->map_valcolno = 2;
59997c478bd9Sstevel@tonic-gate 	else if (sm_strcasecmp(map->map_valcolnm, "uid") == 0)
60007c478bd9Sstevel@tonic-gate 		map->map_valcolno = 3;
60017c478bd9Sstevel@tonic-gate 	else if (sm_strcasecmp(map->map_valcolnm, "gid") == 0)
60027c478bd9Sstevel@tonic-gate 		map->map_valcolno = 4;
60037c478bd9Sstevel@tonic-gate 	else if (sm_strcasecmp(map->map_valcolnm, "gecos") == 0)
60047c478bd9Sstevel@tonic-gate 		map->map_valcolno = 5;
60057c478bd9Sstevel@tonic-gate 	else if (sm_strcasecmp(map->map_valcolnm, "dir") == 0)
60067c478bd9Sstevel@tonic-gate 		map->map_valcolno = 6;
60077c478bd9Sstevel@tonic-gate 	else if (sm_strcasecmp(map->map_valcolnm, "shell") == 0)
60087c478bd9Sstevel@tonic-gate 		map->map_valcolno = 7;
60097c478bd9Sstevel@tonic-gate 	else
60107c478bd9Sstevel@tonic-gate 	{
60117c478bd9Sstevel@tonic-gate 		syserr("User map %s: unknown column name %s",
60127c478bd9Sstevel@tonic-gate 			map->map_mname, map->map_valcolnm);
60137c478bd9Sstevel@tonic-gate 		return false;
60147c478bd9Sstevel@tonic-gate 	}
60157c478bd9Sstevel@tonic-gate 	return true;
60167c478bd9Sstevel@tonic-gate }
60177c478bd9Sstevel@tonic-gate 
60187c478bd9Sstevel@tonic-gate 
60197c478bd9Sstevel@tonic-gate /*
60207c478bd9Sstevel@tonic-gate **  USER_MAP_LOOKUP -- look up a user in the passwd file.
60217c478bd9Sstevel@tonic-gate */
60227c478bd9Sstevel@tonic-gate 
60237c478bd9Sstevel@tonic-gate /* ARGSUSED3 */
60247c478bd9Sstevel@tonic-gate char *
60257c478bd9Sstevel@tonic-gate user_map_lookup(map, key, av, statp)
60267c478bd9Sstevel@tonic-gate 	MAP *map;
60277c478bd9Sstevel@tonic-gate 	char *key;
60287c478bd9Sstevel@tonic-gate 	char **av;
60297c478bd9Sstevel@tonic-gate 	int *statp;
60307c478bd9Sstevel@tonic-gate {
60317c478bd9Sstevel@tonic-gate 	auto bool fuzzy;
60327c478bd9Sstevel@tonic-gate 	SM_MBDB_T user;
60337c478bd9Sstevel@tonic-gate 
60347c478bd9Sstevel@tonic-gate 	if (tTd(38, 20))
60357c478bd9Sstevel@tonic-gate 		sm_dprintf("user_map_lookup(%s, %s)\n",
60367c478bd9Sstevel@tonic-gate 			map->map_mname, key);
60377c478bd9Sstevel@tonic-gate 
60387c478bd9Sstevel@tonic-gate 	*statp = finduser(key, &fuzzy, &user);
60397c478bd9Sstevel@tonic-gate 	if (*statp != EX_OK)
60407c478bd9Sstevel@tonic-gate 		return NULL;
60417c478bd9Sstevel@tonic-gate 	if (bitset(MF_MATCHONLY, map->map_mflags))
60427c478bd9Sstevel@tonic-gate 		return map_rewrite(map, key, strlen(key), NULL);
60437c478bd9Sstevel@tonic-gate 	else
60447c478bd9Sstevel@tonic-gate 	{
60457c478bd9Sstevel@tonic-gate 		char *rwval = NULL;
60467c478bd9Sstevel@tonic-gate 		char buf[30];
60477c478bd9Sstevel@tonic-gate 
60487c478bd9Sstevel@tonic-gate 		switch (map->map_valcolno)
60497c478bd9Sstevel@tonic-gate 		{
60507c478bd9Sstevel@tonic-gate 		  case 0:
60517c478bd9Sstevel@tonic-gate 		  case 1:
60527c478bd9Sstevel@tonic-gate 			rwval = user.mbdb_name;
60537c478bd9Sstevel@tonic-gate 			break;
60547c478bd9Sstevel@tonic-gate 
60557c478bd9Sstevel@tonic-gate 		  case 2:
60567c478bd9Sstevel@tonic-gate 			rwval = "x";	/* passwd no longer supported */
60577c478bd9Sstevel@tonic-gate 			break;
60587c478bd9Sstevel@tonic-gate 
60597c478bd9Sstevel@tonic-gate 		  case 3:
60607c478bd9Sstevel@tonic-gate 			(void) sm_snprintf(buf, sizeof buf, "%d",
60617c478bd9Sstevel@tonic-gate 					   (int) user.mbdb_uid);
60627c478bd9Sstevel@tonic-gate 			rwval = buf;
60637c478bd9Sstevel@tonic-gate 			break;
60647c478bd9Sstevel@tonic-gate 
60657c478bd9Sstevel@tonic-gate 		  case 4:
60667c478bd9Sstevel@tonic-gate 			(void) sm_snprintf(buf, sizeof buf, "%d",
60677c478bd9Sstevel@tonic-gate 					   (int) user.mbdb_gid);
60687c478bd9Sstevel@tonic-gate 			rwval = buf;
60697c478bd9Sstevel@tonic-gate 			break;
60707c478bd9Sstevel@tonic-gate 
60717c478bd9Sstevel@tonic-gate 		  case 5:
60727c478bd9Sstevel@tonic-gate 			rwval = user.mbdb_fullname;
60737c478bd9Sstevel@tonic-gate 			break;
60747c478bd9Sstevel@tonic-gate 
60757c478bd9Sstevel@tonic-gate 		  case 6:
60767c478bd9Sstevel@tonic-gate 			rwval = user.mbdb_homedir;
60777c478bd9Sstevel@tonic-gate 			break;
60787c478bd9Sstevel@tonic-gate 
60797c478bd9Sstevel@tonic-gate 		  case 7:
60807c478bd9Sstevel@tonic-gate 			rwval = user.mbdb_shell;
60817c478bd9Sstevel@tonic-gate 			break;
6082*3ee0e492Sjbeck 		  default:
6083*3ee0e492Sjbeck 			syserr("user_map %s: bogus field %d",
6084*3ee0e492Sjbeck 				map->map_mname, map->map_valcolno);
6085*3ee0e492Sjbeck 			return NULL;
60867c478bd9Sstevel@tonic-gate 		}
60877c478bd9Sstevel@tonic-gate 		return map_rewrite(map, rwval, strlen(rwval), av);
60887c478bd9Sstevel@tonic-gate 	}
60897c478bd9Sstevel@tonic-gate }
60907c478bd9Sstevel@tonic-gate /*
60917c478bd9Sstevel@tonic-gate **  Program map type.
60927c478bd9Sstevel@tonic-gate **
60937c478bd9Sstevel@tonic-gate **	This provides access to arbitrary programs.  It should be used
60947c478bd9Sstevel@tonic-gate **	only very sparingly, since there is no way to bound the cost
60957c478bd9Sstevel@tonic-gate **	of invoking an arbitrary program.
60967c478bd9Sstevel@tonic-gate */
60977c478bd9Sstevel@tonic-gate 
60987c478bd9Sstevel@tonic-gate char *
60997c478bd9Sstevel@tonic-gate prog_map_lookup(map, name, av, statp)
61007c478bd9Sstevel@tonic-gate 	MAP *map;
61017c478bd9Sstevel@tonic-gate 	char *name;
61027c478bd9Sstevel@tonic-gate 	char **av;
61037c478bd9Sstevel@tonic-gate 	int *statp;
61047c478bd9Sstevel@tonic-gate {
61057c478bd9Sstevel@tonic-gate 	int i;
61067c478bd9Sstevel@tonic-gate 	int save_errno;
61077c478bd9Sstevel@tonic-gate 	int fd;
61087c478bd9Sstevel@tonic-gate 	int status;
61097c478bd9Sstevel@tonic-gate 	auto pid_t pid;
61107c478bd9Sstevel@tonic-gate 	register char *p;
61117c478bd9Sstevel@tonic-gate 	char *rval;
61127c478bd9Sstevel@tonic-gate 	char *argv[MAXPV + 1];
61137c478bd9Sstevel@tonic-gate 	char buf[MAXLINE];
61147c478bd9Sstevel@tonic-gate 
61157c478bd9Sstevel@tonic-gate 	if (tTd(38, 20))
61167c478bd9Sstevel@tonic-gate 		sm_dprintf("prog_map_lookup(%s, %s) %s\n",
61177c478bd9Sstevel@tonic-gate 			map->map_mname, name, map->map_file);
61187c478bd9Sstevel@tonic-gate 
61197c478bd9Sstevel@tonic-gate 	i = 0;
61207c478bd9Sstevel@tonic-gate 	argv[i++] = map->map_file;
61217c478bd9Sstevel@tonic-gate 	if (map->map_rebuild != NULL)
61227c478bd9Sstevel@tonic-gate 	{
61237c478bd9Sstevel@tonic-gate 		(void) sm_strlcpy(buf, map->map_rebuild, sizeof buf);
61247c478bd9Sstevel@tonic-gate 		for (p = strtok(buf, " \t"); p != NULL; p = strtok(NULL, " \t"))
61257c478bd9Sstevel@tonic-gate 		{
61267c478bd9Sstevel@tonic-gate 			if (i >= MAXPV - 1)
61277c478bd9Sstevel@tonic-gate 				break;
61287c478bd9Sstevel@tonic-gate 			argv[i++] = p;
61297c478bd9Sstevel@tonic-gate 		}
61307c478bd9Sstevel@tonic-gate 	}
61317c478bd9Sstevel@tonic-gate 	argv[i++] = name;
61327c478bd9Sstevel@tonic-gate 	argv[i] = NULL;
61337c478bd9Sstevel@tonic-gate 	if (tTd(38, 21))
61347c478bd9Sstevel@tonic-gate 	{
61357c478bd9Sstevel@tonic-gate 		sm_dprintf("prog_open:");
61367c478bd9Sstevel@tonic-gate 		for (i = 0; argv[i] != NULL; i++)
61377c478bd9Sstevel@tonic-gate 			sm_dprintf(" %s", argv[i]);
61387c478bd9Sstevel@tonic-gate 		sm_dprintf("\n");
61397c478bd9Sstevel@tonic-gate 	}
61407c478bd9Sstevel@tonic-gate 	(void) sm_blocksignal(SIGCHLD);
61417c478bd9Sstevel@tonic-gate 	pid = prog_open(argv, &fd, CurEnv);
61427c478bd9Sstevel@tonic-gate 	if (pid < 0)
61437c478bd9Sstevel@tonic-gate 	{
61447c478bd9Sstevel@tonic-gate 		if (!bitset(MF_OPTIONAL, map->map_mflags))
61457c478bd9Sstevel@tonic-gate 			syserr("prog_map_lookup(%s) failed (%s) -- closing",
61467c478bd9Sstevel@tonic-gate 			       map->map_mname, sm_errstring(errno));
61477c478bd9Sstevel@tonic-gate 		else if (tTd(38, 9))
61487c478bd9Sstevel@tonic-gate 			sm_dprintf("prog_map_lookup(%s) failed (%s) -- closing",
61497c478bd9Sstevel@tonic-gate 				   map->map_mname, sm_errstring(errno));
61507c478bd9Sstevel@tonic-gate 		map->map_mflags &= ~(MF_VALID|MF_OPEN);
61517c478bd9Sstevel@tonic-gate 		*statp = EX_OSFILE;
61527c478bd9Sstevel@tonic-gate 		return NULL;
61537c478bd9Sstevel@tonic-gate 	}
61547c478bd9Sstevel@tonic-gate 	i = read(fd, buf, sizeof buf - 1);
61557c478bd9Sstevel@tonic-gate 	if (i < 0)
61567c478bd9Sstevel@tonic-gate 	{
61577c478bd9Sstevel@tonic-gate 		syserr("prog_map_lookup(%s): read error %s",
61587c478bd9Sstevel@tonic-gate 		       map->map_mname, sm_errstring(errno));
61597c478bd9Sstevel@tonic-gate 		rval = NULL;
61607c478bd9Sstevel@tonic-gate 	}
61617c478bd9Sstevel@tonic-gate 	else if (i == 0)
61627c478bd9Sstevel@tonic-gate 	{
61637c478bd9Sstevel@tonic-gate 		if (tTd(38, 20))
61647c478bd9Sstevel@tonic-gate 			sm_dprintf("prog_map_lookup(%s): empty answer\n",
61657c478bd9Sstevel@tonic-gate 				   map->map_mname);
61667c478bd9Sstevel@tonic-gate 		rval = NULL;
61677c478bd9Sstevel@tonic-gate 	}
61687c478bd9Sstevel@tonic-gate 	else
61697c478bd9Sstevel@tonic-gate 	{
61707c478bd9Sstevel@tonic-gate 		buf[i] = '\0';
61717c478bd9Sstevel@tonic-gate 		p = strchr(buf, '\n');
61727c478bd9Sstevel@tonic-gate 		if (p != NULL)
61737c478bd9Sstevel@tonic-gate 			*p = '\0';
61747c478bd9Sstevel@tonic-gate 
61757c478bd9Sstevel@tonic-gate 		/* collect the return value */
61767c478bd9Sstevel@tonic-gate 		if (bitset(MF_MATCHONLY, map->map_mflags))
61777c478bd9Sstevel@tonic-gate 			rval = map_rewrite(map, name, strlen(name), NULL);
61787c478bd9Sstevel@tonic-gate 		else
61797c478bd9Sstevel@tonic-gate 			rval = map_rewrite(map, buf, strlen(buf), av);
61807c478bd9Sstevel@tonic-gate 
61817c478bd9Sstevel@tonic-gate 		/* now flush any additional output */
61827c478bd9Sstevel@tonic-gate 		while ((i = read(fd, buf, sizeof buf)) > 0)
61837c478bd9Sstevel@tonic-gate 			continue;
61847c478bd9Sstevel@tonic-gate 	}
61857c478bd9Sstevel@tonic-gate 
61867c478bd9Sstevel@tonic-gate 	/* wait for the process to terminate */
61877c478bd9Sstevel@tonic-gate 	(void) close(fd);
61887c478bd9Sstevel@tonic-gate 	status = waitfor(pid);
61897c478bd9Sstevel@tonic-gate 	save_errno = errno;
61907c478bd9Sstevel@tonic-gate 	(void) sm_releasesignal(SIGCHLD);
61917c478bd9Sstevel@tonic-gate 	errno = save_errno;
61927c478bd9Sstevel@tonic-gate 
61937c478bd9Sstevel@tonic-gate 	if (status == -1)
61947c478bd9Sstevel@tonic-gate 	{
61957c478bd9Sstevel@tonic-gate 		syserr("prog_map_lookup(%s): wait error %s",
61967c478bd9Sstevel@tonic-gate 		       map->map_mname, sm_errstring(errno));
61977c478bd9Sstevel@tonic-gate 		*statp = EX_SOFTWARE;
61987c478bd9Sstevel@tonic-gate 		rval = NULL;
61997c478bd9Sstevel@tonic-gate 	}
62007c478bd9Sstevel@tonic-gate 	else if (WIFEXITED(status))
62017c478bd9Sstevel@tonic-gate 	{
62027c478bd9Sstevel@tonic-gate 		if ((*statp = WEXITSTATUS(status)) != EX_OK)
62037c478bd9Sstevel@tonic-gate 			rval = NULL;
62047c478bd9Sstevel@tonic-gate 	}
62057c478bd9Sstevel@tonic-gate 	else
62067c478bd9Sstevel@tonic-gate 	{
62077c478bd9Sstevel@tonic-gate 		syserr("prog_map_lookup(%s): child died on signal %d",
62087c478bd9Sstevel@tonic-gate 		       map->map_mname, status);
62097c478bd9Sstevel@tonic-gate 		*statp = EX_UNAVAILABLE;
62107c478bd9Sstevel@tonic-gate 		rval = NULL;
62117c478bd9Sstevel@tonic-gate 	}
62127c478bd9Sstevel@tonic-gate 	return rval;
62137c478bd9Sstevel@tonic-gate }
62147c478bd9Sstevel@tonic-gate /*
62157c478bd9Sstevel@tonic-gate **  Sequenced map type.
62167c478bd9Sstevel@tonic-gate **
62177c478bd9Sstevel@tonic-gate **	Tries each map in order until something matches, much like
62187c478bd9Sstevel@tonic-gate **	implicit.  Stores go to the first map in the list that can
62197c478bd9Sstevel@tonic-gate **	support storing.
62207c478bd9Sstevel@tonic-gate **
62217c478bd9Sstevel@tonic-gate **	This is slightly unusual in that there are two interfaces.
62227c478bd9Sstevel@tonic-gate **	The "sequence" interface lets you stack maps arbitrarily.
62237c478bd9Sstevel@tonic-gate **	The "switch" interface builds a sequence map by looking
62247c478bd9Sstevel@tonic-gate **	at a system-dependent configuration file such as
62257c478bd9Sstevel@tonic-gate **	/etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix.
62267c478bd9Sstevel@tonic-gate **
62277c478bd9Sstevel@tonic-gate **	We don't need an explicit open, since all maps are
62287c478bd9Sstevel@tonic-gate **	opened on demand.
62297c478bd9Sstevel@tonic-gate */
62307c478bd9Sstevel@tonic-gate 
62317c478bd9Sstevel@tonic-gate /*
62327c478bd9Sstevel@tonic-gate **  SEQ_MAP_PARSE -- Sequenced map parsing
62337c478bd9Sstevel@tonic-gate */
62347c478bd9Sstevel@tonic-gate 
62357c478bd9Sstevel@tonic-gate bool
62367c478bd9Sstevel@tonic-gate seq_map_parse(map, ap)
62377c478bd9Sstevel@tonic-gate 	MAP *map;
62387c478bd9Sstevel@tonic-gate 	char *ap;
62397c478bd9Sstevel@tonic-gate {
62407c478bd9Sstevel@tonic-gate 	int maxmap;
62417c478bd9Sstevel@tonic-gate 
62427c478bd9Sstevel@tonic-gate 	if (tTd(38, 2))
62437c478bd9Sstevel@tonic-gate 		sm_dprintf("seq_map_parse(%s, %s)\n", map->map_mname, ap);
62447c478bd9Sstevel@tonic-gate 	maxmap = 0;
62457c478bd9Sstevel@tonic-gate 	while (*ap != '\0')
62467c478bd9Sstevel@tonic-gate 	{
62477c478bd9Sstevel@tonic-gate 		register char *p;
62487c478bd9Sstevel@tonic-gate 		STAB *s;
62497c478bd9Sstevel@tonic-gate 
62507c478bd9Sstevel@tonic-gate 		/* find beginning of map name */
62517c478bd9Sstevel@tonic-gate 		while (isascii(*ap) && isspace(*ap))
62527c478bd9Sstevel@tonic-gate 			ap++;
62537c478bd9Sstevel@tonic-gate 		for (p = ap;
62547c478bd9Sstevel@tonic-gate 		     (isascii(*p) && isalnum(*p)) || *p == '_' || *p == '.';
62557c478bd9Sstevel@tonic-gate 		     p++)
62567c478bd9Sstevel@tonic-gate 			continue;
62577c478bd9Sstevel@tonic-gate 		if (*p != '\0')
62587c478bd9Sstevel@tonic-gate 			*p++ = '\0';
62597c478bd9Sstevel@tonic-gate 		while (*p != '\0' && (!isascii(*p) || !isalnum(*p)))
62607c478bd9Sstevel@tonic-gate 			p++;
62617c478bd9Sstevel@tonic-gate 		if (*ap == '\0')
62627c478bd9Sstevel@tonic-gate 		{
62637c478bd9Sstevel@tonic-gate 			ap = p;
62647c478bd9Sstevel@tonic-gate 			continue;
62657c478bd9Sstevel@tonic-gate 		}
62667c478bd9Sstevel@tonic-gate 		s = stab(ap, ST_MAP, ST_FIND);
62677c478bd9Sstevel@tonic-gate 		if (s == NULL)
62687c478bd9Sstevel@tonic-gate 		{
62697c478bd9Sstevel@tonic-gate 			syserr("Sequence map %s: unknown member map %s",
62707c478bd9Sstevel@tonic-gate 				map->map_mname, ap);
62717c478bd9Sstevel@tonic-gate 		}
62727c478bd9Sstevel@tonic-gate 		else if (maxmap >= MAXMAPSTACK)
62737c478bd9Sstevel@tonic-gate 		{
62747c478bd9Sstevel@tonic-gate 			syserr("Sequence map %s: too many member maps (%d max)",
62757c478bd9Sstevel@tonic-gate 				map->map_mname, MAXMAPSTACK);
62767c478bd9Sstevel@tonic-gate 			maxmap++;
62777c478bd9Sstevel@tonic-gate 		}
62787c478bd9Sstevel@tonic-gate 		else if (maxmap < MAXMAPSTACK)
62797c478bd9Sstevel@tonic-gate 		{
62807c478bd9Sstevel@tonic-gate 			map->map_stack[maxmap++] = &s->s_map;
62817c478bd9Sstevel@tonic-gate 		}
62827c478bd9Sstevel@tonic-gate 		ap = p;
62837c478bd9Sstevel@tonic-gate 	}
62847c478bd9Sstevel@tonic-gate 	return true;
62857c478bd9Sstevel@tonic-gate }
62867c478bd9Sstevel@tonic-gate 
62877c478bd9Sstevel@tonic-gate /*
62887c478bd9Sstevel@tonic-gate **  SWITCH_MAP_OPEN -- open a switched map
62897c478bd9Sstevel@tonic-gate **
62907c478bd9Sstevel@tonic-gate **	This looks at the system-dependent configuration and builds
62917c478bd9Sstevel@tonic-gate **	a sequence map that does the same thing.
62927c478bd9Sstevel@tonic-gate **
62937c478bd9Sstevel@tonic-gate **	Every system must define a switch_map_find routine in conf.c
62947c478bd9Sstevel@tonic-gate **	that will return the list of service types associated with a
62957c478bd9Sstevel@tonic-gate **	given service class.
62967c478bd9Sstevel@tonic-gate */
62977c478bd9Sstevel@tonic-gate 
62987c478bd9Sstevel@tonic-gate bool
62997c478bd9Sstevel@tonic-gate switch_map_open(map, mode)
63007c478bd9Sstevel@tonic-gate 	MAP *map;
63017c478bd9Sstevel@tonic-gate 	int mode;
63027c478bd9Sstevel@tonic-gate {
63037c478bd9Sstevel@tonic-gate 	int mapno;
63047c478bd9Sstevel@tonic-gate 	int nmaps;
63057c478bd9Sstevel@tonic-gate 	char *maptype[MAXMAPSTACK];
63067c478bd9Sstevel@tonic-gate 
63077c478bd9Sstevel@tonic-gate 	if (tTd(38, 2))
63087c478bd9Sstevel@tonic-gate 		sm_dprintf("switch_map_open(%s, %s, %d)\n",
63097c478bd9Sstevel@tonic-gate 			map->map_mname, map->map_file, mode);
63107c478bd9Sstevel@tonic-gate 
63117c478bd9Sstevel@tonic-gate 	mode &= O_ACCMODE;
63127c478bd9Sstevel@tonic-gate 	nmaps = switch_map_find(map->map_file, maptype, map->map_return);
63137c478bd9Sstevel@tonic-gate 	if (tTd(38, 19))
63147c478bd9Sstevel@tonic-gate 	{
63157c478bd9Sstevel@tonic-gate 		sm_dprintf("\tswitch_map_find => %d\n", nmaps);
63167c478bd9Sstevel@tonic-gate 		for (mapno = 0; mapno < nmaps; mapno++)
63177c478bd9Sstevel@tonic-gate 			sm_dprintf("\t\t%s\n", maptype[mapno]);
63187c478bd9Sstevel@tonic-gate 	}
63197c478bd9Sstevel@tonic-gate 	if (nmaps <= 0 || nmaps > MAXMAPSTACK)
63207c478bd9Sstevel@tonic-gate 		return false;
63217c478bd9Sstevel@tonic-gate 
63227c478bd9Sstevel@tonic-gate 	for (mapno = 0; mapno < nmaps; mapno++)
63237c478bd9Sstevel@tonic-gate 	{
63247c478bd9Sstevel@tonic-gate 		register STAB *s;
63257c478bd9Sstevel@tonic-gate 		char nbuf[MAXNAME + 1];
63267c478bd9Sstevel@tonic-gate 
63277c478bd9Sstevel@tonic-gate 		if (maptype[mapno] == NULL)
63287c478bd9Sstevel@tonic-gate 			continue;
63297c478bd9Sstevel@tonic-gate 		(void) sm_strlcpyn(nbuf, sizeof nbuf, 3,
63307c478bd9Sstevel@tonic-gate 				   map->map_mname, ".", maptype[mapno]);
63317c478bd9Sstevel@tonic-gate 		s = stab(nbuf, ST_MAP, ST_FIND);
63327c478bd9Sstevel@tonic-gate 		if (s == NULL)
63337c478bd9Sstevel@tonic-gate 		{
63347c478bd9Sstevel@tonic-gate 			syserr("Switch map %s: unknown member map %s",
63357c478bd9Sstevel@tonic-gate 				map->map_mname, nbuf);
63367c478bd9Sstevel@tonic-gate 		}
63377c478bd9Sstevel@tonic-gate 		else
63387c478bd9Sstevel@tonic-gate 		{
63397c478bd9Sstevel@tonic-gate 			map->map_stack[mapno] = &s->s_map;
63407c478bd9Sstevel@tonic-gate 			if (tTd(38, 4))
63417c478bd9Sstevel@tonic-gate 				sm_dprintf("\tmap_stack[%d] = %s:%s\n",
63427c478bd9Sstevel@tonic-gate 					   mapno,
63437c478bd9Sstevel@tonic-gate 					   s->s_map.map_class->map_cname,
63447c478bd9Sstevel@tonic-gate 					   nbuf);
63457c478bd9Sstevel@tonic-gate 		}
63467c478bd9Sstevel@tonic-gate 	}
63477c478bd9Sstevel@tonic-gate 	return true;
63487c478bd9Sstevel@tonic-gate }
63497c478bd9Sstevel@tonic-gate 
63507c478bd9Sstevel@tonic-gate #if 0
63517c478bd9Sstevel@tonic-gate /*
63527c478bd9Sstevel@tonic-gate **  SEQ_MAP_CLOSE -- close all underlying maps
63537c478bd9Sstevel@tonic-gate */
63547c478bd9Sstevel@tonic-gate 
63557c478bd9Sstevel@tonic-gate void
63567c478bd9Sstevel@tonic-gate seq_map_close(map)
63577c478bd9Sstevel@tonic-gate 	MAP *map;
63587c478bd9Sstevel@tonic-gate {
63597c478bd9Sstevel@tonic-gate 	int mapno;
63607c478bd9Sstevel@tonic-gate 
63617c478bd9Sstevel@tonic-gate 	if (tTd(38, 9))
63627c478bd9Sstevel@tonic-gate 		sm_dprintf("seq_map_close(%s)\n", map->map_mname);
63637c478bd9Sstevel@tonic-gate 
63647c478bd9Sstevel@tonic-gate 	for (mapno = 0; mapno < MAXMAPSTACK; mapno++)
63657c478bd9Sstevel@tonic-gate 	{
63667c478bd9Sstevel@tonic-gate 		MAP *mm = map->map_stack[mapno];
63677c478bd9Sstevel@tonic-gate 
63687c478bd9Sstevel@tonic-gate 		if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags))
63697c478bd9Sstevel@tonic-gate 			continue;
63707c478bd9Sstevel@tonic-gate 		mm->map_mflags |= MF_CLOSING;
63717c478bd9Sstevel@tonic-gate 		mm->map_class->map_close(mm);
63727c478bd9Sstevel@tonic-gate 		mm->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING);
63737c478bd9Sstevel@tonic-gate 	}
63747c478bd9Sstevel@tonic-gate }
63757c478bd9Sstevel@tonic-gate #endif /* 0 */
63767c478bd9Sstevel@tonic-gate 
63777c478bd9Sstevel@tonic-gate /*
63787c478bd9Sstevel@tonic-gate **  SEQ_MAP_LOOKUP -- sequenced map lookup
63797c478bd9Sstevel@tonic-gate */
63807c478bd9Sstevel@tonic-gate 
63817c478bd9Sstevel@tonic-gate char *
63827c478bd9Sstevel@tonic-gate seq_map_lookup(map, key, args, pstat)
63837c478bd9Sstevel@tonic-gate 	MAP *map;
63847c478bd9Sstevel@tonic-gate 	char *key;
63857c478bd9Sstevel@tonic-gate 	char **args;
63867c478bd9Sstevel@tonic-gate 	int *pstat;
63877c478bd9Sstevel@tonic-gate {
63887c478bd9Sstevel@tonic-gate 	int mapno;
63897c478bd9Sstevel@tonic-gate 	int mapbit = 0x01;
63907c478bd9Sstevel@tonic-gate 	bool tempfail = false;
63917c478bd9Sstevel@tonic-gate 
63927c478bd9Sstevel@tonic-gate 	if (tTd(38, 20))
63937c478bd9Sstevel@tonic-gate 		sm_dprintf("seq_map_lookup(%s, %s)\n", map->map_mname, key);
63947c478bd9Sstevel@tonic-gate 
63957c478bd9Sstevel@tonic-gate 	for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++)
63967c478bd9Sstevel@tonic-gate 	{
63977c478bd9Sstevel@tonic-gate 		MAP *mm = map->map_stack[mapno];
63987c478bd9Sstevel@tonic-gate 		char *rv;
63997c478bd9Sstevel@tonic-gate 
64007c478bd9Sstevel@tonic-gate 		if (mm == NULL)
64017c478bd9Sstevel@tonic-gate 			continue;
64027c478bd9Sstevel@tonic-gate 		if (!bitset(MF_OPEN, mm->map_mflags) &&
64037c478bd9Sstevel@tonic-gate 		    !openmap(mm))
64047c478bd9Sstevel@tonic-gate 		{
64057c478bd9Sstevel@tonic-gate 			if (bitset(mapbit, map->map_return[MA_UNAVAIL]))
64067c478bd9Sstevel@tonic-gate 			{
64077c478bd9Sstevel@tonic-gate 				*pstat = EX_UNAVAILABLE;
64087c478bd9Sstevel@tonic-gate 				return NULL;
64097c478bd9Sstevel@tonic-gate 			}
64107c478bd9Sstevel@tonic-gate 			continue;
64117c478bd9Sstevel@tonic-gate 		}
64127c478bd9Sstevel@tonic-gate 		*pstat = EX_OK;
64137c478bd9Sstevel@tonic-gate 		rv = mm->map_class->map_lookup(mm, key, args, pstat);
64147c478bd9Sstevel@tonic-gate 		if (rv != NULL)
64157c478bd9Sstevel@tonic-gate 			return rv;
64167c478bd9Sstevel@tonic-gate 		if (*pstat == EX_TEMPFAIL)
64177c478bd9Sstevel@tonic-gate 		{
64187c478bd9Sstevel@tonic-gate 			if (bitset(mapbit, map->map_return[MA_TRYAGAIN]))
64197c478bd9Sstevel@tonic-gate 				return NULL;
64207c478bd9Sstevel@tonic-gate 			tempfail = true;
64217c478bd9Sstevel@tonic-gate 		}
64227c478bd9Sstevel@tonic-gate 		else if (bitset(mapbit, map->map_return[MA_NOTFOUND]))
64237c478bd9Sstevel@tonic-gate 			break;
64247c478bd9Sstevel@tonic-gate 	}
64257c478bd9Sstevel@tonic-gate 	if (tempfail)
64267c478bd9Sstevel@tonic-gate 		*pstat = EX_TEMPFAIL;
64277c478bd9Sstevel@tonic-gate 	else if (*pstat == EX_OK)
64287c478bd9Sstevel@tonic-gate 		*pstat = EX_NOTFOUND;
64297c478bd9Sstevel@tonic-gate 	return NULL;
64307c478bd9Sstevel@tonic-gate }
64317c478bd9Sstevel@tonic-gate 
64327c478bd9Sstevel@tonic-gate /*
64337c478bd9Sstevel@tonic-gate **  SEQ_MAP_STORE -- sequenced map store
64347c478bd9Sstevel@tonic-gate */
64357c478bd9Sstevel@tonic-gate 
64367c478bd9Sstevel@tonic-gate void
64377c478bd9Sstevel@tonic-gate seq_map_store(map, key, val)
64387c478bd9Sstevel@tonic-gate 	MAP *map;
64397c478bd9Sstevel@tonic-gate 	char *key;
64407c478bd9Sstevel@tonic-gate 	char *val;
64417c478bd9Sstevel@tonic-gate {
64427c478bd9Sstevel@tonic-gate 	int mapno;
64437c478bd9Sstevel@tonic-gate 
64447c478bd9Sstevel@tonic-gate 	if (tTd(38, 12))
64457c478bd9Sstevel@tonic-gate 		sm_dprintf("seq_map_store(%s, %s, %s)\n",
64467c478bd9Sstevel@tonic-gate 			map->map_mname, key, val);
64477c478bd9Sstevel@tonic-gate 
64487c478bd9Sstevel@tonic-gate 	for (mapno = 0; mapno < MAXMAPSTACK; mapno++)
64497c478bd9Sstevel@tonic-gate 	{
64507c478bd9Sstevel@tonic-gate 		MAP *mm = map->map_stack[mapno];
64517c478bd9Sstevel@tonic-gate 
64527c478bd9Sstevel@tonic-gate 		if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags))
64537c478bd9Sstevel@tonic-gate 			continue;
64547c478bd9Sstevel@tonic-gate 
64557c478bd9Sstevel@tonic-gate 		mm->map_class->map_store(mm, key, val);
64567c478bd9Sstevel@tonic-gate 		return;
64577c478bd9Sstevel@tonic-gate 	}
64587c478bd9Sstevel@tonic-gate 	syserr("seq_map_store(%s, %s, %s): no writable map",
64597c478bd9Sstevel@tonic-gate 		map->map_mname, key, val);
64607c478bd9Sstevel@tonic-gate }
64617c478bd9Sstevel@tonic-gate /*
64627c478bd9Sstevel@tonic-gate **  NULL stubs
64637c478bd9Sstevel@tonic-gate */
64647c478bd9Sstevel@tonic-gate 
64657c478bd9Sstevel@tonic-gate /* ARGSUSED */
64667c478bd9Sstevel@tonic-gate bool
64677c478bd9Sstevel@tonic-gate null_map_open(map, mode)
64687c478bd9Sstevel@tonic-gate 	MAP *map;
64697c478bd9Sstevel@tonic-gate 	int mode;
64707c478bd9Sstevel@tonic-gate {
64717c478bd9Sstevel@tonic-gate 	return true;
64727c478bd9Sstevel@tonic-gate }
64737c478bd9Sstevel@tonic-gate 
64747c478bd9Sstevel@tonic-gate /* ARGSUSED */
64757c478bd9Sstevel@tonic-gate void
64767c478bd9Sstevel@tonic-gate null_map_close(map)
64777c478bd9Sstevel@tonic-gate 	MAP *map;
64787c478bd9Sstevel@tonic-gate {
64797c478bd9Sstevel@tonic-gate 	return;
64807c478bd9Sstevel@tonic-gate }
64817c478bd9Sstevel@tonic-gate 
64827c478bd9Sstevel@tonic-gate char *
64837c478bd9Sstevel@tonic-gate null_map_lookup(map, key, args, pstat)
64847c478bd9Sstevel@tonic-gate 	MAP *map;
64857c478bd9Sstevel@tonic-gate 	char *key;
64867c478bd9Sstevel@tonic-gate 	char **args;
64877c478bd9Sstevel@tonic-gate 	int *pstat;
64887c478bd9Sstevel@tonic-gate {
64897c478bd9Sstevel@tonic-gate 	*pstat = EX_NOTFOUND;
64907c478bd9Sstevel@tonic-gate 	return NULL;
64917c478bd9Sstevel@tonic-gate }
64927c478bd9Sstevel@tonic-gate 
64937c478bd9Sstevel@tonic-gate /* ARGSUSED */
64947c478bd9Sstevel@tonic-gate void
64957c478bd9Sstevel@tonic-gate null_map_store(map, key, val)
64967c478bd9Sstevel@tonic-gate 	MAP *map;
64977c478bd9Sstevel@tonic-gate 	char *key;
64987c478bd9Sstevel@tonic-gate 	char *val;
64997c478bd9Sstevel@tonic-gate {
65007c478bd9Sstevel@tonic-gate 	return;
65017c478bd9Sstevel@tonic-gate }
65027c478bd9Sstevel@tonic-gate 
65037c478bd9Sstevel@tonic-gate /*
65047c478bd9Sstevel@tonic-gate **  BOGUS stubs
65057c478bd9Sstevel@tonic-gate */
65067c478bd9Sstevel@tonic-gate 
65077c478bd9Sstevel@tonic-gate char *
65087c478bd9Sstevel@tonic-gate bogus_map_lookup(map, key, args, pstat)
65097c478bd9Sstevel@tonic-gate 	MAP *map;
65107c478bd9Sstevel@tonic-gate 	char *key;
65117c478bd9Sstevel@tonic-gate 	char **args;
65127c478bd9Sstevel@tonic-gate 	int *pstat;
65137c478bd9Sstevel@tonic-gate {
65147c478bd9Sstevel@tonic-gate 	*pstat = EX_TEMPFAIL;
65157c478bd9Sstevel@tonic-gate 	return NULL;
65167c478bd9Sstevel@tonic-gate }
65177c478bd9Sstevel@tonic-gate 
65187c478bd9Sstevel@tonic-gate MAPCLASS	BogusMapClass =
65197c478bd9Sstevel@tonic-gate {
65207c478bd9Sstevel@tonic-gate 	"bogus-map",		NULL,			0,
65217c478bd9Sstevel@tonic-gate 	NULL,			bogus_map_lookup,	null_map_store,
65227c478bd9Sstevel@tonic-gate 	null_map_open,		null_map_close,
65237c478bd9Sstevel@tonic-gate };
65247c478bd9Sstevel@tonic-gate /*
65257c478bd9Sstevel@tonic-gate **  MACRO modules
65267c478bd9Sstevel@tonic-gate */
65277c478bd9Sstevel@tonic-gate 
65287c478bd9Sstevel@tonic-gate char *
65297c478bd9Sstevel@tonic-gate macro_map_lookup(map, name, av, statp)
65307c478bd9Sstevel@tonic-gate 	MAP *map;
65317c478bd9Sstevel@tonic-gate 	char *name;
65327c478bd9Sstevel@tonic-gate 	char **av;
65337c478bd9Sstevel@tonic-gate 	int *statp;
65347c478bd9Sstevel@tonic-gate {
65357c478bd9Sstevel@tonic-gate 	int mid;
65367c478bd9Sstevel@tonic-gate 
65377c478bd9Sstevel@tonic-gate 	if (tTd(38, 20))
65387c478bd9Sstevel@tonic-gate 		sm_dprintf("macro_map_lookup(%s, %s)\n", map->map_mname,
65397c478bd9Sstevel@tonic-gate 			name == NULL ? "NULL" : name);
65407c478bd9Sstevel@tonic-gate 
65417c478bd9Sstevel@tonic-gate 	if (name == NULL ||
65427c478bd9Sstevel@tonic-gate 	    *name == '\0' ||
65437c478bd9Sstevel@tonic-gate 	    (mid = macid(name)) == 0)
65447c478bd9Sstevel@tonic-gate 	{
65457c478bd9Sstevel@tonic-gate 		*statp = EX_CONFIG;
65467c478bd9Sstevel@tonic-gate 		return NULL;
65477c478bd9Sstevel@tonic-gate 	}
65487c478bd9Sstevel@tonic-gate 
65497c478bd9Sstevel@tonic-gate 	if (av[1] == NULL)
65507c478bd9Sstevel@tonic-gate 		macdefine(&CurEnv->e_macro, A_PERM, mid, NULL);
65517c478bd9Sstevel@tonic-gate 	else
65527c478bd9Sstevel@tonic-gate 		macdefine(&CurEnv->e_macro, A_TEMP, mid, av[1]);
65537c478bd9Sstevel@tonic-gate 
65547c478bd9Sstevel@tonic-gate 	*statp = EX_OK;
65557c478bd9Sstevel@tonic-gate 	return "";
65567c478bd9Sstevel@tonic-gate }
65577c478bd9Sstevel@tonic-gate /*
65587c478bd9Sstevel@tonic-gate **  REGEX modules
65597c478bd9Sstevel@tonic-gate */
65607c478bd9Sstevel@tonic-gate 
65617c478bd9Sstevel@tonic-gate #if MAP_REGEX
65627c478bd9Sstevel@tonic-gate 
65637c478bd9Sstevel@tonic-gate # include <regex.h>
65647c478bd9Sstevel@tonic-gate 
65657c478bd9Sstevel@tonic-gate # define DEFAULT_DELIM	CONDELSE
65667c478bd9Sstevel@tonic-gate # define END_OF_FIELDS	-1
65677c478bd9Sstevel@tonic-gate # define ERRBUF_SIZE	80
65687c478bd9Sstevel@tonic-gate # define MAX_MATCH	32
65697c478bd9Sstevel@tonic-gate 
65707c478bd9Sstevel@tonic-gate # define xnalloc(s)	memset(xalloc(s), '\0', s);
65717c478bd9Sstevel@tonic-gate 
65727c478bd9Sstevel@tonic-gate struct regex_map
65737c478bd9Sstevel@tonic-gate {
65747c478bd9Sstevel@tonic-gate 	regex_t	*regex_pattern_buf;	/* xalloc it */
65757c478bd9Sstevel@tonic-gate 	int	*regex_subfields;	/* move to type MAP */
65767c478bd9Sstevel@tonic-gate 	char	*regex_delim;		/* move to type MAP */
65777c478bd9Sstevel@tonic-gate };
65787c478bd9Sstevel@tonic-gate 
65797c478bd9Sstevel@tonic-gate static int	parse_fields __P((char *, int *, int, int));
65807c478bd9Sstevel@tonic-gate static char	*regex_map_rewrite __P((MAP *, const char*, size_t, char **));
65817c478bd9Sstevel@tonic-gate 
65827c478bd9Sstevel@tonic-gate static int
65837c478bd9Sstevel@tonic-gate parse_fields(s, ibuf, blen, nr_substrings)
65847c478bd9Sstevel@tonic-gate 	char *s;
65857c478bd9Sstevel@tonic-gate 	int *ibuf;		/* array */
65867c478bd9Sstevel@tonic-gate 	int blen;		/* number of elements in ibuf */
65877c478bd9Sstevel@tonic-gate 	int nr_substrings;	/* number of substrings in the pattern */
65887c478bd9Sstevel@tonic-gate {
65897c478bd9Sstevel@tonic-gate 	register char *cp;
65907c478bd9Sstevel@tonic-gate 	int i = 0;
65917c478bd9Sstevel@tonic-gate 	bool lastone = false;
65927c478bd9Sstevel@tonic-gate 
65937c478bd9Sstevel@tonic-gate 	blen--;		/* for terminating END_OF_FIELDS */
65947c478bd9Sstevel@tonic-gate 	cp = s;
65957c478bd9Sstevel@tonic-gate 	do
65967c478bd9Sstevel@tonic-gate 	{
65977c478bd9Sstevel@tonic-gate 		for (;; cp++)
65987c478bd9Sstevel@tonic-gate 		{
65997c478bd9Sstevel@tonic-gate 			if (*cp == ',')
66007c478bd9Sstevel@tonic-gate 			{
66017c478bd9Sstevel@tonic-gate 				*cp = '\0';
66027c478bd9Sstevel@tonic-gate 				break;
66037c478bd9Sstevel@tonic-gate 			}
66047c478bd9Sstevel@tonic-gate 			if (*cp == '\0')
66057c478bd9Sstevel@tonic-gate 			{
66067c478bd9Sstevel@tonic-gate 				lastone = true;
66077c478bd9Sstevel@tonic-gate 				break;
66087c478bd9Sstevel@tonic-gate 			}
66097c478bd9Sstevel@tonic-gate 		}
66107c478bd9Sstevel@tonic-gate 		if (i < blen)
66117c478bd9Sstevel@tonic-gate 		{
66127c478bd9Sstevel@tonic-gate 			int val = atoi(s);
66137c478bd9Sstevel@tonic-gate 
66147c478bd9Sstevel@tonic-gate 			if (val < 0 || val >= nr_substrings)
66157c478bd9Sstevel@tonic-gate 			{
66167c478bd9Sstevel@tonic-gate 				syserr("field (%d) out of range, only %d substrings in pattern",
66177c478bd9Sstevel@tonic-gate 				       val, nr_substrings);
66187c478bd9Sstevel@tonic-gate 				return -1;
66197c478bd9Sstevel@tonic-gate 			}
66207c478bd9Sstevel@tonic-gate 			ibuf[i++] = val;
66217c478bd9Sstevel@tonic-gate 		}
66227c478bd9Sstevel@tonic-gate 		else
66237c478bd9Sstevel@tonic-gate 		{
66247c478bd9Sstevel@tonic-gate 			syserr("too many fields, %d max", blen);
66257c478bd9Sstevel@tonic-gate 			return -1;
66267c478bd9Sstevel@tonic-gate 		}
66277c478bd9Sstevel@tonic-gate 		s = ++cp;
66287c478bd9Sstevel@tonic-gate 	} while (!lastone);
66297c478bd9Sstevel@tonic-gate 	ibuf[i] = END_OF_FIELDS;
66307c478bd9Sstevel@tonic-gate 	return i;
66317c478bd9Sstevel@tonic-gate }
66327c478bd9Sstevel@tonic-gate 
66337c478bd9Sstevel@tonic-gate bool
66347c478bd9Sstevel@tonic-gate regex_map_init(map, ap)
66357c478bd9Sstevel@tonic-gate 	MAP *map;
66367c478bd9Sstevel@tonic-gate 	char *ap;
66377c478bd9Sstevel@tonic-gate {
66387c478bd9Sstevel@tonic-gate 	int regerr;
66397c478bd9Sstevel@tonic-gate 	struct regex_map *map_p;
66407c478bd9Sstevel@tonic-gate 	register char *p;
66417c478bd9Sstevel@tonic-gate 	char *sub_param = NULL;
66427c478bd9Sstevel@tonic-gate 	int pflags;
66437c478bd9Sstevel@tonic-gate 	static char defdstr[] = { (char) DEFAULT_DELIM, '\0' };
66447c478bd9Sstevel@tonic-gate 
66457c478bd9Sstevel@tonic-gate 	if (tTd(38, 2))
66467c478bd9Sstevel@tonic-gate 		sm_dprintf("regex_map_init: mapname '%s', args '%s'\n",
66477c478bd9Sstevel@tonic-gate 			map->map_mname, ap);
66487c478bd9Sstevel@tonic-gate 
66497c478bd9Sstevel@tonic-gate 	pflags = REG_ICASE | REG_EXTENDED | REG_NOSUB;
66507c478bd9Sstevel@tonic-gate 	p = ap;
66517c478bd9Sstevel@tonic-gate 	map_p = (struct regex_map *) xnalloc(sizeof *map_p);
66527c478bd9Sstevel@tonic-gate 	map_p->regex_pattern_buf = (regex_t *)xnalloc(sizeof(regex_t));
66537c478bd9Sstevel@tonic-gate 
66547c478bd9Sstevel@tonic-gate 	for (;;)
66557c478bd9Sstevel@tonic-gate 	{
66567c478bd9Sstevel@tonic-gate 		while (isascii(*p) && isspace(*p))
66577c478bd9Sstevel@tonic-gate 			p++;
66587c478bd9Sstevel@tonic-gate 		if (*p != '-')
66597c478bd9Sstevel@tonic-gate 			break;
66607c478bd9Sstevel@tonic-gate 		switch (*++p)
66617c478bd9Sstevel@tonic-gate 		{
66627c478bd9Sstevel@tonic-gate 		  case 'n':	/* not */
66637c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_REGEX_NOT;
66647c478bd9Sstevel@tonic-gate 			break;
66657c478bd9Sstevel@tonic-gate 
66667c478bd9Sstevel@tonic-gate 		  case 'f':	/* case sensitive */
66677c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_NOFOLDCASE;
66687c478bd9Sstevel@tonic-gate 			pflags &= ~REG_ICASE;
66697c478bd9Sstevel@tonic-gate 			break;
66707c478bd9Sstevel@tonic-gate 
66717c478bd9Sstevel@tonic-gate 		  case 'b':	/* basic regular expressions */
66727c478bd9Sstevel@tonic-gate 			pflags &= ~REG_EXTENDED;
66737c478bd9Sstevel@tonic-gate 			break;
66747c478bd9Sstevel@tonic-gate 
66757c478bd9Sstevel@tonic-gate 		  case 's':	/* substring match () syntax */
66767c478bd9Sstevel@tonic-gate 			sub_param = ++p;
66777c478bd9Sstevel@tonic-gate 			pflags &= ~REG_NOSUB;
66787c478bd9Sstevel@tonic-gate 			break;
66797c478bd9Sstevel@tonic-gate 
66807c478bd9Sstevel@tonic-gate 		  case 'd':	/* delimiter */
66817c478bd9Sstevel@tonic-gate 			map_p->regex_delim = ++p;
66827c478bd9Sstevel@tonic-gate 			break;
66837c478bd9Sstevel@tonic-gate 
66847c478bd9Sstevel@tonic-gate 		  case 'a':	/* map append */
66857c478bd9Sstevel@tonic-gate 			map->map_app = ++p;
66867c478bd9Sstevel@tonic-gate 			break;
66877c478bd9Sstevel@tonic-gate 
66887c478bd9Sstevel@tonic-gate 		  case 'm':	/* matchonly */
66897c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_MATCHONLY;
66907c478bd9Sstevel@tonic-gate 			break;
66917c478bd9Sstevel@tonic-gate 
66927c478bd9Sstevel@tonic-gate 		  case 'q':
66937c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_KEEPQUOTES;
66947c478bd9Sstevel@tonic-gate 			break;
66957c478bd9Sstevel@tonic-gate 
66967c478bd9Sstevel@tonic-gate 		  case 'S':
66977c478bd9Sstevel@tonic-gate 			map->map_spacesub = *++p;
66987c478bd9Sstevel@tonic-gate 			break;
66997c478bd9Sstevel@tonic-gate 
67007c478bd9Sstevel@tonic-gate 		  case 'D':
67017c478bd9Sstevel@tonic-gate 			map->map_mflags |= MF_DEFER;
67027c478bd9Sstevel@tonic-gate 			break;
67037c478bd9Sstevel@tonic-gate 
67047c478bd9Sstevel@tonic-gate 		}
67057c478bd9Sstevel@tonic-gate 		while (*p != '\0' && !(isascii(*p) && isspace(*p)))
67067c478bd9Sstevel@tonic-gate 			p++;
67077c478bd9Sstevel@tonic-gate 		if (*p != '\0')
67087c478bd9Sstevel@tonic-gate 			*p++ = '\0';
67097c478bd9Sstevel@tonic-gate 	}
67107c478bd9Sstevel@tonic-gate 	if (tTd(38, 3))
67117c478bd9Sstevel@tonic-gate 		sm_dprintf("regex_map_init: compile '%s' 0x%x\n", p, pflags);
67127c478bd9Sstevel@tonic-gate 
67137c478bd9Sstevel@tonic-gate 	if ((regerr = regcomp(map_p->regex_pattern_buf, p, pflags)) != 0)
67147c478bd9Sstevel@tonic-gate 	{
67157c478bd9Sstevel@tonic-gate 		/* Errorhandling */
67167c478bd9Sstevel@tonic-gate 		char errbuf[ERRBUF_SIZE];
67177c478bd9Sstevel@tonic-gate 
67187c478bd9Sstevel@tonic-gate 		(void) regerror(regerr, map_p->regex_pattern_buf,
67197c478bd9Sstevel@tonic-gate 			 errbuf, sizeof errbuf);
67207c478bd9Sstevel@tonic-gate 		syserr("pattern-compile-error: %s", errbuf);
67217c478bd9Sstevel@tonic-gate 		sm_free(map_p->regex_pattern_buf); /* XXX */
67227c478bd9Sstevel@tonic-gate 		sm_free(map_p); /* XXX */
67237c478bd9Sstevel@tonic-gate 		return false;
67247c478bd9Sstevel@tonic-gate 	}
67257c478bd9Sstevel@tonic-gate 
67267c478bd9Sstevel@tonic-gate 	if (map->map_app != NULL)
67277c478bd9Sstevel@tonic-gate 		map->map_app = newstr(map->map_app);
67287c478bd9Sstevel@tonic-gate 	if (map_p->regex_delim != NULL)
67297c478bd9Sstevel@tonic-gate 		map_p->regex_delim = newstr(map_p->regex_delim);
67307c478bd9Sstevel@tonic-gate 	else
67317c478bd9Sstevel@tonic-gate 		map_p->regex_delim = defdstr;
67327c478bd9Sstevel@tonic-gate 
67337c478bd9Sstevel@tonic-gate 	if (!bitset(REG_NOSUB, pflags))
67347c478bd9Sstevel@tonic-gate 	{
67357c478bd9Sstevel@tonic-gate 		/* substring matching */
67367c478bd9Sstevel@tonic-gate 		int substrings;
67377c478bd9Sstevel@tonic-gate 		int *fields = (int *) xalloc(sizeof(int) * (MAX_MATCH + 1));
67387c478bd9Sstevel@tonic-gate 
67397c478bd9Sstevel@tonic-gate 		substrings = map_p->regex_pattern_buf->re_nsub + 1;
67407c478bd9Sstevel@tonic-gate 
67417c478bd9Sstevel@tonic-gate 		if (tTd(38, 3))
67427c478bd9Sstevel@tonic-gate 			sm_dprintf("regex_map_init: nr of substrings %d\n",
67437c478bd9Sstevel@tonic-gate 				substrings);
67447c478bd9Sstevel@tonic-gate 
67457c478bd9Sstevel@tonic-gate 		if (substrings >= MAX_MATCH)
67467c478bd9Sstevel@tonic-gate 		{
67477c478bd9Sstevel@tonic-gate 			syserr("too many substrings, %d max", MAX_MATCH);
67487c478bd9Sstevel@tonic-gate 			sm_free(map_p->regex_pattern_buf); /* XXX */
67497c478bd9Sstevel@tonic-gate 			sm_free(map_p); /* XXX */
67507c478bd9Sstevel@tonic-gate 			return false;
67517c478bd9Sstevel@tonic-gate 		}
67527c478bd9Sstevel@tonic-gate 		if (sub_param != NULL && sub_param[0] != '\0')
67537c478bd9Sstevel@tonic-gate 		{
67547c478bd9Sstevel@tonic-gate 			/* optional parameter -sfields */
67557c478bd9Sstevel@tonic-gate 			if (parse_fields(sub_param, fields,
67567c478bd9Sstevel@tonic-gate 					 MAX_MATCH + 1, substrings) == -1)
67577c478bd9Sstevel@tonic-gate 				return false;
67587c478bd9Sstevel@tonic-gate 		}
67597c478bd9Sstevel@tonic-gate 		else
67607c478bd9Sstevel@tonic-gate 		{
67617c478bd9Sstevel@tonic-gate 			int i;
67627c478bd9Sstevel@tonic-gate 
67637c478bd9Sstevel@tonic-gate 			/* set default fields */
67647c478bd9Sstevel@tonic-gate 			for (i = 0; i < substrings; i++)
67657c478bd9Sstevel@tonic-gate 				fields[i] = i;
67667c478bd9Sstevel@tonic-gate 			fields[i] = END_OF_FIELDS;
67677c478bd9Sstevel@tonic-gate 		}
67687c478bd9Sstevel@tonic-gate 		map_p->regex_subfields = fields;
67697c478bd9Sstevel@tonic-gate 		if (tTd(38, 3))
67707c478bd9Sstevel@tonic-gate 		{
67717c478bd9Sstevel@tonic-gate 			int *ip;
67727c478bd9Sstevel@tonic-gate 
67737c478bd9Sstevel@tonic-gate 			sm_dprintf("regex_map_init: subfields");
67747c478bd9Sstevel@tonic-gate 			for (ip = fields; *ip != END_OF_FIELDS; ip++)
67757c478bd9Sstevel@tonic-gate 				sm_dprintf(" %d", *ip);
67767c478bd9Sstevel@tonic-gate 			sm_dprintf("\n");
67777c478bd9Sstevel@tonic-gate 		}
67787c478bd9Sstevel@tonic-gate 	}
67797c478bd9Sstevel@tonic-gate 	map->map_db1 = (ARBPTR_T) map_p;	/* dirty hack */
67807c478bd9Sstevel@tonic-gate 	return true;
67817c478bd9Sstevel@tonic-gate }
67827c478bd9Sstevel@tonic-gate 
67837c478bd9Sstevel@tonic-gate static char *
67847c478bd9Sstevel@tonic-gate regex_map_rewrite(map, s, slen, av)
67857c478bd9Sstevel@tonic-gate 	MAP *map;
67867c478bd9Sstevel@tonic-gate 	const char *s;
67877c478bd9Sstevel@tonic-gate 	size_t slen;
67887c478bd9Sstevel@tonic-gate 	char **av;
67897c478bd9Sstevel@tonic-gate {
67907c478bd9Sstevel@tonic-gate 	if (bitset(MF_MATCHONLY, map->map_mflags))
67917c478bd9Sstevel@tonic-gate 		return map_rewrite(map, av[0], strlen(av[0]), NULL);
67927c478bd9Sstevel@tonic-gate 	else
67937c478bd9Sstevel@tonic-gate 		return map_rewrite(map, s, slen, av);
67947c478bd9Sstevel@tonic-gate }
67957c478bd9Sstevel@tonic-gate 
67967c478bd9Sstevel@tonic-gate char *
67977c478bd9Sstevel@tonic-gate regex_map_lookup(map, name, av, statp)
67987c478bd9Sstevel@tonic-gate 	MAP *map;
67997c478bd9Sstevel@tonic-gate 	char *name;
68007c478bd9Sstevel@tonic-gate 	char **av;
68017c478bd9Sstevel@tonic-gate 	int *statp;
68027c478bd9Sstevel@tonic-gate {
68037c478bd9Sstevel@tonic-gate 	int reg_res;
68047c478bd9Sstevel@tonic-gate 	struct regex_map *map_p;
68057c478bd9Sstevel@tonic-gate 	regmatch_t pmatch[MAX_MATCH];
68067c478bd9Sstevel@tonic-gate 
68077c478bd9Sstevel@tonic-gate 	if (tTd(38, 20))
68087c478bd9Sstevel@tonic-gate 	{
68097c478bd9Sstevel@tonic-gate 		char **cpp;
68107c478bd9Sstevel@tonic-gate 
68117c478bd9Sstevel@tonic-gate 		sm_dprintf("regex_map_lookup: key '%s'\n", name);
68127c478bd9Sstevel@tonic-gate 		for (cpp = av; cpp != NULL && *cpp != NULL; cpp++)
68137c478bd9Sstevel@tonic-gate 			sm_dprintf("regex_map_lookup: arg '%s'\n", *cpp);
68147c478bd9Sstevel@tonic-gate 	}
68157c478bd9Sstevel@tonic-gate 
68167c478bd9Sstevel@tonic-gate 	map_p = (struct regex_map *)(map->map_db1);
68177c478bd9Sstevel@tonic-gate 	reg_res = regexec(map_p->regex_pattern_buf,
68187c478bd9Sstevel@tonic-gate 			  name, MAX_MATCH, pmatch, 0);
68197c478bd9Sstevel@tonic-gate 
68207c478bd9Sstevel@tonic-gate 	if (bitset(MF_REGEX_NOT, map->map_mflags))
68217c478bd9Sstevel@tonic-gate 	{
68227c478bd9Sstevel@tonic-gate 		/* option -n */
68237c478bd9Sstevel@tonic-gate 		if (reg_res == REG_NOMATCH)
68247c478bd9Sstevel@tonic-gate 			return regex_map_rewrite(map, "", (size_t) 0, av);
68257c478bd9Sstevel@tonic-gate 		else
68267c478bd9Sstevel@tonic-gate 			return NULL;
68277c478bd9Sstevel@tonic-gate 	}
68287c478bd9Sstevel@tonic-gate 	if (reg_res == REG_NOMATCH)
68297c478bd9Sstevel@tonic-gate 		return NULL;
68307c478bd9Sstevel@tonic-gate 
68317c478bd9Sstevel@tonic-gate 	if (map_p->regex_subfields != NULL)
68327c478bd9Sstevel@tonic-gate 	{
68337c478bd9Sstevel@tonic-gate 		/* option -s */
68347c478bd9Sstevel@tonic-gate 		static char retbuf[MAXNAME];
68357c478bd9Sstevel@tonic-gate 		int fields[MAX_MATCH + 1];
68367c478bd9Sstevel@tonic-gate 		bool first = true;
68377c478bd9Sstevel@tonic-gate 		int anglecnt = 0, cmntcnt = 0, spacecnt = 0;
68387c478bd9Sstevel@tonic-gate 		bool quotemode = false, bslashmode = false;
68397c478bd9Sstevel@tonic-gate 		register char *dp, *sp;
68407c478bd9Sstevel@tonic-gate 		char *endp, *ldp;
68417c478bd9Sstevel@tonic-gate 		int *ip;
68427c478bd9Sstevel@tonic-gate 
68437c478bd9Sstevel@tonic-gate 		dp = retbuf;
68447c478bd9Sstevel@tonic-gate 		ldp = retbuf + sizeof(retbuf) - 1;
68457c478bd9Sstevel@tonic-gate 
68467c478bd9Sstevel@tonic-gate 		if (av[1] != NULL)
68477c478bd9Sstevel@tonic-gate 		{
68487c478bd9Sstevel@tonic-gate 			if (parse_fields(av[1], fields, MAX_MATCH + 1,
68497c478bd9Sstevel@tonic-gate 					 (int) map_p->regex_pattern_buf->re_nsub + 1) == -1)
68507c478bd9Sstevel@tonic-gate 			{
68517c478bd9Sstevel@tonic-gate 				*statp = EX_CONFIG;
68527c478bd9Sstevel@tonic-gate 				return NULL;
68537c478bd9Sstevel@tonic-gate 			}
68547c478bd9Sstevel@tonic-gate 			ip = fields;
68557c478bd9Sstevel@tonic-gate 		}
68567c478bd9Sstevel@tonic-gate 		else
68577c478bd9Sstevel@tonic-gate 			ip = map_p->regex_subfields;
68587c478bd9Sstevel@tonic-gate 
68597c478bd9Sstevel@tonic-gate 		for ( ; *ip != END_OF_FIELDS; ip++)
68607c478bd9Sstevel@tonic-gate 		{
68617c478bd9Sstevel@tonic-gate 			if (!first)
68627c478bd9Sstevel@tonic-gate 			{
68637c478bd9Sstevel@tonic-gate 				for (sp = map_p->regex_delim; *sp; sp++)
68647c478bd9Sstevel@tonic-gate 				{
68657c478bd9Sstevel@tonic-gate 					if (dp < ldp)
68667c478bd9Sstevel@tonic-gate 						*dp++ = *sp;
68677c478bd9Sstevel@tonic-gate 				}
68687c478bd9Sstevel@tonic-gate 			}
68697c478bd9Sstevel@tonic-gate 			else
68707c478bd9Sstevel@tonic-gate 				first = false;
68717c478bd9Sstevel@tonic-gate 
68727c478bd9Sstevel@tonic-gate 			if (*ip >= MAX_MATCH ||
68737c478bd9Sstevel@tonic-gate 			    pmatch[*ip].rm_so < 0 || pmatch[*ip].rm_eo < 0)
68747c478bd9Sstevel@tonic-gate 				continue;
68757c478bd9Sstevel@tonic-gate 
68767c478bd9Sstevel@tonic-gate 			sp = name + pmatch[*ip].rm_so;
68777c478bd9Sstevel@tonic-gate 			endp = name + pmatch[*ip].rm_eo;
68787c478bd9Sstevel@tonic-gate 			for (; endp > sp; sp++)
68797c478bd9Sstevel@tonic-gate 			{
68807c478bd9Sstevel@tonic-gate 				if (dp < ldp)
68817c478bd9Sstevel@tonic-gate 				{
68827c478bd9Sstevel@tonic-gate 					if (bslashmode)
68837c478bd9Sstevel@tonic-gate 					{
68847c478bd9Sstevel@tonic-gate 						*dp++ = *sp;
68857c478bd9Sstevel@tonic-gate 						bslashmode = false;
68867c478bd9Sstevel@tonic-gate 					}
68877c478bd9Sstevel@tonic-gate 					else if (quotemode && *sp != '"' &&
68887c478bd9Sstevel@tonic-gate 						*sp != '\\')
68897c478bd9Sstevel@tonic-gate 					{
68907c478bd9Sstevel@tonic-gate 						*dp++ = *sp;
68917c478bd9Sstevel@tonic-gate 					}
68927c478bd9Sstevel@tonic-gate 					else switch (*dp++ = *sp)
68937c478bd9Sstevel@tonic-gate 					{
68947c478bd9Sstevel@tonic-gate 					  case '\\':
68957c478bd9Sstevel@tonic-gate 						bslashmode = true;
68967c478bd9Sstevel@tonic-gate 						break;
68977c478bd9Sstevel@tonic-gate 
68987c478bd9Sstevel@tonic-gate 					  case '(':
68997c478bd9Sstevel@tonic-gate 						cmntcnt++;
69007c478bd9Sstevel@tonic-gate 						break;
69017c478bd9Sstevel@tonic-gate 
69027c478bd9Sstevel@tonic-gate 					  case ')':
69037c478bd9Sstevel@tonic-gate 						cmntcnt--;
69047c478bd9Sstevel@tonic-gate 						break;
69057c478bd9Sstevel@tonic-gate 
69067c478bd9Sstevel@tonic-gate 					  case '<':
69077c478bd9Sstevel@tonic-gate 						anglecnt++;
69087c478bd9Sstevel@tonic-gate 						break;
69097c478bd9Sstevel@tonic-gate 
69107c478bd9Sstevel@tonic-gate 					  case '>':
69117c478bd9Sstevel@tonic-gate 						anglecnt--;
69127c478bd9Sstevel@tonic-gate 						break;
69137c478bd9Sstevel@tonic-gate 
69147c478bd9Sstevel@tonic-gate 					  case ' ':
69157c478bd9Sstevel@tonic-gate 						spacecnt++;
69167c478bd9Sstevel@tonic-gate 						break;
69177c478bd9Sstevel@tonic-gate 
69187c478bd9Sstevel@tonic-gate 					  case '"':
69197c478bd9Sstevel@tonic-gate 						quotemode = !quotemode;
69207c478bd9Sstevel@tonic-gate 						break;
69217c478bd9Sstevel@tonic-gate 					}
69227c478bd9Sstevel@tonic-gate 				}
69237c478bd9Sstevel@tonic-gate 			}
69247c478bd9Sstevel@tonic-gate 		}
69257c478bd9Sstevel@tonic-gate 		if (anglecnt != 0 || cmntcnt != 0 || quotemode ||
69267c478bd9Sstevel@tonic-gate 		    bslashmode || spacecnt != 0)
69277c478bd9Sstevel@tonic-gate 		{
69287c478bd9Sstevel@tonic-gate 			sm_syslog(LOG_WARNING, NOQID,
69297c478bd9Sstevel@tonic-gate 				  "Warning: regex may cause prescan() failure map=%s lookup=%s",
69307c478bd9Sstevel@tonic-gate 				  map->map_mname, name);
69317c478bd9Sstevel@tonic-gate 			return NULL;
69327c478bd9Sstevel@tonic-gate 		}
69337c478bd9Sstevel@tonic-gate 
69347c478bd9Sstevel@tonic-gate 		*dp = '\0';
69357c478bd9Sstevel@tonic-gate 
69367c478bd9Sstevel@tonic-gate 		return regex_map_rewrite(map, retbuf, strlen(retbuf), av);
69377c478bd9Sstevel@tonic-gate 	}
69387c478bd9Sstevel@tonic-gate 	return regex_map_rewrite(map, "", (size_t)0, av);
69397c478bd9Sstevel@tonic-gate }
69407c478bd9Sstevel@tonic-gate #endif /* MAP_REGEX */
69417c478bd9Sstevel@tonic-gate /*
69427c478bd9Sstevel@tonic-gate **  NSD modules
69437c478bd9Sstevel@tonic-gate */
69447c478bd9Sstevel@tonic-gate #if MAP_NSD
69457c478bd9Sstevel@tonic-gate 
69467c478bd9Sstevel@tonic-gate # include <ndbm.h>
69477c478bd9Sstevel@tonic-gate # define _DATUM_DEFINED
69487c478bd9Sstevel@tonic-gate # include <ns_api.h>
69497c478bd9Sstevel@tonic-gate 
69507c478bd9Sstevel@tonic-gate typedef struct ns_map_list
69517c478bd9Sstevel@tonic-gate {
69527c478bd9Sstevel@tonic-gate 	ns_map_t		*map;		/* XXX ns_ ? */
69537c478bd9Sstevel@tonic-gate 	char			*mapname;
69547c478bd9Sstevel@tonic-gate 	struct ns_map_list	*next;
69557c478bd9Sstevel@tonic-gate } ns_map_list_t;
69567c478bd9Sstevel@tonic-gate 
69577c478bd9Sstevel@tonic-gate static ns_map_t *
69587c478bd9Sstevel@tonic-gate ns_map_t_find(mapname)
69597c478bd9Sstevel@tonic-gate 	char *mapname;
69607c478bd9Sstevel@tonic-gate {
69617c478bd9Sstevel@tonic-gate 	static ns_map_list_t *ns_maps = NULL;
69627c478bd9Sstevel@tonic-gate 	ns_map_list_t *ns_map;
69637c478bd9Sstevel@tonic-gate 
69647c478bd9Sstevel@tonic-gate 	/* walk the list of maps looking for the correctly named map */
69657c478bd9Sstevel@tonic-gate 	for (ns_map = ns_maps; ns_map != NULL; ns_map = ns_map->next)
69667c478bd9Sstevel@tonic-gate 	{
69677c478bd9Sstevel@tonic-gate 		if (strcmp(ns_map->mapname, mapname) == 0)
69687c478bd9Sstevel@tonic-gate 			break;
69697c478bd9Sstevel@tonic-gate 	}
69707c478bd9Sstevel@tonic-gate 
69717c478bd9Sstevel@tonic-gate 	/* if we are looking at a NULL ns_map_list_t, then create a new one */
69727c478bd9Sstevel@tonic-gate 	if (ns_map == NULL)
69737c478bd9Sstevel@tonic-gate 	{
69747c478bd9Sstevel@tonic-gate 		ns_map = (ns_map_list_t *) xalloc(sizeof *ns_map);
69757c478bd9Sstevel@tonic-gate 		ns_map->mapname = newstr(mapname);
69767c478bd9Sstevel@tonic-gate 		ns_map->map = (ns_map_t *) xalloc(sizeof *ns_map->map);
69777c478bd9Sstevel@tonic-gate 		memset(ns_map->map, '\0', sizeof *ns_map->map);
69787c478bd9Sstevel@tonic-gate 		ns_map->next = ns_maps;
69797c478bd9Sstevel@tonic-gate 		ns_maps = ns_map;
69807c478bd9Sstevel@tonic-gate 	}
69817c478bd9Sstevel@tonic-gate 	return ns_map->map;
69827c478bd9Sstevel@tonic-gate }
69837c478bd9Sstevel@tonic-gate 
69847c478bd9Sstevel@tonic-gate char *
69857c478bd9Sstevel@tonic-gate nsd_map_lookup(map, name, av, statp)
69867c478bd9Sstevel@tonic-gate 	MAP *map;
69877c478bd9Sstevel@tonic-gate 	char *name;
69887c478bd9Sstevel@tonic-gate 	char **av;
69897c478bd9Sstevel@tonic-gate 	int *statp;
69907c478bd9Sstevel@tonic-gate {
69917c478bd9Sstevel@tonic-gate 	int buflen, r;
69927c478bd9Sstevel@tonic-gate 	char *p;
69937c478bd9Sstevel@tonic-gate 	ns_map_t *ns_map;
69947c478bd9Sstevel@tonic-gate 	char keybuf[MAXNAME + 1];
69957c478bd9Sstevel@tonic-gate 	char buf[MAXLINE];
69967c478bd9Sstevel@tonic-gate 
69977c478bd9Sstevel@tonic-gate 	if (tTd(38, 20))
69987c478bd9Sstevel@tonic-gate 		sm_dprintf("nsd_map_lookup(%s, %s)\n", map->map_mname, name);
69997c478bd9Sstevel@tonic-gate 
70007c478bd9Sstevel@tonic-gate 	buflen = strlen(name);
70017c478bd9Sstevel@tonic-gate 	if (buflen > sizeof keybuf - 1)
70027c478bd9Sstevel@tonic-gate 		buflen = sizeof keybuf - 1;	/* XXX simply cut off? */
70037c478bd9Sstevel@tonic-gate 	memmove(keybuf, name, buflen);
70047c478bd9Sstevel@tonic-gate 	keybuf[buflen] = '\0';
70057c478bd9Sstevel@tonic-gate 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
70067c478bd9Sstevel@tonic-gate 		makelower(keybuf);
70077c478bd9Sstevel@tonic-gate 
70087c478bd9Sstevel@tonic-gate 	ns_map = ns_map_t_find(map->map_file);
70097c478bd9Sstevel@tonic-gate 	if (ns_map == NULL)
70107c478bd9Sstevel@tonic-gate 	{
70117c478bd9Sstevel@tonic-gate 		if (tTd(38, 20))
70127c478bd9Sstevel@tonic-gate 			sm_dprintf("nsd_map_t_find failed\n");
70137c478bd9Sstevel@tonic-gate 		*statp = EX_UNAVAILABLE;
70147c478bd9Sstevel@tonic-gate 		return NULL;
70157c478bd9Sstevel@tonic-gate 	}
70167c478bd9Sstevel@tonic-gate 	r = ns_lookup(ns_map, NULL, map->map_file, keybuf, NULL,
70177c478bd9Sstevel@tonic-gate 		      buf, sizeof buf);
70187c478bd9Sstevel@tonic-gate 	if (r == NS_UNAVAIL || r == NS_TRYAGAIN)
70197c478bd9Sstevel@tonic-gate 	{
70207c478bd9Sstevel@tonic-gate 		*statp = EX_TEMPFAIL;
70217c478bd9Sstevel@tonic-gate 		return NULL;
70227c478bd9Sstevel@tonic-gate 	}
70237c478bd9Sstevel@tonic-gate 	if (r == NS_BADREQ
70247c478bd9Sstevel@tonic-gate # ifdef NS_NOPERM
70257c478bd9Sstevel@tonic-gate 	    || r == NS_NOPERM
70267c478bd9Sstevel@tonic-gate # endif /* NS_NOPERM */
70277c478bd9Sstevel@tonic-gate 	    )
70287c478bd9Sstevel@tonic-gate 	{
70297c478bd9Sstevel@tonic-gate 		*statp = EX_CONFIG;
70307c478bd9Sstevel@tonic-gate 		return NULL;
70317c478bd9Sstevel@tonic-gate 	}
70327c478bd9Sstevel@tonic-gate 	if (r != NS_SUCCESS)
70337c478bd9Sstevel@tonic-gate 	{
70347c478bd9Sstevel@tonic-gate 		*statp = EX_NOTFOUND;
70357c478bd9Sstevel@tonic-gate 		return NULL;
70367c478bd9Sstevel@tonic-gate 	}
70377c478bd9Sstevel@tonic-gate 
70387c478bd9Sstevel@tonic-gate 	*statp = EX_OK;
70397c478bd9Sstevel@tonic-gate 
70407c478bd9Sstevel@tonic-gate 	/* Null out trailing \n */
70417c478bd9Sstevel@tonic-gate 	if ((p = strchr(buf, '\n')) != NULL)
70427c478bd9Sstevel@tonic-gate 		*p = '\0';
70437c478bd9Sstevel@tonic-gate 
70447c478bd9Sstevel@tonic-gate 	return map_rewrite(map, buf, strlen(buf), av);
70457c478bd9Sstevel@tonic-gate }
70467c478bd9Sstevel@tonic-gate #endif /* MAP_NSD */
70477c478bd9Sstevel@tonic-gate 
70487c478bd9Sstevel@tonic-gate char *
70497c478bd9Sstevel@tonic-gate arith_map_lookup(map, name, av, statp)
70507c478bd9Sstevel@tonic-gate 	MAP *map;
70517c478bd9Sstevel@tonic-gate 	char *name;
70527c478bd9Sstevel@tonic-gate 	char **av;
70537c478bd9Sstevel@tonic-gate 	int *statp;
70547c478bd9Sstevel@tonic-gate {
70557c478bd9Sstevel@tonic-gate 	long r;
70567c478bd9Sstevel@tonic-gate 	long v[2];
70577c478bd9Sstevel@tonic-gate 	bool res = false;
70587c478bd9Sstevel@tonic-gate 	bool boolres;
70597c478bd9Sstevel@tonic-gate 	static char result[16];
70607c478bd9Sstevel@tonic-gate 	char **cpp;
70617c478bd9Sstevel@tonic-gate 
70627c478bd9Sstevel@tonic-gate 	if (tTd(38, 2))
70637c478bd9Sstevel@tonic-gate 	{
70647c478bd9Sstevel@tonic-gate 		sm_dprintf("arith_map_lookup: key '%s'\n", name);
70657c478bd9Sstevel@tonic-gate 		for (cpp = av; cpp != NULL && *cpp != NULL; cpp++)
70667c478bd9Sstevel@tonic-gate 			sm_dprintf("arith_map_lookup: arg '%s'\n", *cpp);
70677c478bd9Sstevel@tonic-gate 	}
70687c478bd9Sstevel@tonic-gate 	r = 0;
70697c478bd9Sstevel@tonic-gate 	boolres = false;
70707c478bd9Sstevel@tonic-gate 	cpp = av;
70717c478bd9Sstevel@tonic-gate 	*statp = EX_OK;
70727c478bd9Sstevel@tonic-gate 
70737c478bd9Sstevel@tonic-gate 	/*
70747c478bd9Sstevel@tonic-gate 	**  read arguments for arith map
70757c478bd9Sstevel@tonic-gate 	**  - no check is made whether they are really numbers
70767c478bd9Sstevel@tonic-gate 	**  - just ignores args after the second
70777c478bd9Sstevel@tonic-gate 	*/
70787c478bd9Sstevel@tonic-gate 
70797c478bd9Sstevel@tonic-gate 	for (++cpp; cpp != NULL && *cpp != NULL && r < 2; cpp++)
70807c478bd9Sstevel@tonic-gate 		v[r++] = strtol(*cpp, NULL, 0);
70817c478bd9Sstevel@tonic-gate 
70827c478bd9Sstevel@tonic-gate 	/* operator and (at least) two operands given? */
70837c478bd9Sstevel@tonic-gate 	if (name != NULL && r == 2)
70847c478bd9Sstevel@tonic-gate 	{
70857c478bd9Sstevel@tonic-gate 		switch (*name)
70867c478bd9Sstevel@tonic-gate 		{
70877c478bd9Sstevel@tonic-gate 		  case '|':
70887c478bd9Sstevel@tonic-gate 			r = v[0] | v[1];
70897c478bd9Sstevel@tonic-gate 			break;
70907c478bd9Sstevel@tonic-gate 
70917c478bd9Sstevel@tonic-gate 		  case '&':
70927c478bd9Sstevel@tonic-gate 			r = v[0] & v[1];
70937c478bd9Sstevel@tonic-gate 			break;
70947c478bd9Sstevel@tonic-gate 
70957c478bd9Sstevel@tonic-gate 		  case '%':
70967c478bd9Sstevel@tonic-gate 			if (v[1] == 0)
70977c478bd9Sstevel@tonic-gate 				return NULL;
70987c478bd9Sstevel@tonic-gate 			r = v[0] % v[1];
70997c478bd9Sstevel@tonic-gate 			break;
71007c478bd9Sstevel@tonic-gate 		  case '+':
71017c478bd9Sstevel@tonic-gate 			r = v[0] + v[1];
71027c478bd9Sstevel@tonic-gate 			break;
71037c478bd9Sstevel@tonic-gate 
71047c478bd9Sstevel@tonic-gate 		  case '-':
71057c478bd9Sstevel@tonic-gate 			r = v[0] - v[1];
71067c478bd9Sstevel@tonic-gate 			break;
71077c478bd9Sstevel@tonic-gate 
71087c478bd9Sstevel@tonic-gate 		  case '*':
71097c478bd9Sstevel@tonic-gate 			r = v[0] * v[1];
71107c478bd9Sstevel@tonic-gate 			break;
71117c478bd9Sstevel@tonic-gate 
71127c478bd9Sstevel@tonic-gate 		  case '/':
71137c478bd9Sstevel@tonic-gate 			if (v[1] == 0)
71147c478bd9Sstevel@tonic-gate 				return NULL;
71157c478bd9Sstevel@tonic-gate 			r = v[0] / v[1];
71167c478bd9Sstevel@tonic-gate 			break;
71177c478bd9Sstevel@tonic-gate 
71187c478bd9Sstevel@tonic-gate 		  case 'l':
71197c478bd9Sstevel@tonic-gate 			res = v[0] < v[1];
71207c478bd9Sstevel@tonic-gate 			boolres = true;
71217c478bd9Sstevel@tonic-gate 			break;
71227c478bd9Sstevel@tonic-gate 
71237c478bd9Sstevel@tonic-gate 		  case '=':
71247c478bd9Sstevel@tonic-gate 			res = v[0] == v[1];
71257c478bd9Sstevel@tonic-gate 			boolres = true;
71267c478bd9Sstevel@tonic-gate 			break;
71277c478bd9Sstevel@tonic-gate 
71287c478bd9Sstevel@tonic-gate 		  default:
71297c478bd9Sstevel@tonic-gate 			/* XXX */
71307c478bd9Sstevel@tonic-gate 			*statp = EX_CONFIG;
71317c478bd9Sstevel@tonic-gate 			if (LogLevel > 10)
71327c478bd9Sstevel@tonic-gate 				sm_syslog(LOG_WARNING, NOQID,
71337c478bd9Sstevel@tonic-gate 					  "arith_map: unknown operator %c",
71347c478bd9Sstevel@tonic-gate 					  isprint(*name) ? *name : '?');
71357c478bd9Sstevel@tonic-gate 			return NULL;
71367c478bd9Sstevel@tonic-gate 		}
71377c478bd9Sstevel@tonic-gate 		if (boolres)
71387c478bd9Sstevel@tonic-gate 			(void) sm_snprintf(result, sizeof result,
71397c478bd9Sstevel@tonic-gate 				res ? "TRUE" : "FALSE");
71407c478bd9Sstevel@tonic-gate 		else
71417c478bd9Sstevel@tonic-gate 			(void) sm_snprintf(result, sizeof result, "%ld", r);
71427c478bd9Sstevel@tonic-gate 		return result;
71437c478bd9Sstevel@tonic-gate 	}
71447c478bd9Sstevel@tonic-gate 	*statp = EX_CONFIG;
71457c478bd9Sstevel@tonic-gate 	return NULL;
71467c478bd9Sstevel@tonic-gate }
71477c478bd9Sstevel@tonic-gate 
71487c478bd9Sstevel@tonic-gate #if SOCKETMAP
71497c478bd9Sstevel@tonic-gate 
71507c478bd9Sstevel@tonic-gate # if NETINET || NETINET6
71517c478bd9Sstevel@tonic-gate #  include <arpa/inet.h>
71527c478bd9Sstevel@tonic-gate # endif /* NETINET || NETINET6 */
71537c478bd9Sstevel@tonic-gate 
71547c478bd9Sstevel@tonic-gate # define socket_map_next map_stack[0]
71557c478bd9Sstevel@tonic-gate 
71567c478bd9Sstevel@tonic-gate /*
71577c478bd9Sstevel@tonic-gate **  SOCKET_MAP_OPEN -- open socket table
71587c478bd9Sstevel@tonic-gate */
71597c478bd9Sstevel@tonic-gate 
71607c478bd9Sstevel@tonic-gate bool
71617c478bd9Sstevel@tonic-gate socket_map_open(map, mode)
71627c478bd9Sstevel@tonic-gate 	MAP *map;
71637c478bd9Sstevel@tonic-gate 	int mode;
71647c478bd9Sstevel@tonic-gate {
71657c478bd9Sstevel@tonic-gate 	STAB *s;
71667c478bd9Sstevel@tonic-gate 	int sock = 0;
71677c478bd9Sstevel@tonic-gate 	SOCKADDR_LEN_T addrlen = 0;
71687c478bd9Sstevel@tonic-gate 	int addrno = 0;
71697c478bd9Sstevel@tonic-gate 	int save_errno;
71707c478bd9Sstevel@tonic-gate 	char *p;
71717c478bd9Sstevel@tonic-gate 	char *colon;
71727c478bd9Sstevel@tonic-gate 	char *at;
71737c478bd9Sstevel@tonic-gate 	struct hostent *hp = NULL;
71747c478bd9Sstevel@tonic-gate 	SOCKADDR addr;
71757c478bd9Sstevel@tonic-gate 
71767c478bd9Sstevel@tonic-gate 	if (tTd(38, 2))
71777c478bd9Sstevel@tonic-gate 		sm_dprintf("socket_map_open(%s, %s, %d)\n",
71787c478bd9Sstevel@tonic-gate 			map->map_mname, map->map_file, mode);
71797c478bd9Sstevel@tonic-gate 
71807c478bd9Sstevel@tonic-gate 	mode &= O_ACCMODE;
71817c478bd9Sstevel@tonic-gate 
71827c478bd9Sstevel@tonic-gate 	/* sendmail doesn't have the ability to write to SOCKET (yet) */
71837c478bd9Sstevel@tonic-gate 	if (mode != O_RDONLY)
71847c478bd9Sstevel@tonic-gate 	{
71857c478bd9Sstevel@tonic-gate 		/* issue a pseudo-error message */
71867c478bd9Sstevel@tonic-gate 		errno = SM_EMAPCANTWRITE;
71877c478bd9Sstevel@tonic-gate 		return false;
71887c478bd9Sstevel@tonic-gate 	}
71897c478bd9Sstevel@tonic-gate 
71907c478bd9Sstevel@tonic-gate 	if (*map->map_file == '\0')
71917c478bd9Sstevel@tonic-gate 	{
71927c478bd9Sstevel@tonic-gate 		syserr("socket map \"%s\": empty or missing socket information",
71937c478bd9Sstevel@tonic-gate 			map->map_mname);
71947c478bd9Sstevel@tonic-gate 		return false;
71957c478bd9Sstevel@tonic-gate 	}
71967c478bd9Sstevel@tonic-gate 
71977c478bd9Sstevel@tonic-gate 	s = socket_map_findconn(map->map_file);
71987c478bd9Sstevel@tonic-gate 	if (s->s_socketmap != NULL)
71997c478bd9Sstevel@tonic-gate 	{
72007c478bd9Sstevel@tonic-gate 		/* Copy open connection */
72017c478bd9Sstevel@tonic-gate 		map->map_db1 = s->s_socketmap->map_db1;
72027c478bd9Sstevel@tonic-gate 
72037c478bd9Sstevel@tonic-gate 		/* Add this map as head of linked list */
72047c478bd9Sstevel@tonic-gate 		map->socket_map_next = s->s_socketmap;
72057c478bd9Sstevel@tonic-gate 		s->s_socketmap = map;
72067c478bd9Sstevel@tonic-gate 
72077c478bd9Sstevel@tonic-gate 		if (tTd(38, 2))
72087c478bd9Sstevel@tonic-gate 			sm_dprintf("using cached connection\n");
72097c478bd9Sstevel@tonic-gate 		return true;
72107c478bd9Sstevel@tonic-gate 	}
72117c478bd9Sstevel@tonic-gate 
72127c478bd9Sstevel@tonic-gate 	if (tTd(38, 2))
72137c478bd9Sstevel@tonic-gate 		sm_dprintf("opening new connection\n");
72147c478bd9Sstevel@tonic-gate 
72157c478bd9Sstevel@tonic-gate 	/* following code is ripped from milter.c */
72167c478bd9Sstevel@tonic-gate 	/* XXX It should be put in a library... */
72177c478bd9Sstevel@tonic-gate 
72187c478bd9Sstevel@tonic-gate 	/* protocol:filename or protocol:port@host */
72197c478bd9Sstevel@tonic-gate 	memset(&addr, '\0', sizeof addr);
72207c478bd9Sstevel@tonic-gate 	p = map->map_file;
72217c478bd9Sstevel@tonic-gate 	colon = strchr(p, ':');
72227c478bd9Sstevel@tonic-gate 	if (colon != NULL)
72237c478bd9Sstevel@tonic-gate 	{
72247c478bd9Sstevel@tonic-gate 		*colon = '\0';
72257c478bd9Sstevel@tonic-gate 
72267c478bd9Sstevel@tonic-gate 		if (*p == '\0')
72277c478bd9Sstevel@tonic-gate 		{
72287c478bd9Sstevel@tonic-gate # if NETUNIX
72297c478bd9Sstevel@tonic-gate 			/* default to AF_UNIX */
72307c478bd9Sstevel@tonic-gate 			addr.sa.sa_family = AF_UNIX;
72317c478bd9Sstevel@tonic-gate # else /* NETUNIX */
72327c478bd9Sstevel@tonic-gate #  if NETINET
72337c478bd9Sstevel@tonic-gate 			/* default to AF_INET */
72347c478bd9Sstevel@tonic-gate 			addr.sa.sa_family = AF_INET;
72357c478bd9Sstevel@tonic-gate #  else /* NETINET */
72367c478bd9Sstevel@tonic-gate #   if NETINET6
72377c478bd9Sstevel@tonic-gate 			/* default to AF_INET6 */
72387c478bd9Sstevel@tonic-gate 			addr.sa.sa_family = AF_INET6;
72397c478bd9Sstevel@tonic-gate #   else /* NETINET6 */
72407c478bd9Sstevel@tonic-gate 			/* no protocols available */
72417c478bd9Sstevel@tonic-gate 			syserr("socket map \"%s\": no valid socket protocols available",
72427c478bd9Sstevel@tonic-gate 			map->map_mname);
72437c478bd9Sstevel@tonic-gate 			return false;
72447c478bd9Sstevel@tonic-gate #   endif /* NETINET6 */
72457c478bd9Sstevel@tonic-gate #  endif /* NETINET */
72467c478bd9Sstevel@tonic-gate # endif /* NETUNIX */
72477c478bd9Sstevel@tonic-gate 		}
72487c478bd9Sstevel@tonic-gate # if NETUNIX
72497c478bd9Sstevel@tonic-gate 		else if (sm_strcasecmp(p, "unix") == 0 ||
72507c478bd9Sstevel@tonic-gate 			 sm_strcasecmp(p, "local") == 0)
72517c478bd9Sstevel@tonic-gate 			addr.sa.sa_family = AF_UNIX;
72527c478bd9Sstevel@tonic-gate # endif /* NETUNIX */
72537c478bd9Sstevel@tonic-gate # if NETINET
72547c478bd9Sstevel@tonic-gate 		else if (sm_strcasecmp(p, "inet") == 0)
72557c478bd9Sstevel@tonic-gate 			addr.sa.sa_family = AF_INET;
72567c478bd9Sstevel@tonic-gate # endif /* NETINET */
72577c478bd9Sstevel@tonic-gate # if NETINET6
72587c478bd9Sstevel@tonic-gate 		else if (sm_strcasecmp(p, "inet6") == 0)
72597c478bd9Sstevel@tonic-gate 			addr.sa.sa_family = AF_INET6;
72607c478bd9Sstevel@tonic-gate # endif /* NETINET6 */
72617c478bd9Sstevel@tonic-gate 		else
72627c478bd9Sstevel@tonic-gate 		{
72637c478bd9Sstevel@tonic-gate # ifdef EPROTONOSUPPORT
72647c478bd9Sstevel@tonic-gate 			errno = EPROTONOSUPPORT;
72657c478bd9Sstevel@tonic-gate # else /* EPROTONOSUPPORT */
72667c478bd9Sstevel@tonic-gate 			errno = EINVAL;
72677c478bd9Sstevel@tonic-gate # endif /* EPROTONOSUPPORT */
72687c478bd9Sstevel@tonic-gate 			syserr("socket map \"%s\": unknown socket type %s",
72697c478bd9Sstevel@tonic-gate 			       map->map_mname, p);
72707c478bd9Sstevel@tonic-gate 			return false;
72717c478bd9Sstevel@tonic-gate 		}
72727c478bd9Sstevel@tonic-gate 		*colon++ = ':';
72737c478bd9Sstevel@tonic-gate 	}
72747c478bd9Sstevel@tonic-gate 	else
72757c478bd9Sstevel@tonic-gate 	{
72767c478bd9Sstevel@tonic-gate 		colon = p;
72777c478bd9Sstevel@tonic-gate #if NETUNIX
72787c478bd9Sstevel@tonic-gate 		/* default to AF_UNIX */
72797c478bd9Sstevel@tonic-gate 		addr.sa.sa_family = AF_UNIX;
72807c478bd9Sstevel@tonic-gate #else /* NETUNIX */
72817c478bd9Sstevel@tonic-gate # if NETINET
72827c478bd9Sstevel@tonic-gate 		/* default to AF_INET */
72837c478bd9Sstevel@tonic-gate 		addr.sa.sa_family = AF_INET;
72847c478bd9Sstevel@tonic-gate # else /* NETINET */
72857c478bd9Sstevel@tonic-gate #  if NETINET6
72867c478bd9Sstevel@tonic-gate 		/* default to AF_INET6 */
72877c478bd9Sstevel@tonic-gate 		addr.sa.sa_family = AF_INET6;
72887c478bd9Sstevel@tonic-gate #  else /* NETINET6 */
72897c478bd9Sstevel@tonic-gate 		syserr("socket map \"%s\": unknown socket type %s",
72907c478bd9Sstevel@tonic-gate 		       map->map_mname, p);
72917c478bd9Sstevel@tonic-gate 		return false;
72927c478bd9Sstevel@tonic-gate #  endif /* NETINET6 */
72937c478bd9Sstevel@tonic-gate # endif /* NETINET */
72947c478bd9Sstevel@tonic-gate #endif /* NETUNIX */
72957c478bd9Sstevel@tonic-gate 	}
72967c478bd9Sstevel@tonic-gate 
72977c478bd9Sstevel@tonic-gate # if NETUNIX
72987c478bd9Sstevel@tonic-gate 	if (addr.sa.sa_family == AF_UNIX)
72997c478bd9Sstevel@tonic-gate 	{
73007c478bd9Sstevel@tonic-gate 		long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_EXECOK;
73017c478bd9Sstevel@tonic-gate 
73027c478bd9Sstevel@tonic-gate 		at = colon;
73037c478bd9Sstevel@tonic-gate 		if (strlen(colon) >= sizeof addr.sunix.sun_path)
73047c478bd9Sstevel@tonic-gate 		{
73057c478bd9Sstevel@tonic-gate 			syserr("socket map \"%s\": local socket name %s too long",
73067c478bd9Sstevel@tonic-gate 			       map->map_mname, colon);
73077c478bd9Sstevel@tonic-gate 			return false;
73087c478bd9Sstevel@tonic-gate 		}
73097c478bd9Sstevel@tonic-gate 		errno = safefile(colon, RunAsUid, RunAsGid, RunAsUserName, sff,
73107c478bd9Sstevel@tonic-gate 				 S_IRUSR|S_IWUSR, NULL);
73117c478bd9Sstevel@tonic-gate 
73127c478bd9Sstevel@tonic-gate 		if (errno != 0)
73137c478bd9Sstevel@tonic-gate 		{
73147c478bd9Sstevel@tonic-gate 			/* if not safe, don't create */
73157c478bd9Sstevel@tonic-gate 				syserr("socket map \"%s\": local socket name %s unsafe",
73167c478bd9Sstevel@tonic-gate 			       map->map_mname, colon);
73177c478bd9Sstevel@tonic-gate 			return false;
73187c478bd9Sstevel@tonic-gate 		}
73197c478bd9Sstevel@tonic-gate 
73207c478bd9Sstevel@tonic-gate 		(void) sm_strlcpy(addr.sunix.sun_path, colon,
73217c478bd9Sstevel@tonic-gate 			       sizeof addr.sunix.sun_path);
73227c478bd9Sstevel@tonic-gate 		addrlen = sizeof (struct sockaddr_un);
73237c478bd9Sstevel@tonic-gate 	}
73247c478bd9Sstevel@tonic-gate 	else
73257c478bd9Sstevel@tonic-gate # endif /* NETUNIX */
73267c478bd9Sstevel@tonic-gate # if NETINET || NETINET6
73277c478bd9Sstevel@tonic-gate 	if (false
73287c478bd9Sstevel@tonic-gate #  if NETINET
73297c478bd9Sstevel@tonic-gate 		 || addr.sa.sa_family == AF_INET
73307c478bd9Sstevel@tonic-gate #  endif /* NETINET */
73317c478bd9Sstevel@tonic-gate #  if NETINET6
73327c478bd9Sstevel@tonic-gate 		 || addr.sa.sa_family == AF_INET6
73337c478bd9Sstevel@tonic-gate #  endif /* NETINET6 */
73347c478bd9Sstevel@tonic-gate 		 )
73357c478bd9Sstevel@tonic-gate 	{
73367c478bd9Sstevel@tonic-gate 		unsigned short port;
73377c478bd9Sstevel@tonic-gate 
73387c478bd9Sstevel@tonic-gate 		/* Parse port@host */
73397c478bd9Sstevel@tonic-gate 		at = strchr(colon, '@');
73407c478bd9Sstevel@tonic-gate 		if (at == NULL)
73417c478bd9Sstevel@tonic-gate 		{
73427c478bd9Sstevel@tonic-gate 			syserr("socket map \"%s\": bad address %s (expected port@host)",
73437c478bd9Sstevel@tonic-gate 				       map->map_mname, colon);
73447c478bd9Sstevel@tonic-gate 			return false;
73457c478bd9Sstevel@tonic-gate 		}
73467c478bd9Sstevel@tonic-gate 		*at = '\0';
73477c478bd9Sstevel@tonic-gate 		if (isascii(*colon) && isdigit(*colon))
73487c478bd9Sstevel@tonic-gate 			port = htons((unsigned short) atoi(colon));
73497c478bd9Sstevel@tonic-gate 		else
73507c478bd9Sstevel@tonic-gate 		{
73517c478bd9Sstevel@tonic-gate #  ifdef NO_GETSERVBYNAME
73527c478bd9Sstevel@tonic-gate 			syserr("socket map \"%s\": invalid port number %s",
73537c478bd9Sstevel@tonic-gate 				       map->map_mname, colon);
73547c478bd9Sstevel@tonic-gate 			return false;
73557c478bd9Sstevel@tonic-gate #  else /* NO_GETSERVBYNAME */
73567c478bd9Sstevel@tonic-gate 			register struct servent *sp;
73577c478bd9Sstevel@tonic-gate 
73587c478bd9Sstevel@tonic-gate 			sp = getservbyname(colon, "tcp");
73597c478bd9Sstevel@tonic-gate 			if (sp == NULL)
73607c478bd9Sstevel@tonic-gate 			{
73617c478bd9Sstevel@tonic-gate 				syserr("socket map \"%s\": unknown port name %s",
73627c478bd9Sstevel@tonic-gate 					       map->map_mname, colon);
73637c478bd9Sstevel@tonic-gate 				return false;
73647c478bd9Sstevel@tonic-gate 			}
73657c478bd9Sstevel@tonic-gate 			port = sp->s_port;
73667c478bd9Sstevel@tonic-gate #  endif /* NO_GETSERVBYNAME */
73677c478bd9Sstevel@tonic-gate 		}
73687c478bd9Sstevel@tonic-gate 		*at++ = '@';
73697c478bd9Sstevel@tonic-gate 		if (*at == '[')
73707c478bd9Sstevel@tonic-gate 		{
73717c478bd9Sstevel@tonic-gate 			char *end;
73727c478bd9Sstevel@tonic-gate 
73737c478bd9Sstevel@tonic-gate 			end = strchr(at, ']');
73747c478bd9Sstevel@tonic-gate 			if (end != NULL)
73757c478bd9Sstevel@tonic-gate 			{
73767c478bd9Sstevel@tonic-gate 				bool found = false;
73777c478bd9Sstevel@tonic-gate #  if NETINET
73787c478bd9Sstevel@tonic-gate 				unsigned long hid = INADDR_NONE;
73797c478bd9Sstevel@tonic-gate #  endif /* NETINET */
73807c478bd9Sstevel@tonic-gate #  if NETINET6
73817c478bd9Sstevel@tonic-gate 				struct sockaddr_in6 hid6;
73827c478bd9Sstevel@tonic-gate #  endif /* NETINET6 */
73837c478bd9Sstevel@tonic-gate 
73847c478bd9Sstevel@tonic-gate 				*end = '\0';
73857c478bd9Sstevel@tonic-gate #  if NETINET
73867c478bd9Sstevel@tonic-gate 				if (addr.sa.sa_family == AF_INET &&
73877c478bd9Sstevel@tonic-gate 				    (hid = inet_addr(&at[1])) != INADDR_NONE)
73887c478bd9Sstevel@tonic-gate 				{
73897c478bd9Sstevel@tonic-gate 					addr.sin.sin_addr.s_addr = hid;
73907c478bd9Sstevel@tonic-gate 					addr.sin.sin_port = port;
73917c478bd9Sstevel@tonic-gate 					found = true;
73927c478bd9Sstevel@tonic-gate 				}
73937c478bd9Sstevel@tonic-gate #  endif /* NETINET */
73947c478bd9Sstevel@tonic-gate #  if NETINET6
73957c478bd9Sstevel@tonic-gate 				(void) memset(&hid6, '\0', sizeof hid6);
73967c478bd9Sstevel@tonic-gate 				if (addr.sa.sa_family == AF_INET6 &&
73977c478bd9Sstevel@tonic-gate 				    anynet_pton(AF_INET6, &at[1],
73987c478bd9Sstevel@tonic-gate 						&hid6.sin6_addr) == 1)
73997c478bd9Sstevel@tonic-gate 				{
74007c478bd9Sstevel@tonic-gate 					addr.sin6.sin6_addr = hid6.sin6_addr;
74017c478bd9Sstevel@tonic-gate 					addr.sin6.sin6_port = port;
74027c478bd9Sstevel@tonic-gate 					found = true;
74037c478bd9Sstevel@tonic-gate 				}
74047c478bd9Sstevel@tonic-gate #  endif /* NETINET6 */
74057c478bd9Sstevel@tonic-gate 				*end = ']';
74067c478bd9Sstevel@tonic-gate 				if (!found)
74077c478bd9Sstevel@tonic-gate 				{
74087c478bd9Sstevel@tonic-gate 					syserr("socket map \"%s\": Invalid numeric domain spec \"%s\"",
74097c478bd9Sstevel@tonic-gate 					       map->map_mname, at);
74107c478bd9Sstevel@tonic-gate 					return false;
74117c478bd9Sstevel@tonic-gate 				}
74127c478bd9Sstevel@tonic-gate 			}
74137c478bd9Sstevel@tonic-gate 			else
74147c478bd9Sstevel@tonic-gate 			{
74157c478bd9Sstevel@tonic-gate 				syserr("socket map \"%s\": Invalid numeric domain spec \"%s\"",
74167c478bd9Sstevel@tonic-gate 				       map->map_mname, at);
74177c478bd9Sstevel@tonic-gate 				return false;
74187c478bd9Sstevel@tonic-gate 			}
74197c478bd9Sstevel@tonic-gate 		}
74207c478bd9Sstevel@tonic-gate 		else
74217c478bd9Sstevel@tonic-gate 		{
74227c478bd9Sstevel@tonic-gate 			hp = sm_gethostbyname(at, addr.sa.sa_family);
74237c478bd9Sstevel@tonic-gate 			if (hp == NULL)
74247c478bd9Sstevel@tonic-gate 			{
74257c478bd9Sstevel@tonic-gate 				syserr("socket map \"%s\": Unknown host name %s",
74267c478bd9Sstevel@tonic-gate 					map->map_mname, at);
74277c478bd9Sstevel@tonic-gate 				return false;
74287c478bd9Sstevel@tonic-gate 			}
74297c478bd9Sstevel@tonic-gate 			addr.sa.sa_family = hp->h_addrtype;
74307c478bd9Sstevel@tonic-gate 			switch (hp->h_addrtype)
74317c478bd9Sstevel@tonic-gate 			{
74327c478bd9Sstevel@tonic-gate #  if NETINET
74337c478bd9Sstevel@tonic-gate 			  case AF_INET:
74347c478bd9Sstevel@tonic-gate 				memmove(&addr.sin.sin_addr,
74357c478bd9Sstevel@tonic-gate 					hp->h_addr, INADDRSZ);
74367c478bd9Sstevel@tonic-gate 				addr.sin.sin_port = port;
74377c478bd9Sstevel@tonic-gate 				addrlen = sizeof (struct sockaddr_in);
74387c478bd9Sstevel@tonic-gate 				addrno = 1;
74397c478bd9Sstevel@tonic-gate 				break;
74407c478bd9Sstevel@tonic-gate #  endif /* NETINET */
74417c478bd9Sstevel@tonic-gate 
74427c478bd9Sstevel@tonic-gate #  if NETINET6
74437c478bd9Sstevel@tonic-gate 			  case AF_INET6:
74447c478bd9Sstevel@tonic-gate 				memmove(&addr.sin6.sin6_addr,
74457c478bd9Sstevel@tonic-gate 					hp->h_addr, IN6ADDRSZ);
74467c478bd9Sstevel@tonic-gate 				addr.sin6.sin6_port = port;
74477c478bd9Sstevel@tonic-gate 				addrlen = sizeof (struct sockaddr_in6);
74487c478bd9Sstevel@tonic-gate 				addrno = 1;
74497c478bd9Sstevel@tonic-gate 				break;
74507c478bd9Sstevel@tonic-gate #  endif /* NETINET6 */
74517c478bd9Sstevel@tonic-gate 
74527c478bd9Sstevel@tonic-gate 			  default:
74537c478bd9Sstevel@tonic-gate 				syserr("socket map \"%s\": Unknown protocol for %s (%d)",
74547c478bd9Sstevel@tonic-gate 					map->map_mname, at, hp->h_addrtype);
74557c478bd9Sstevel@tonic-gate #  if NETINET6
74567c478bd9Sstevel@tonic-gate 				freehostent(hp);
74577c478bd9Sstevel@tonic-gate #  endif /* NETINET6 */
74587c478bd9Sstevel@tonic-gate 				return false;
74597c478bd9Sstevel@tonic-gate 			}
74607c478bd9Sstevel@tonic-gate 		}
74617c478bd9Sstevel@tonic-gate 	}
74627c478bd9Sstevel@tonic-gate 	else
74637c478bd9Sstevel@tonic-gate # endif /* NETINET || NETINET6 */
74647c478bd9Sstevel@tonic-gate 	{
74657c478bd9Sstevel@tonic-gate 		syserr("socket map \"%s\": unknown socket protocol",
74667c478bd9Sstevel@tonic-gate 			map->map_mname);
74677c478bd9Sstevel@tonic-gate 		return false;
74687c478bd9Sstevel@tonic-gate 	}
74697c478bd9Sstevel@tonic-gate 
74707c478bd9Sstevel@tonic-gate 	/* nope, actually connecting */
74717c478bd9Sstevel@tonic-gate 	for (;;)
74727c478bd9Sstevel@tonic-gate 	{
74737c478bd9Sstevel@tonic-gate 		sock = socket(addr.sa.sa_family, SOCK_STREAM, 0);
74747c478bd9Sstevel@tonic-gate 		if (sock < 0)
74757c478bd9Sstevel@tonic-gate 		{
74767c478bd9Sstevel@tonic-gate 			save_errno = errno;
74777c478bd9Sstevel@tonic-gate 			if (tTd(38, 5))
74787c478bd9Sstevel@tonic-gate 				sm_dprintf("socket map \"%s\": error creating socket: %s\n",
74797c478bd9Sstevel@tonic-gate 					   map->map_mname,
74807c478bd9Sstevel@tonic-gate 					   sm_errstring(save_errno));
74817c478bd9Sstevel@tonic-gate # if NETINET6
74827c478bd9Sstevel@tonic-gate 			if (hp != NULL)
74837c478bd9Sstevel@tonic-gate 				freehostent(hp);
74847c478bd9Sstevel@tonic-gate # endif /* NETINET6 */
74857c478bd9Sstevel@tonic-gate 			return false;
74867c478bd9Sstevel@tonic-gate 		}
74877c478bd9Sstevel@tonic-gate 
74887c478bd9Sstevel@tonic-gate 		if (connect(sock, (struct sockaddr *) &addr, addrlen) >= 0)
74897c478bd9Sstevel@tonic-gate 			break;
74907c478bd9Sstevel@tonic-gate 
74917c478bd9Sstevel@tonic-gate 		/* couldn't connect.... try next address */
74927c478bd9Sstevel@tonic-gate 		save_errno = errno;
74937c478bd9Sstevel@tonic-gate 		p = CurHostName;
74947c478bd9Sstevel@tonic-gate 		CurHostName = at;
74957c478bd9Sstevel@tonic-gate 		if (tTd(38, 5))
74967c478bd9Sstevel@tonic-gate 			sm_dprintf("socket_open (%s): open %s failed: %s\n",
74977c478bd9Sstevel@tonic-gate 				map->map_mname, at, sm_errstring(save_errno));
74987c478bd9Sstevel@tonic-gate 		CurHostName = p;
74997c478bd9Sstevel@tonic-gate 		(void) close(sock);
75007c478bd9Sstevel@tonic-gate 
75017c478bd9Sstevel@tonic-gate 		/* try next address */
75027c478bd9Sstevel@tonic-gate 		if (hp != NULL && hp->h_addr_list[addrno] != NULL)
75037c478bd9Sstevel@tonic-gate 		{
75047c478bd9Sstevel@tonic-gate 			switch (addr.sa.sa_family)
75057c478bd9Sstevel@tonic-gate 			{
75067c478bd9Sstevel@tonic-gate # if NETINET
75077c478bd9Sstevel@tonic-gate 			  case AF_INET:
75087c478bd9Sstevel@tonic-gate 				memmove(&addr.sin.sin_addr,
75097c478bd9Sstevel@tonic-gate 					hp->h_addr_list[addrno++],
75107c478bd9Sstevel@tonic-gate 					INADDRSZ);
75117c478bd9Sstevel@tonic-gate 				break;
75127c478bd9Sstevel@tonic-gate # endif /* NETINET */
75137c478bd9Sstevel@tonic-gate 
75147c478bd9Sstevel@tonic-gate # if NETINET6
75157c478bd9Sstevel@tonic-gate 			  case AF_INET6:
75167c478bd9Sstevel@tonic-gate 				memmove(&addr.sin6.sin6_addr,
75177c478bd9Sstevel@tonic-gate 					hp->h_addr_list[addrno++],
75187c478bd9Sstevel@tonic-gate 					IN6ADDRSZ);
75197c478bd9Sstevel@tonic-gate 				break;
75207c478bd9Sstevel@tonic-gate # endif /* NETINET6 */
75217c478bd9Sstevel@tonic-gate 
75227c478bd9Sstevel@tonic-gate 			  default:
75237c478bd9Sstevel@tonic-gate 				if (tTd(38, 5))
75247c478bd9Sstevel@tonic-gate 					sm_dprintf("socket map \"%s\": Unknown protocol for %s (%d)\n",
75257c478bd9Sstevel@tonic-gate 						   map->map_mname, at,
75267c478bd9Sstevel@tonic-gate 						   hp->h_addrtype);
75277c478bd9Sstevel@tonic-gate # if NETINET6
75287c478bd9Sstevel@tonic-gate 				freehostent(hp);
75297c478bd9Sstevel@tonic-gate # endif /* NETINET6 */
75307c478bd9Sstevel@tonic-gate 				return false;
75317c478bd9Sstevel@tonic-gate 			}
75327c478bd9Sstevel@tonic-gate 			continue;
75337c478bd9Sstevel@tonic-gate 		}
75347c478bd9Sstevel@tonic-gate 		p = CurHostName;
75357c478bd9Sstevel@tonic-gate 		CurHostName = at;
75367c478bd9Sstevel@tonic-gate 		if (tTd(38, 5))
75377c478bd9Sstevel@tonic-gate 			sm_dprintf("socket map \"%s\": error connecting to socket map: %s\n",
75387c478bd9Sstevel@tonic-gate 				   map->map_mname, sm_errstring(save_errno));
75397c478bd9Sstevel@tonic-gate 		CurHostName = p;
75407c478bd9Sstevel@tonic-gate # if NETINET6
75417c478bd9Sstevel@tonic-gate 		if (hp != NULL)
75427c478bd9Sstevel@tonic-gate 			freehostent(hp);
75437c478bd9Sstevel@tonic-gate # endif /* NETINET6 */
75447c478bd9Sstevel@tonic-gate 		return false;
75457c478bd9Sstevel@tonic-gate 	}
75467c478bd9Sstevel@tonic-gate # if NETINET6
75477c478bd9Sstevel@tonic-gate 	if (hp != NULL)
75487c478bd9Sstevel@tonic-gate 	{
75497c478bd9Sstevel@tonic-gate 		freehostent(hp);
75507c478bd9Sstevel@tonic-gate 		hp = NULL;
75517c478bd9Sstevel@tonic-gate 	}
75527c478bd9Sstevel@tonic-gate # endif /* NETINET6 */
75537c478bd9Sstevel@tonic-gate 	if ((map->map_db1 = (ARBPTR_T) sm_io_open(SmFtStdiofd,
75547c478bd9Sstevel@tonic-gate 						  SM_TIME_DEFAULT,
75557c478bd9Sstevel@tonic-gate 						  (void *) &sock,
75567c478bd9Sstevel@tonic-gate 						  SM_IO_RDWR,
75577c478bd9Sstevel@tonic-gate 						  NULL)) == NULL)
75587c478bd9Sstevel@tonic-gate 	{
75597c478bd9Sstevel@tonic-gate 		close(sock);
75607c478bd9Sstevel@tonic-gate 		if (tTd(38, 2))
75617c478bd9Sstevel@tonic-gate 		    sm_dprintf("socket_open (%s): failed to create stream: %s\n",
75627c478bd9Sstevel@tonic-gate 			       map->map_mname, sm_errstring(errno));
75637c478bd9Sstevel@tonic-gate 		return false;
75647c478bd9Sstevel@tonic-gate 	}
75657c478bd9Sstevel@tonic-gate 
75667c478bd9Sstevel@tonic-gate 	/* Save connection for reuse */
75677c478bd9Sstevel@tonic-gate 	s->s_socketmap = map;
75687c478bd9Sstevel@tonic-gate 	return true;
75697c478bd9Sstevel@tonic-gate }
75707c478bd9Sstevel@tonic-gate 
75717c478bd9Sstevel@tonic-gate /*
75727c478bd9Sstevel@tonic-gate **  SOCKET_MAP_FINDCONN -- find a SOCKET connection to the server
75737c478bd9Sstevel@tonic-gate **
75747c478bd9Sstevel@tonic-gate **	Cache SOCKET connections based on the connection specifier
75757c478bd9Sstevel@tonic-gate **	and PID so we don't have multiple connections open to
75767c478bd9Sstevel@tonic-gate **	the same server for different maps.  Need a separate connection
75777c478bd9Sstevel@tonic-gate **	per PID since a parent process may close the map before the
75787c478bd9Sstevel@tonic-gate **	child is done with it.
75797c478bd9Sstevel@tonic-gate **
75807c478bd9Sstevel@tonic-gate **	Parameters:
75817c478bd9Sstevel@tonic-gate **		conn -- SOCKET map connection specifier
75827c478bd9Sstevel@tonic-gate **
75837c478bd9Sstevel@tonic-gate **	Returns:
75847c478bd9Sstevel@tonic-gate **		Symbol table entry for the SOCKET connection.
75857c478bd9Sstevel@tonic-gate */
75867c478bd9Sstevel@tonic-gate 
75877c478bd9Sstevel@tonic-gate static STAB *
75887c478bd9Sstevel@tonic-gate socket_map_findconn(conn)
75897c478bd9Sstevel@tonic-gate 	const char *conn;
75907c478bd9Sstevel@tonic-gate {
75917c478bd9Sstevel@tonic-gate 	char *nbuf;
75927c478bd9Sstevel@tonic-gate 	STAB *SM_NONVOLATILE s = NULL;
75937c478bd9Sstevel@tonic-gate 
75947c478bd9Sstevel@tonic-gate 	nbuf = sm_stringf_x("%s%c%d", conn, CONDELSE, (int) CurrentPid);
75957c478bd9Sstevel@tonic-gate 	SM_TRY
75967c478bd9Sstevel@tonic-gate 		s = stab(nbuf, ST_SOCKETMAP, ST_ENTER);
75977c478bd9Sstevel@tonic-gate 	SM_FINALLY
75987c478bd9Sstevel@tonic-gate 		sm_free(nbuf);
75997c478bd9Sstevel@tonic-gate 	SM_END_TRY
76007c478bd9Sstevel@tonic-gate 	return s;
76017c478bd9Sstevel@tonic-gate }
76027c478bd9Sstevel@tonic-gate 
76037c478bd9Sstevel@tonic-gate /*
76047c478bd9Sstevel@tonic-gate **  SOCKET_MAP_CLOSE -- close the socket
76057c478bd9Sstevel@tonic-gate */
76067c478bd9Sstevel@tonic-gate 
76077c478bd9Sstevel@tonic-gate void
76087c478bd9Sstevel@tonic-gate socket_map_close(map)
76097c478bd9Sstevel@tonic-gate 	MAP *map;
76107c478bd9Sstevel@tonic-gate {
76117c478bd9Sstevel@tonic-gate 	STAB *s;
76127c478bd9Sstevel@tonic-gate 	MAP *smap;
76137c478bd9Sstevel@tonic-gate 
76147c478bd9Sstevel@tonic-gate 	if (tTd(38, 20))
76157c478bd9Sstevel@tonic-gate 		sm_dprintf("socket_map_close(%s), pid=%ld\n", map->map_file,
76167c478bd9Sstevel@tonic-gate 			(long) CurrentPid);
76177c478bd9Sstevel@tonic-gate 
76187c478bd9Sstevel@tonic-gate 	/* Check if already closed */
76197c478bd9Sstevel@tonic-gate 	if (map->map_db1 == NULL)
76207c478bd9Sstevel@tonic-gate 	{
76217c478bd9Sstevel@tonic-gate 		if (tTd(38, 20))
76227c478bd9Sstevel@tonic-gate 			sm_dprintf("socket_map_close(%s) already closed\n",
76237c478bd9Sstevel@tonic-gate 				map->map_file);
76247c478bd9Sstevel@tonic-gate 		return;
76257c478bd9Sstevel@tonic-gate 	}
76267c478bd9Sstevel@tonic-gate 	sm_io_close((SM_FILE_T *)map->map_db1, SM_TIME_DEFAULT);
76277c478bd9Sstevel@tonic-gate 
76287c478bd9Sstevel@tonic-gate 	/* Mark all the maps that share the connection as closed */
76297c478bd9Sstevel@tonic-gate 	s = socket_map_findconn(map->map_file);
76307c478bd9Sstevel@tonic-gate 	smap = s->s_socketmap;
76317c478bd9Sstevel@tonic-gate 	while (smap != NULL)
76327c478bd9Sstevel@tonic-gate 	{
76337c478bd9Sstevel@tonic-gate 		MAP *next;
76347c478bd9Sstevel@tonic-gate 
76357c478bd9Sstevel@tonic-gate 		if (tTd(38, 2) && smap != map)
76367c478bd9Sstevel@tonic-gate 			sm_dprintf("socket_map_close(%s): closed %s (shared SOCKET connection)\n",
76377c478bd9Sstevel@tonic-gate 				map->map_mname, smap->map_mname);
76387c478bd9Sstevel@tonic-gate 
76397c478bd9Sstevel@tonic-gate 		smap->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
76407c478bd9Sstevel@tonic-gate 		smap->map_db1 = NULL;
76417c478bd9Sstevel@tonic-gate 		next = smap->socket_map_next;
76427c478bd9Sstevel@tonic-gate 		smap->socket_map_next = NULL;
76437c478bd9Sstevel@tonic-gate 		smap = next;
76447c478bd9Sstevel@tonic-gate 	}
76457c478bd9Sstevel@tonic-gate 	s->s_socketmap = NULL;
76467c478bd9Sstevel@tonic-gate }
76477c478bd9Sstevel@tonic-gate 
76487c478bd9Sstevel@tonic-gate /*
76497c478bd9Sstevel@tonic-gate ** SOCKET_MAP_LOOKUP -- look up a datum in a SOCKET table
76507c478bd9Sstevel@tonic-gate */
76517c478bd9Sstevel@tonic-gate 
76527c478bd9Sstevel@tonic-gate char *
76537c478bd9Sstevel@tonic-gate socket_map_lookup(map, name, av, statp)
76547c478bd9Sstevel@tonic-gate 	MAP *map;
76557c478bd9Sstevel@tonic-gate 	char *name;
76567c478bd9Sstevel@tonic-gate 	char **av;
76577c478bd9Sstevel@tonic-gate 	int *statp;
76587c478bd9Sstevel@tonic-gate {
76597c478bd9Sstevel@tonic-gate 	unsigned int nettolen, replylen, recvlen;
76607c478bd9Sstevel@tonic-gate 	char *replybuf, *rval, *value, *status, *key;
76617c478bd9Sstevel@tonic-gate 	SM_FILE_T *f;
76627c478bd9Sstevel@tonic-gate 	char keybuf[MAXNAME + 1];
76637c478bd9Sstevel@tonic-gate 
76647c478bd9Sstevel@tonic-gate 	replybuf = NULL;
76657c478bd9Sstevel@tonic-gate 	rval = NULL;
76667c478bd9Sstevel@tonic-gate 	f = (SM_FILE_T *)map->map_db1;
76677c478bd9Sstevel@tonic-gate 	if (tTd(38, 20))
76687c478bd9Sstevel@tonic-gate 		sm_dprintf("socket_map_lookup(%s, %s) %s\n",
76697c478bd9Sstevel@tonic-gate 			map->map_mname, name, map->map_file);
76707c478bd9Sstevel@tonic-gate 
76717c478bd9Sstevel@tonic-gate 	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
76727c478bd9Sstevel@tonic-gate 	{
76737c478bd9Sstevel@tonic-gate 		nettolen = strlen(name);
76747c478bd9Sstevel@tonic-gate 		if (nettolen > sizeof keybuf - 1)
76757c478bd9Sstevel@tonic-gate 			nettolen = sizeof keybuf - 1;
76767c478bd9Sstevel@tonic-gate 		memmove(keybuf, name, nettolen);
76777c478bd9Sstevel@tonic-gate 		keybuf[nettolen] = '\0';
76787c478bd9Sstevel@tonic-gate 		makelower(keybuf);
76797c478bd9Sstevel@tonic-gate 		key = keybuf;
76807c478bd9Sstevel@tonic-gate 	}
76817c478bd9Sstevel@tonic-gate 	else
76827c478bd9Sstevel@tonic-gate 		key = name;
76837c478bd9Sstevel@tonic-gate 
76847c478bd9Sstevel@tonic-gate 	nettolen = strlen(map->map_mname) + 1 + strlen(key);
76857c478bd9Sstevel@tonic-gate 	SM_ASSERT(nettolen > strlen(map->map_mname));
76867c478bd9Sstevel@tonic-gate 	SM_ASSERT(nettolen > strlen(key));
76877c478bd9Sstevel@tonic-gate 	if ((sm_io_fprintf(f, SM_TIME_DEFAULT, "%u:%s %s,",
76887c478bd9Sstevel@tonic-gate 			   nettolen, map->map_mname, key) == SM_IO_EOF) ||
76897c478bd9Sstevel@tonic-gate 	    (sm_io_flush(f, SM_TIME_DEFAULT) != 0) ||
76907c478bd9Sstevel@tonic-gate 	    (sm_io_error(f)))
76917c478bd9Sstevel@tonic-gate 	{
76927c478bd9Sstevel@tonic-gate 		syserr("451 4.3.0 socket_map_lookup(%s): failed to send lookup request",
76937c478bd9Sstevel@tonic-gate 			map->map_mname);
76947c478bd9Sstevel@tonic-gate 		*statp = EX_TEMPFAIL;
76957c478bd9Sstevel@tonic-gate 		goto errcl;
76967c478bd9Sstevel@tonic-gate 	}
76977c478bd9Sstevel@tonic-gate 
76987c478bd9Sstevel@tonic-gate 	if (sm_io_fscanf(f, SM_TIME_DEFAULT, "%9u", &replylen) != 1)
76997c478bd9Sstevel@tonic-gate 	{
77007c478bd9Sstevel@tonic-gate 		syserr("451 4.3.0 socket_map_lookup(%s): failed to read length parameter of reply",
77017c478bd9Sstevel@tonic-gate 			map->map_mname);
77027c478bd9Sstevel@tonic-gate 		*statp = EX_TEMPFAIL;
77037c478bd9Sstevel@tonic-gate 		goto errcl;
77047c478bd9Sstevel@tonic-gate 	}
77057c478bd9Sstevel@tonic-gate 	if (replylen > SOCKETMAP_MAXL)
77067c478bd9Sstevel@tonic-gate 	{
77077c478bd9Sstevel@tonic-gate 		syserr("451 4.3.0 socket_map_lookup(%s): reply too long: %u",
77087c478bd9Sstevel@tonic-gate 			   map->map_mname, replylen);
77097c478bd9Sstevel@tonic-gate 		*statp = EX_TEMPFAIL;
77107c478bd9Sstevel@tonic-gate 		goto errcl;
77117c478bd9Sstevel@tonic-gate 	}
77127c478bd9Sstevel@tonic-gate 	if (sm_io_getc(f, SM_TIME_DEFAULT) != ':')
77137c478bd9Sstevel@tonic-gate 	{
77147c478bd9Sstevel@tonic-gate 		syserr("451 4.3.0 socket_map_lookup(%s): missing ':' in reply",
77157c478bd9Sstevel@tonic-gate 			map->map_mname);
77167c478bd9Sstevel@tonic-gate 		*statp = EX_TEMPFAIL;
77177c478bd9Sstevel@tonic-gate 		goto error;
77187c478bd9Sstevel@tonic-gate 	}
77197c478bd9Sstevel@tonic-gate 
77207c478bd9Sstevel@tonic-gate 	replybuf = (char *) sm_malloc(replylen + 1);
77217c478bd9Sstevel@tonic-gate 	if (replybuf == NULL)
77227c478bd9Sstevel@tonic-gate 	{
77237c478bd9Sstevel@tonic-gate 		syserr("451 4.3.0 socket_map_lookup(%s): can't allocate %u bytes",
77247c478bd9Sstevel@tonic-gate 			map->map_mname, replylen + 1);
77257c478bd9Sstevel@tonic-gate 		*statp = EX_OSERR;
77267c478bd9Sstevel@tonic-gate 		goto error;
77277c478bd9Sstevel@tonic-gate 	}
77287c478bd9Sstevel@tonic-gate 
77297c478bd9Sstevel@tonic-gate 	recvlen = sm_io_read(f, SM_TIME_DEFAULT, replybuf, replylen);
77307c478bd9Sstevel@tonic-gate 	if (recvlen < replylen)
77317c478bd9Sstevel@tonic-gate 	{
77327c478bd9Sstevel@tonic-gate 		syserr("451 4.3.0 socket_map_lookup(%s): received only %u of %u reply characters",
77337c478bd9Sstevel@tonic-gate 			   map->map_mname, recvlen, replylen);
77347c478bd9Sstevel@tonic-gate 		*statp = EX_TEMPFAIL;
77357c478bd9Sstevel@tonic-gate 		goto errcl;
77367c478bd9Sstevel@tonic-gate 	}
77377c478bd9Sstevel@tonic-gate 	if (sm_io_getc(f, SM_TIME_DEFAULT) != ',')
77387c478bd9Sstevel@tonic-gate 	{
77397c478bd9Sstevel@tonic-gate 		syserr("451 4.3.0 socket_map_lookup(%s): missing ',' in reply",
77407c478bd9Sstevel@tonic-gate 			map->map_mname);
77417c478bd9Sstevel@tonic-gate 		*statp = EX_TEMPFAIL;
77427c478bd9Sstevel@tonic-gate 		goto errcl;
77437c478bd9Sstevel@tonic-gate 	}
77447c478bd9Sstevel@tonic-gate 	status = replybuf;
77457c478bd9Sstevel@tonic-gate 	replybuf[recvlen] = '\0';
77467c478bd9Sstevel@tonic-gate 	value = strchr(replybuf, ' ');
77477c478bd9Sstevel@tonic-gate 	if (value != NULL)
77487c478bd9Sstevel@tonic-gate 	{
77497c478bd9Sstevel@tonic-gate 		*value = '\0';
77507c478bd9Sstevel@tonic-gate 		value++;
77517c478bd9Sstevel@tonic-gate 	}
77527c478bd9Sstevel@tonic-gate 	if (strcmp(status, "OK") == 0)
77537c478bd9Sstevel@tonic-gate 	{
77547c478bd9Sstevel@tonic-gate 		*statp = EX_OK;
77557c478bd9Sstevel@tonic-gate 
77567c478bd9Sstevel@tonic-gate 		/* collect the return value */
77577c478bd9Sstevel@tonic-gate 		if (bitset(MF_MATCHONLY, map->map_mflags))
77587c478bd9Sstevel@tonic-gate 			rval = map_rewrite(map, key, strlen(key), NULL);
77597c478bd9Sstevel@tonic-gate 		else
77607c478bd9Sstevel@tonic-gate 			rval = map_rewrite(map, value, strlen(value), av);
77617c478bd9Sstevel@tonic-gate 	}
77627c478bd9Sstevel@tonic-gate 	else if (strcmp(status, "NOTFOUND") == 0)
77637c478bd9Sstevel@tonic-gate 	{
77647c478bd9Sstevel@tonic-gate 		*statp = EX_NOTFOUND;
77657c478bd9Sstevel@tonic-gate 		if (tTd(38, 20))
77667c478bd9Sstevel@tonic-gate 			sm_dprintf("socket_map_lookup(%s): %s not found\n",
77677c478bd9Sstevel@tonic-gate 				map->map_mname, key);
77687c478bd9Sstevel@tonic-gate 	}
77697c478bd9Sstevel@tonic-gate 	else
77707c478bd9Sstevel@tonic-gate 	{
77717c478bd9Sstevel@tonic-gate 		if (tTd(38, 5))
77727c478bd9Sstevel@tonic-gate 			sm_dprintf("socket_map_lookup(%s, %s): server returned error: type=%s, reason=%s\n",
77737c478bd9Sstevel@tonic-gate 				map->map_mname, key, status,
77747c478bd9Sstevel@tonic-gate 				value ? value : "");
77757c478bd9Sstevel@tonic-gate 		if ((strcmp(status, "TEMP") == 0) ||
77767c478bd9Sstevel@tonic-gate 		    (strcmp(status, "TIMEOUT") == 0))
77777c478bd9Sstevel@tonic-gate 			*statp = EX_TEMPFAIL;
77787c478bd9Sstevel@tonic-gate 		else if(strcmp(status, "PERM") == 0)
77797c478bd9Sstevel@tonic-gate 			*statp = EX_UNAVAILABLE;
77807c478bd9Sstevel@tonic-gate 		else
77817c478bd9Sstevel@tonic-gate 			*statp = EX_PROTOCOL;
77827c478bd9Sstevel@tonic-gate 	}
77837c478bd9Sstevel@tonic-gate 
77847c478bd9Sstevel@tonic-gate 	if (replybuf != NULL)
77857c478bd9Sstevel@tonic-gate 		sm_free(replybuf);
77867c478bd9Sstevel@tonic-gate 	return rval;
77877c478bd9Sstevel@tonic-gate 
77887c478bd9Sstevel@tonic-gate   errcl:
77897c478bd9Sstevel@tonic-gate 	socket_map_close(map);
77907c478bd9Sstevel@tonic-gate   error:
77917c478bd9Sstevel@tonic-gate 	if (replybuf != NULL)
77927c478bd9Sstevel@tonic-gate 		sm_free(replybuf);
77937c478bd9Sstevel@tonic-gate 	return rval;
77947c478bd9Sstevel@tonic-gate }
77957c478bd9Sstevel@tonic-gate #endif /* SOCKETMAP */
7796