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