xref: /illumos-gate/usr/src/cmd/sendmail/src/udb.c (revision 2a8bcb4e)
17c478bd9Sstevel@tonic-gate /*
2*058561cbSjbeck  * Copyright (c) 1998-2003, 2006 Sendmail, Inc. and its suppliers.
37c478bd9Sstevel@tonic-gate  *	All rights reserved.
47c478bd9Sstevel@tonic-gate  * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
57c478bd9Sstevel@tonic-gate  * Copyright (c) 1988, 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 #include <sendmail.h>
15*058561cbSjbeck #include "map.h"
167c478bd9Sstevel@tonic-gate 
177c478bd9Sstevel@tonic-gate #if USERDB
18*058561cbSjbeck SM_RCSID("@(#)$Id: udb.c,v 8.164 2006/12/19 19:49:51 ca Exp $ (with USERDB)")
197c478bd9Sstevel@tonic-gate #else /* USERDB */
20*058561cbSjbeck SM_RCSID("@(#)$Id: udb.c,v 8.164 2006/12/19 19:49:51 ca Exp $ (without USERDB)")
217c478bd9Sstevel@tonic-gate #endif /* USERDB */
227c478bd9Sstevel@tonic-gate 
237c478bd9Sstevel@tonic-gate #if USERDB
247c478bd9Sstevel@tonic-gate 
25*058561cbSjbeck #include <sm/sendmail.h>
267c478bd9Sstevel@tonic-gate # if NEWDB
277c478bd9Sstevel@tonic-gate #  include "sm/bdb.h"
287c478bd9Sstevel@tonic-gate # else /* NEWDB */
297c478bd9Sstevel@tonic-gate #  define DBT	struct _data_base_thang_
307c478bd9Sstevel@tonic-gate DBT
317c478bd9Sstevel@tonic-gate {
327c478bd9Sstevel@tonic-gate 	void	*data;		/* pointer to data */
337c478bd9Sstevel@tonic-gate 	size_t	size;		/* length of data */
347c478bd9Sstevel@tonic-gate };
357c478bd9Sstevel@tonic-gate # endif /* NEWDB */
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate /*
387c478bd9Sstevel@tonic-gate **  UDB.C -- interface between sendmail and Berkeley User Data Base.
397c478bd9Sstevel@tonic-gate **
407c478bd9Sstevel@tonic-gate **	This depends on the 4.4BSD db package.
417c478bd9Sstevel@tonic-gate */
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate struct udbent
457c478bd9Sstevel@tonic-gate {
467c478bd9Sstevel@tonic-gate 	char	*udb_spec;		/* string version of spec */
477c478bd9Sstevel@tonic-gate 	int	udb_type;		/* type of entry */
487c478bd9Sstevel@tonic-gate 	pid_t	udb_pid;		/* PID of process which opened db */
497c478bd9Sstevel@tonic-gate 	char	*udb_default;		/* default host for outgoing mail */
507c478bd9Sstevel@tonic-gate 	union
517c478bd9Sstevel@tonic-gate 	{
527c478bd9Sstevel@tonic-gate # if NETINET || NETINET6
537c478bd9Sstevel@tonic-gate 		/* type UE_REMOTE -- do remote call for lookup */
547c478bd9Sstevel@tonic-gate 		struct
557c478bd9Sstevel@tonic-gate 		{
567c478bd9Sstevel@tonic-gate 			SOCKADDR	_udb_addr;	/* address */
577c478bd9Sstevel@tonic-gate 			int		_udb_timeout;	/* timeout */
587c478bd9Sstevel@tonic-gate 		} udb_remote;
597c478bd9Sstevel@tonic-gate #  define udb_addr	udb_u.udb_remote._udb_addr
607c478bd9Sstevel@tonic-gate #  define udb_timeout	udb_u.udb_remote._udb_timeout
617c478bd9Sstevel@tonic-gate # endif /* NETINET || NETINET6 */
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate 		/* type UE_FORWARD -- forward message to remote */
647c478bd9Sstevel@tonic-gate 		struct
657c478bd9Sstevel@tonic-gate 		{
667c478bd9Sstevel@tonic-gate 			char	*_udb_fwdhost;	/* name of forward host */
677c478bd9Sstevel@tonic-gate 		} udb_forward;
687c478bd9Sstevel@tonic-gate # define udb_fwdhost	udb_u.udb_forward._udb_fwdhost
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate # if NEWDB
717c478bd9Sstevel@tonic-gate 		/* type UE_FETCH -- lookup in local database */
727c478bd9Sstevel@tonic-gate 		struct
737c478bd9Sstevel@tonic-gate 		{
747c478bd9Sstevel@tonic-gate 			char	*_udb_dbname;	/* pathname of database */
757c478bd9Sstevel@tonic-gate 			DB	*_udb_dbp;	/* open database ptr */
767c478bd9Sstevel@tonic-gate 		} udb_lookup;
777c478bd9Sstevel@tonic-gate #  define udb_dbname	udb_u.udb_lookup._udb_dbname
787c478bd9Sstevel@tonic-gate #  define udb_dbp	udb_u.udb_lookup._udb_dbp
797c478bd9Sstevel@tonic-gate # endif /* NEWDB */
807c478bd9Sstevel@tonic-gate 	} udb_u;
817c478bd9Sstevel@tonic-gate };
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate # define UDB_EOLIST	0	/* end of list */
847c478bd9Sstevel@tonic-gate # define UDB_SKIP	1	/* skip this entry */
857c478bd9Sstevel@tonic-gate # define UDB_REMOTE	2	/* look up in remote database */
867c478bd9Sstevel@tonic-gate # define UDB_DBFETCH	3	/* look up in local database */
877c478bd9Sstevel@tonic-gate # define UDB_FORWARD	4	/* forward to remote host */
887c478bd9Sstevel@tonic-gate # define UDB_HESIOD	5	/* look up via hesiod */
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate # define MAXUDBENT	10	/* maximum number of UDB entries */
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate struct udb_option
947c478bd9Sstevel@tonic-gate {
957c478bd9Sstevel@tonic-gate 	char	*udbo_name;
967c478bd9Sstevel@tonic-gate 	char	*udbo_val;
977c478bd9Sstevel@tonic-gate };
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate # if HESIOD
1007c478bd9Sstevel@tonic-gate static int	hes_udb_get __P((DBT *, DBT *));
1017c478bd9Sstevel@tonic-gate # endif /* HESIOD */
1027c478bd9Sstevel@tonic-gate static char	*udbmatch __P((char *, char *, SM_RPOOL_T *));
1037c478bd9Sstevel@tonic-gate static int	_udbx_init __P((ENVELOPE *));
1047c478bd9Sstevel@tonic-gate static int	_udb_parsespec __P((char *, struct udb_option [], int));
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate /*
1077c478bd9Sstevel@tonic-gate **  UDBEXPAND -- look up user in database and expand
1087c478bd9Sstevel@tonic-gate **
1097c478bd9Sstevel@tonic-gate **	Parameters:
1107c478bd9Sstevel@tonic-gate **		a -- address to expand.
1117c478bd9Sstevel@tonic-gate **		sendq -- pointer to head of sendq to put the expansions in.
1127c478bd9Sstevel@tonic-gate **		aliaslevel -- the current alias nesting depth.
1137c478bd9Sstevel@tonic-gate **		e -- the current envelope.
1147c478bd9Sstevel@tonic-gate **
1157c478bd9Sstevel@tonic-gate **	Returns:
1167c478bd9Sstevel@tonic-gate **		EX_TEMPFAIL -- if something "odd" happened -- probably due
1177c478bd9Sstevel@tonic-gate **			to accessing a file on an NFS server that is down.
1187c478bd9Sstevel@tonic-gate **		EX_OK -- otherwise.
1197c478bd9Sstevel@tonic-gate **
1207c478bd9Sstevel@tonic-gate **	Side Effects:
1217c478bd9Sstevel@tonic-gate **		Modifies sendq.
1227c478bd9Sstevel@tonic-gate */
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate static struct udbent	UdbEnts[MAXUDBENT + 1];
1257c478bd9Sstevel@tonic-gate static bool		UdbInitialized = false;
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate int
udbexpand(a,sendq,aliaslevel,e)1287c478bd9Sstevel@tonic-gate udbexpand(a, sendq, aliaslevel, e)
1297c478bd9Sstevel@tonic-gate 	register ADDRESS *a;
1307c478bd9Sstevel@tonic-gate 	ADDRESS **sendq;
1317c478bd9Sstevel@tonic-gate 	int aliaslevel;
1327c478bd9Sstevel@tonic-gate 	register ENVELOPE *e;
1337c478bd9Sstevel@tonic-gate {
1347c478bd9Sstevel@tonic-gate 	int i;
1357c478bd9Sstevel@tonic-gate 	DBT key;
1367c478bd9Sstevel@tonic-gate 	DBT info;
1377c478bd9Sstevel@tonic-gate 	bool breakout;
1387c478bd9Sstevel@tonic-gate 	register struct udbent *up;
1397c478bd9Sstevel@tonic-gate 	int keylen;
1407c478bd9Sstevel@tonic-gate 	int naddrs;
1417c478bd9Sstevel@tonic-gate 	char *user;
14249218d4fSjbeck 	char keybuf[MAXUDBKEY];
1437c478bd9Sstevel@tonic-gate 
144*058561cbSjbeck 	memset(&key, '\0', sizeof(key));
145*058561cbSjbeck 	memset(&info, '\0', sizeof(info));
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate 	if (tTd(28, 1))
1487c478bd9Sstevel@tonic-gate 		sm_dprintf("udbexpand(%s)\n", a->q_paddr);
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate 	/* make certain we are supposed to send to this address */
1517c478bd9Sstevel@tonic-gate 	if (!QS_IS_SENDABLE(a->q_state))
1527c478bd9Sstevel@tonic-gate 		return EX_OK;
1537c478bd9Sstevel@tonic-gate 	e->e_to = a->q_paddr;
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate 	/* on first call, locate the database */
1567c478bd9Sstevel@tonic-gate 	if (!UdbInitialized)
1577c478bd9Sstevel@tonic-gate 	{
1587c478bd9Sstevel@tonic-gate 		if (_udbx_init(e) == EX_TEMPFAIL)
1597c478bd9Sstevel@tonic-gate 			return EX_TEMPFAIL;
1607c478bd9Sstevel@tonic-gate 	}
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate 	/* short circuit the process if no chance of a match */
1637c478bd9Sstevel@tonic-gate 	if (UdbSpec == NULL || UdbSpec[0] == '\0')
1647c478bd9Sstevel@tonic-gate 		return EX_OK;
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 	/* extract user to do userdb matching on */
1677c478bd9Sstevel@tonic-gate 	user = a->q_user;
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate 	/* short circuit name begins with '\\' since it can't possibly match */
1707c478bd9Sstevel@tonic-gate 	/* (might want to treat this as unquoted instead) */
1717c478bd9Sstevel@tonic-gate 	if (user[0] == '\\')
1727c478bd9Sstevel@tonic-gate 		return EX_OK;
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate 	/* if name begins with a colon, it indicates our metadata */
1757c478bd9Sstevel@tonic-gate 	if (user[0] == ':')
1767c478bd9Sstevel@tonic-gate 		return EX_OK;
1777c478bd9Sstevel@tonic-gate 
178*058561cbSjbeck 	keylen = sm_strlcpyn(keybuf, sizeof(keybuf), 2, user, ":maildrop");
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate 	/* if name is too long, assume it won't match */
181*058561cbSjbeck 	if (keylen >= sizeof(keybuf))
1827c478bd9Sstevel@tonic-gate 		return EX_OK;
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate 	/* build actual database key */
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate 	breakout = false;
1877c478bd9Sstevel@tonic-gate 	for (up = UdbEnts; !breakout; up++)
1887c478bd9Sstevel@tonic-gate 	{
1897c478bd9Sstevel@tonic-gate 		int usersize;
1907c478bd9Sstevel@tonic-gate 		int userleft;
1917c478bd9Sstevel@tonic-gate 		char userbuf[MEMCHUNKSIZE];
1927c478bd9Sstevel@tonic-gate # if HESIOD && HES_GETMAILHOST
1937c478bd9Sstevel@tonic-gate 		char pobuf[MAXNAME];
1947c478bd9Sstevel@tonic-gate # endif /* HESIOD && HES_GETMAILHOST */
1957c478bd9Sstevel@tonic-gate # if defined(NEWDB) && DB_VERSION_MAJOR > 1
1967c478bd9Sstevel@tonic-gate 		DBC *dbc = NULL;
1977c478bd9Sstevel@tonic-gate # endif /* defined(NEWDB) && DB_VERSION_MAJOR > 1 */
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate 		user = userbuf;
2007c478bd9Sstevel@tonic-gate 		userbuf[0] = '\0';
201*058561cbSjbeck 		usersize = sizeof(userbuf);
202*058561cbSjbeck 		userleft = sizeof(userbuf) - 1;
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate 		/*
2057c478bd9Sstevel@tonic-gate 		**  Select action based on entry type.
2067c478bd9Sstevel@tonic-gate 		**
2077c478bd9Sstevel@tonic-gate 		**	On dropping out of this switch, "class" should
2087c478bd9Sstevel@tonic-gate 		**	explain the type of the data, and "user" should
2097c478bd9Sstevel@tonic-gate 		**	contain the user information.
2107c478bd9Sstevel@tonic-gate 		*/
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate 		switch (up->udb_type)
2137c478bd9Sstevel@tonic-gate 		{
2147c478bd9Sstevel@tonic-gate # if NEWDB
2157c478bd9Sstevel@tonic-gate 		  case UDB_DBFETCH:
2167c478bd9Sstevel@tonic-gate 			key.data = keybuf;
2177c478bd9Sstevel@tonic-gate 			key.size = keylen;
2187c478bd9Sstevel@tonic-gate 			if (tTd(28, 80))
2197c478bd9Sstevel@tonic-gate 				sm_dprintf("udbexpand: trying %s (%d) via db\n",
2207c478bd9Sstevel@tonic-gate 					keybuf, keylen);
2217c478bd9Sstevel@tonic-gate #  if DB_VERSION_MAJOR < 2
2227c478bd9Sstevel@tonic-gate 			i = (*up->udb_dbp->seq)(up->udb_dbp, &key, &info, R_CURSOR);
2237c478bd9Sstevel@tonic-gate #  else /* DB_VERSION_MAJOR < 2 */
2247c478bd9Sstevel@tonic-gate 			i = 0;
2257c478bd9Sstevel@tonic-gate 			if (dbc == NULL &&
2267c478bd9Sstevel@tonic-gate #   if DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6
2277c478bd9Sstevel@tonic-gate 			    (errno = (*up->udb_dbp->cursor)(up->udb_dbp,
2287c478bd9Sstevel@tonic-gate 							    NULL, &dbc, 0)) != 0)
2297c478bd9Sstevel@tonic-gate #   else /* DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6 */
2307c478bd9Sstevel@tonic-gate 			    (errno = (*up->udb_dbp->cursor)(up->udb_dbp,
2317c478bd9Sstevel@tonic-gate 							    NULL, &dbc)) != 0)
2327c478bd9Sstevel@tonic-gate #   endif /* DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6 */
2337c478bd9Sstevel@tonic-gate 				i = -1;
2347c478bd9Sstevel@tonic-gate 			if (i != 0 || dbc == NULL ||
2357c478bd9Sstevel@tonic-gate 			    (errno = dbc->c_get(dbc, &key,
2367c478bd9Sstevel@tonic-gate 						&info, DB_SET)) != 0)
2377c478bd9Sstevel@tonic-gate 				i = 1;
2387c478bd9Sstevel@tonic-gate #  endif /* DB_VERSION_MAJOR < 2 */
2397c478bd9Sstevel@tonic-gate 			if (i > 0 || info.size <= 0)
2407c478bd9Sstevel@tonic-gate 			{
2417c478bd9Sstevel@tonic-gate 				if (tTd(28, 2))
2427c478bd9Sstevel@tonic-gate 					sm_dprintf("udbexpand: no match on %s (%d)\n",
2437c478bd9Sstevel@tonic-gate 						keybuf, keylen);
2447c478bd9Sstevel@tonic-gate #  if DB_VERSION_MAJOR > 1
2457c478bd9Sstevel@tonic-gate 				if (dbc != NULL)
2467c478bd9Sstevel@tonic-gate 				{
2477c478bd9Sstevel@tonic-gate 					(void) dbc->c_close(dbc);
2487c478bd9Sstevel@tonic-gate 					dbc = NULL;
2497c478bd9Sstevel@tonic-gate 				}
2507c478bd9Sstevel@tonic-gate #  endif /* DB_VERSION_MAJOR > 1 */
2517c478bd9Sstevel@tonic-gate 				break;
2527c478bd9Sstevel@tonic-gate 			}
2537c478bd9Sstevel@tonic-gate 			if (tTd(28, 80))
2547c478bd9Sstevel@tonic-gate 				sm_dprintf("udbexpand: match %.*s: %.*s\n",
2557c478bd9Sstevel@tonic-gate 					(int) key.size, (char *) key.data,
2567c478bd9Sstevel@tonic-gate 					(int) info.size, (char *) info.data);
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate 			a->q_flags &= ~QSELFREF;
2597c478bd9Sstevel@tonic-gate 			while (i == 0 && key.size == keylen &&
2607c478bd9Sstevel@tonic-gate 			       memcmp(key.data, keybuf, keylen) == 0)
2617c478bd9Sstevel@tonic-gate 			{
2627c478bd9Sstevel@tonic-gate 				char *p;
2637c478bd9Sstevel@tonic-gate 
2647c478bd9Sstevel@tonic-gate 				if (bitset(EF_VRFYONLY, e->e_flags))
2657c478bd9Sstevel@tonic-gate 				{
2667c478bd9Sstevel@tonic-gate 					a->q_state = QS_VERIFIED;
2677c478bd9Sstevel@tonic-gate #  if DB_VERSION_MAJOR > 1
2687c478bd9Sstevel@tonic-gate 					if (dbc != NULL)
2697c478bd9Sstevel@tonic-gate 					{
2707c478bd9Sstevel@tonic-gate 						(void) dbc->c_close(dbc);
2717c478bd9Sstevel@tonic-gate 						dbc = NULL;
2727c478bd9Sstevel@tonic-gate 					}
2737c478bd9Sstevel@tonic-gate #  endif /* DB_VERSION_MAJOR > 1 */
2747c478bd9Sstevel@tonic-gate 					return EX_OK;
2757c478bd9Sstevel@tonic-gate 				}
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate 				breakout = true;
2787c478bd9Sstevel@tonic-gate 				if (info.size >= userleft - 1)
2797c478bd9Sstevel@tonic-gate 				{
2807c478bd9Sstevel@tonic-gate 					char *nuser;
2817c478bd9Sstevel@tonic-gate 					int size = MEMCHUNKSIZE;
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate 					if (info.size > MEMCHUNKSIZE)
2847c478bd9Sstevel@tonic-gate 						size = info.size;
2857c478bd9Sstevel@tonic-gate 					nuser = sm_malloc_x(usersize + size);
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate 					memmove(nuser, user, usersize);
2887c478bd9Sstevel@tonic-gate 					if (user != userbuf)
2897c478bd9Sstevel@tonic-gate 						sm_free(user); /* XXX */
2907c478bd9Sstevel@tonic-gate 					user = nuser;
2917c478bd9Sstevel@tonic-gate 					usersize += size;
2927c478bd9Sstevel@tonic-gate 					userleft += size;
2937c478bd9Sstevel@tonic-gate 				}
2947c478bd9Sstevel@tonic-gate 				p = &user[strlen(user)];
2957c478bd9Sstevel@tonic-gate 				if (p != user)
2967c478bd9Sstevel@tonic-gate 				{
2977c478bd9Sstevel@tonic-gate 					*p++ = ',';
2987c478bd9Sstevel@tonic-gate 					userleft--;
2997c478bd9Sstevel@tonic-gate 				}
3007c478bd9Sstevel@tonic-gate 				memmove(p, info.data, info.size);
3017c478bd9Sstevel@tonic-gate 				p[info.size] = '\0';
3027c478bd9Sstevel@tonic-gate 				userleft -= info.size;
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate 				/* get the next record */
3057c478bd9Sstevel@tonic-gate #  if DB_VERSION_MAJOR < 2
3067c478bd9Sstevel@tonic-gate 				i = (*up->udb_dbp->seq)(up->udb_dbp, &key, &info, R_NEXT);
3077c478bd9Sstevel@tonic-gate #  else /* DB_VERSION_MAJOR < 2 */
3087c478bd9Sstevel@tonic-gate 				i = 0;
3097c478bd9Sstevel@tonic-gate 				if ((errno = dbc->c_get(dbc, &key,
3107c478bd9Sstevel@tonic-gate 							&info, DB_NEXT)) != 0)
3117c478bd9Sstevel@tonic-gate 					i = 1;
3127c478bd9Sstevel@tonic-gate #  endif /* DB_VERSION_MAJOR < 2 */
3137c478bd9Sstevel@tonic-gate 			}
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate #  if DB_VERSION_MAJOR > 1
3167c478bd9Sstevel@tonic-gate 			if (dbc != NULL)
3177c478bd9Sstevel@tonic-gate 			{
3187c478bd9Sstevel@tonic-gate 				(void) dbc->c_close(dbc);
3197c478bd9Sstevel@tonic-gate 				dbc = NULL;
3207c478bd9Sstevel@tonic-gate 			}
3217c478bd9Sstevel@tonic-gate #  endif /* DB_VERSION_MAJOR > 1 */
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate 			/* if nothing ever matched, try next database */
3247c478bd9Sstevel@tonic-gate 			if (!breakout)
3257c478bd9Sstevel@tonic-gate 				break;
3267c478bd9Sstevel@tonic-gate 
3277c478bd9Sstevel@tonic-gate 			message("expanded to %s", user);
3287c478bd9Sstevel@tonic-gate 			if (LogLevel > 10)
3297c478bd9Sstevel@tonic-gate 				sm_syslog(LOG_INFO, e->e_id,
3307c478bd9Sstevel@tonic-gate 					  "expand %.100s => %s",
3317c478bd9Sstevel@tonic-gate 					  e->e_to,
3327c478bd9Sstevel@tonic-gate 					  shortenstring(user, MAXSHORTSTR));
3337c478bd9Sstevel@tonic-gate 			naddrs = sendtolist(user, a, sendq, aliaslevel + 1, e);
3347c478bd9Sstevel@tonic-gate 			if (naddrs > 0 && !bitset(QSELFREF, a->q_flags))
3357c478bd9Sstevel@tonic-gate 			{
3367c478bd9Sstevel@tonic-gate 				if (tTd(28, 5))
3377c478bd9Sstevel@tonic-gate 				{
3387c478bd9Sstevel@tonic-gate 					sm_dprintf("udbexpand: QS_EXPANDED ");
3397c478bd9Sstevel@tonic-gate 					printaddr(sm_debug_file(), a, false);
3407c478bd9Sstevel@tonic-gate 				}
3417c478bd9Sstevel@tonic-gate 				a->q_state = QS_EXPANDED;
3427c478bd9Sstevel@tonic-gate 			}
3437c478bd9Sstevel@tonic-gate 			if (i < 0)
3447c478bd9Sstevel@tonic-gate 			{
3457c478bd9Sstevel@tonic-gate 				syserr("udbexpand: db-get %.*s stat %d",
3467c478bd9Sstevel@tonic-gate 					(int) key.size, (char *) key.data, i);
3477c478bd9Sstevel@tonic-gate 				return EX_TEMPFAIL;
3487c478bd9Sstevel@tonic-gate 			}
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate 			/*
3517c478bd9Sstevel@tonic-gate 			**  If this address has a -request address, reflect
3527c478bd9Sstevel@tonic-gate 			**  it into the envelope.
3537c478bd9Sstevel@tonic-gate 			*/
3547c478bd9Sstevel@tonic-gate 
355*058561cbSjbeck 			memset(&key, '\0', sizeof(key));
356*058561cbSjbeck 			memset(&info, '\0', sizeof(info));
357*058561cbSjbeck 			(void) sm_strlcpyn(keybuf, sizeof(keybuf), 2, a->q_user,
3587c478bd9Sstevel@tonic-gate 					   ":mailsender");
3597c478bd9Sstevel@tonic-gate 			keylen = strlen(keybuf);
3607c478bd9Sstevel@tonic-gate 			key.data = keybuf;
3617c478bd9Sstevel@tonic-gate 			key.size = keylen;
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate #  if DB_VERSION_MAJOR < 2
3647c478bd9Sstevel@tonic-gate 			i = (*up->udb_dbp->get)(up->udb_dbp, &key, &info, 0);
3657c478bd9Sstevel@tonic-gate #  else /* DB_VERSION_MAJOR < 2 */
3667c478bd9Sstevel@tonic-gate 			i = errno = (*up->udb_dbp->get)(up->udb_dbp, NULL,
3677c478bd9Sstevel@tonic-gate 							&key, &info, 0);
3687c478bd9Sstevel@tonic-gate #  endif /* DB_VERSION_MAJOR < 2 */
3697c478bd9Sstevel@tonic-gate 			if (i != 0 || info.size <= 0)
3707c478bd9Sstevel@tonic-gate 				break;
3717c478bd9Sstevel@tonic-gate 			a->q_owner = sm_rpool_malloc_x(e->e_rpool,
3727c478bd9Sstevel@tonic-gate 						       info.size + 1);
3737c478bd9Sstevel@tonic-gate 			memmove(a->q_owner, info.data, info.size);
3747c478bd9Sstevel@tonic-gate 			a->q_owner[info.size] = '\0';
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate 			/* announce delivery; NORECEIPT bit set later */
3777c478bd9Sstevel@tonic-gate 			if (e->e_xfp != NULL)
3787c478bd9Sstevel@tonic-gate 			{
3797c478bd9Sstevel@tonic-gate 				(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
3807c478bd9Sstevel@tonic-gate 						     "Message delivered to mailing list %s\n",
3817c478bd9Sstevel@tonic-gate 						     a->q_paddr);
3827c478bd9Sstevel@tonic-gate 			}
3837c478bd9Sstevel@tonic-gate 			e->e_flags |= EF_SENDRECEIPT;
3847c478bd9Sstevel@tonic-gate 			a->q_flags |= QDELIVERED|QEXPANDED;
3857c478bd9Sstevel@tonic-gate 			break;
3867c478bd9Sstevel@tonic-gate # endif /* NEWDB */
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate # if HESIOD
3897c478bd9Sstevel@tonic-gate 		  case UDB_HESIOD:
3907c478bd9Sstevel@tonic-gate 			key.data = keybuf;
3917c478bd9Sstevel@tonic-gate 			key.size = keylen;
3927c478bd9Sstevel@tonic-gate 			if (tTd(28, 80))
3937c478bd9Sstevel@tonic-gate 				sm_dprintf("udbexpand: trying %s (%d) via hesiod\n",
3947c478bd9Sstevel@tonic-gate 					keybuf, keylen);
3957c478bd9Sstevel@tonic-gate 			/* look up the key via hesiod */
3967c478bd9Sstevel@tonic-gate 			i = hes_udb_get(&key, &info);
3977c478bd9Sstevel@tonic-gate 			if (i < 0)
3987c478bd9Sstevel@tonic-gate 			{
3997c478bd9Sstevel@tonic-gate 				syserr("udbexpand: hesiod-get %.*s stat %d",
4007c478bd9Sstevel@tonic-gate 					(int) key.size, (char *) key.data, i);
4017c478bd9Sstevel@tonic-gate 				return EX_TEMPFAIL;
4027c478bd9Sstevel@tonic-gate 			}
4037c478bd9Sstevel@tonic-gate 			else if (i > 0 || info.size <= 0)
4047c478bd9Sstevel@tonic-gate 			{
4057c478bd9Sstevel@tonic-gate #  if HES_GETMAILHOST
4067c478bd9Sstevel@tonic-gate 				struct hes_postoffice *hp;
4077c478bd9Sstevel@tonic-gate #  endif /* HES_GETMAILHOST */
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate 				if (tTd(28, 2))
4107c478bd9Sstevel@tonic-gate 					sm_dprintf("udbexpand: no match on %s (%d)\n",
4117c478bd9Sstevel@tonic-gate 						(char *) keybuf, (int) keylen);
4127c478bd9Sstevel@tonic-gate #  if HES_GETMAILHOST
4137c478bd9Sstevel@tonic-gate 				if (tTd(28, 8))
4147c478bd9Sstevel@tonic-gate 					sm_dprintf("  ... trying hes_getmailhost(%s)\n",
4157c478bd9Sstevel@tonic-gate 						a->q_user);
4167c478bd9Sstevel@tonic-gate 				hp = hes_getmailhost(a->q_user);
4177c478bd9Sstevel@tonic-gate 				if (hp == NULL)
4187c478bd9Sstevel@tonic-gate 				{
4197c478bd9Sstevel@tonic-gate 					if (hes_error() == HES_ER_NET)
4207c478bd9Sstevel@tonic-gate 					{
4217c478bd9Sstevel@tonic-gate 						syserr("udbexpand: hesiod-getmail %s stat %d",
4227c478bd9Sstevel@tonic-gate 							a->q_user, hes_error());
4237c478bd9Sstevel@tonic-gate 						return EX_TEMPFAIL;
4247c478bd9Sstevel@tonic-gate 					}
4257c478bd9Sstevel@tonic-gate 					if (tTd(28, 2))
4267c478bd9Sstevel@tonic-gate 						sm_dprintf("hes_getmailhost(%s): %d\n",
4277c478bd9Sstevel@tonic-gate 							a->q_user, hes_error());
4287c478bd9Sstevel@tonic-gate 					break;
4297c478bd9Sstevel@tonic-gate 				}
4307c478bd9Sstevel@tonic-gate 				if (strlen(hp->po_name) + strlen(hp->po_host) >
431*058561cbSjbeck 				    sizeof(pobuf) - 2)
4327c478bd9Sstevel@tonic-gate 				{
4337c478bd9Sstevel@tonic-gate 					if (tTd(28, 2))
4347c478bd9Sstevel@tonic-gate 						sm_dprintf("hes_getmailhost(%s): expansion too long: %.30s@%.30s\n",
4357c478bd9Sstevel@tonic-gate 							a->q_user,
4367c478bd9Sstevel@tonic-gate 							hp->po_name,
4377c478bd9Sstevel@tonic-gate 							hp->po_host);
4387c478bd9Sstevel@tonic-gate 					break;
4397c478bd9Sstevel@tonic-gate 				}
4407c478bd9Sstevel@tonic-gate 				info.data = pobuf;
441*058561cbSjbeck 				(void) sm_snprintf(pobuf, sizeof(pobuf),
4427c478bd9Sstevel@tonic-gate 					"%s@%s", hp->po_name, hp->po_host);
4437c478bd9Sstevel@tonic-gate 				info.size = strlen(info.data);
4447c478bd9Sstevel@tonic-gate #  else /* HES_GETMAILHOST */
4457c478bd9Sstevel@tonic-gate 				break;
4467c478bd9Sstevel@tonic-gate #  endif /* HES_GETMAILHOST */
4477c478bd9Sstevel@tonic-gate 			}
4487c478bd9Sstevel@tonic-gate 			if (tTd(28, 80))
4497c478bd9Sstevel@tonic-gate 				sm_dprintf("udbexpand: match %.*s: %.*s\n",
4507c478bd9Sstevel@tonic-gate 					(int) key.size, (char *) key.data,
4517c478bd9Sstevel@tonic-gate 					(int) info.size, (char *) info.data);
4527c478bd9Sstevel@tonic-gate 			a->q_flags &= ~QSELFREF;
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate 			if (bitset(EF_VRFYONLY, e->e_flags))
4557c478bd9Sstevel@tonic-gate 			{
4567c478bd9Sstevel@tonic-gate 				a->q_state = QS_VERIFIED;
4577c478bd9Sstevel@tonic-gate 				return EX_OK;
4587c478bd9Sstevel@tonic-gate 			}
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 			breakout = true;
4617c478bd9Sstevel@tonic-gate 			if (info.size >= usersize)
4627c478bd9Sstevel@tonic-gate 				user = sm_malloc_x(info.size + 1);
4637c478bd9Sstevel@tonic-gate 			memmove(user, info.data, info.size);
4647c478bd9Sstevel@tonic-gate 			user[info.size] = '\0';
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate 			message("hesioded to %s", user);
4677c478bd9Sstevel@tonic-gate 			if (LogLevel > 10)
4687c478bd9Sstevel@tonic-gate 				sm_syslog(LOG_INFO, e->e_id,
4697c478bd9Sstevel@tonic-gate 					  "hesiod %.100s => %s",
4707c478bd9Sstevel@tonic-gate 					  e->e_to,
4717c478bd9Sstevel@tonic-gate 					  shortenstring(user, MAXSHORTSTR));
4727c478bd9Sstevel@tonic-gate 			naddrs = sendtolist(user, a, sendq, aliaslevel + 1, e);
4737c478bd9Sstevel@tonic-gate 
4747c478bd9Sstevel@tonic-gate 			if (naddrs > 0 && !bitset(QSELFREF, a->q_flags))
4757c478bd9Sstevel@tonic-gate 			{
4767c478bd9Sstevel@tonic-gate 				if (tTd(28, 5))
4777c478bd9Sstevel@tonic-gate 				{
4787c478bd9Sstevel@tonic-gate 					sm_dprintf("udbexpand: QS_EXPANDED ");
4797c478bd9Sstevel@tonic-gate 					printaddr(sm_debug_file(), a, false);
4807c478bd9Sstevel@tonic-gate 				}
4817c478bd9Sstevel@tonic-gate 				a->q_state = QS_EXPANDED;
4827c478bd9Sstevel@tonic-gate 			}
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate 			/*
4857c478bd9Sstevel@tonic-gate 			**  If this address has a -request address, reflect
4867c478bd9Sstevel@tonic-gate 			**  it into the envelope.
4877c478bd9Sstevel@tonic-gate 			*/
4887c478bd9Sstevel@tonic-gate 
489*058561cbSjbeck 			(void) sm_strlcpyn(keybuf, sizeof(keybuf), 2, a->q_user,
4907c478bd9Sstevel@tonic-gate 					   ":mailsender");
4917c478bd9Sstevel@tonic-gate 			keylen = strlen(keybuf);
4927c478bd9Sstevel@tonic-gate 			key.data = keybuf;
4937c478bd9Sstevel@tonic-gate 			key.size = keylen;
4947c478bd9Sstevel@tonic-gate 			i = hes_udb_get(&key, &info);
4957c478bd9Sstevel@tonic-gate 			if (i != 0 || info.size <= 0)
4967c478bd9Sstevel@tonic-gate 				break;
4977c478bd9Sstevel@tonic-gate 			a->q_owner = sm_rpool_malloc_x(e->e_rpool,
4987c478bd9Sstevel@tonic-gate 						       info.size + 1);
4997c478bd9Sstevel@tonic-gate 			memmove(a->q_owner, info.data, info.size);
5007c478bd9Sstevel@tonic-gate 			a->q_owner[info.size] = '\0';
5017c478bd9Sstevel@tonic-gate 			break;
5027c478bd9Sstevel@tonic-gate # endif /* HESIOD */
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate 		  case UDB_REMOTE:
5057c478bd9Sstevel@tonic-gate 			/* not yet implemented */
5067c478bd9Sstevel@tonic-gate 			break;
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate 		  case UDB_FORWARD:
5097c478bd9Sstevel@tonic-gate 			if (bitset(EF_VRFYONLY, e->e_flags))
5107c478bd9Sstevel@tonic-gate 			{
5117c478bd9Sstevel@tonic-gate 				a->q_state = QS_VERIFIED;
5127c478bd9Sstevel@tonic-gate 				return EX_OK;
5137c478bd9Sstevel@tonic-gate 			}
5147c478bd9Sstevel@tonic-gate 			i = strlen(up->udb_fwdhost) + strlen(a->q_user) + 1;
5157c478bd9Sstevel@tonic-gate 			if (i >= usersize)
5167c478bd9Sstevel@tonic-gate 			{
5177c478bd9Sstevel@tonic-gate 				usersize = i + 1;
5187c478bd9Sstevel@tonic-gate 				user = sm_malloc_x(usersize);
5197c478bd9Sstevel@tonic-gate 			}
5207c478bd9Sstevel@tonic-gate 			(void) sm_strlcpyn(user, usersize, 3,
5217c478bd9Sstevel@tonic-gate 					a->q_user, "@", up->udb_fwdhost);
5227c478bd9Sstevel@tonic-gate 			message("expanded to %s", user);
5237c478bd9Sstevel@tonic-gate 			a->q_flags &= ~QSELFREF;
5247c478bd9Sstevel@tonic-gate 			naddrs = sendtolist(user, a, sendq, aliaslevel + 1, e);
5257c478bd9Sstevel@tonic-gate 			if (naddrs > 0 && !bitset(QSELFREF, a->q_flags))
5267c478bd9Sstevel@tonic-gate 			{
5277c478bd9Sstevel@tonic-gate 				if (tTd(28, 5))
5287c478bd9Sstevel@tonic-gate 				{
5297c478bd9Sstevel@tonic-gate 					sm_dprintf("udbexpand: QS_EXPANDED ");
5307c478bd9Sstevel@tonic-gate 					printaddr(sm_debug_file(), a, false);
5317c478bd9Sstevel@tonic-gate 				}
5327c478bd9Sstevel@tonic-gate 				a->q_state = QS_EXPANDED;
5337c478bd9Sstevel@tonic-gate 			}
5347c478bd9Sstevel@tonic-gate 			breakout = true;
5357c478bd9Sstevel@tonic-gate 			break;
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate 		  case UDB_EOLIST:
5387c478bd9Sstevel@tonic-gate 			breakout = true;
5397c478bd9Sstevel@tonic-gate 			break;
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate 		  default:
5427c478bd9Sstevel@tonic-gate 			/* unknown entry type */
5437c478bd9Sstevel@tonic-gate 			break;
5447c478bd9Sstevel@tonic-gate 		}
5457c478bd9Sstevel@tonic-gate 		/* XXX if an exception occurs, there is a storage leak */
5467c478bd9Sstevel@tonic-gate 		if (user != userbuf)
5477c478bd9Sstevel@tonic-gate 			sm_free(user); /* XXX */
5487c478bd9Sstevel@tonic-gate 	}
5497c478bd9Sstevel@tonic-gate 	return EX_OK;
5507c478bd9Sstevel@tonic-gate }
5517c478bd9Sstevel@tonic-gate /*
5527c478bd9Sstevel@tonic-gate **  UDBSENDER -- return canonical external name of sender, given local name
5537c478bd9Sstevel@tonic-gate **
5547c478bd9Sstevel@tonic-gate **	Parameters:
5557c478bd9Sstevel@tonic-gate **		sender -- the name of the sender on the local machine.
5567c478bd9Sstevel@tonic-gate **		rpool -- resource pool from which to allocate result
5577c478bd9Sstevel@tonic-gate **
5587c478bd9Sstevel@tonic-gate **	Returns:
5597c478bd9Sstevel@tonic-gate **		The external name for this sender, if derivable from the
5607c478bd9Sstevel@tonic-gate **			database.  Storage allocated from rpool.
5617c478bd9Sstevel@tonic-gate **		NULL -- if nothing is changed from the database.
5627c478bd9Sstevel@tonic-gate **
5637c478bd9Sstevel@tonic-gate **	Side Effects:
5647c478bd9Sstevel@tonic-gate **		none.
5657c478bd9Sstevel@tonic-gate */
5667c478bd9Sstevel@tonic-gate 
5677c478bd9Sstevel@tonic-gate char *
udbsender(sender,rpool)5687c478bd9Sstevel@tonic-gate udbsender(sender, rpool)
5697c478bd9Sstevel@tonic-gate 	char *sender;
5707c478bd9Sstevel@tonic-gate 	SM_RPOOL_T *rpool;
5717c478bd9Sstevel@tonic-gate {
5727c478bd9Sstevel@tonic-gate 	return udbmatch(sender, "mailname", rpool);
5737c478bd9Sstevel@tonic-gate }
5747c478bd9Sstevel@tonic-gate /*
5757c478bd9Sstevel@tonic-gate **  UDBMATCH -- match user in field, return result of lookup.
5767c478bd9Sstevel@tonic-gate **
5777c478bd9Sstevel@tonic-gate **	Parameters:
5787c478bd9Sstevel@tonic-gate **		user -- the name of the user.
5797c478bd9Sstevel@tonic-gate **		field -- the field to lookup.
5807c478bd9Sstevel@tonic-gate **		rpool -- resource pool from which to allocate result
5817c478bd9Sstevel@tonic-gate **
5827c478bd9Sstevel@tonic-gate **	Returns:
5837c478bd9Sstevel@tonic-gate **		The external name for this sender, if derivable from the
5847c478bd9Sstevel@tonic-gate **			database.  Storage allocated from rpool.
5857c478bd9Sstevel@tonic-gate **		NULL -- if nothing is changed from the database.
5867c478bd9Sstevel@tonic-gate **
5877c478bd9Sstevel@tonic-gate **	Side Effects:
5887c478bd9Sstevel@tonic-gate **		none.
5897c478bd9Sstevel@tonic-gate */
5907c478bd9Sstevel@tonic-gate 
5917c478bd9Sstevel@tonic-gate static char *
udbmatch(user,field,rpool)5927c478bd9Sstevel@tonic-gate udbmatch(user, field, rpool)
5937c478bd9Sstevel@tonic-gate 	char *user;
5947c478bd9Sstevel@tonic-gate 	char *field;
5957c478bd9Sstevel@tonic-gate 	SM_RPOOL_T *rpool;
5967c478bd9Sstevel@tonic-gate {
5977c478bd9Sstevel@tonic-gate 	register char *p;
5987c478bd9Sstevel@tonic-gate 	register struct udbent *up;
5997c478bd9Sstevel@tonic-gate 	int i;
6007c478bd9Sstevel@tonic-gate 	int keylen;
6017c478bd9Sstevel@tonic-gate 	DBT key, info;
60249218d4fSjbeck 	char keybuf[MAXUDBKEY];
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate 	if (tTd(28, 1))
6057c478bd9Sstevel@tonic-gate 		sm_dprintf("udbmatch(%s, %s)\n", user, field);
6067c478bd9Sstevel@tonic-gate 
6077c478bd9Sstevel@tonic-gate 	if (!UdbInitialized)
6087c478bd9Sstevel@tonic-gate 	{
6097c478bd9Sstevel@tonic-gate 		if (_udbx_init(CurEnv) == EX_TEMPFAIL)
6107c478bd9Sstevel@tonic-gate 			return NULL;
6117c478bd9Sstevel@tonic-gate 	}
6127c478bd9Sstevel@tonic-gate 
6137c478bd9Sstevel@tonic-gate 	/* short circuit if no spec */
6147c478bd9Sstevel@tonic-gate 	if (UdbSpec == NULL || UdbSpec[0] == '\0')
6157c478bd9Sstevel@tonic-gate 		return NULL;
6167c478bd9Sstevel@tonic-gate 
6177c478bd9Sstevel@tonic-gate 	/* short circuit name begins with '\\' since it can't possibly match */
6187c478bd9Sstevel@tonic-gate 	if (user[0] == '\\')
6197c478bd9Sstevel@tonic-gate 		return NULL;
6207c478bd9Sstevel@tonic-gate 
6217c478bd9Sstevel@tonic-gate 	/* long names can never match and are a pain to deal with */
6227c478bd9Sstevel@tonic-gate 	i = strlen(field);
623*058561cbSjbeck 	if (i < sizeof("maildrop"))
624*058561cbSjbeck 		i = sizeof("maildrop");
625*058561cbSjbeck 	if ((strlen(user) + i) > sizeof(keybuf) - 4)
6267c478bd9Sstevel@tonic-gate 		return NULL;
6277c478bd9Sstevel@tonic-gate 
6287c478bd9Sstevel@tonic-gate 	/* names beginning with colons indicate metadata */
6297c478bd9Sstevel@tonic-gate 	if (user[0] == ':')
6307c478bd9Sstevel@tonic-gate 		return NULL;
6317c478bd9Sstevel@tonic-gate 
6327c478bd9Sstevel@tonic-gate 	/* build database key */
633*058561cbSjbeck 	(void) sm_strlcpyn(keybuf, sizeof(keybuf), 3, user, ":", field);
6347c478bd9Sstevel@tonic-gate 	keylen = strlen(keybuf);
6357c478bd9Sstevel@tonic-gate 
6367c478bd9Sstevel@tonic-gate 	for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
6377c478bd9Sstevel@tonic-gate 	{
6387c478bd9Sstevel@tonic-gate 		/*
6397c478bd9Sstevel@tonic-gate 		**  Select action based on entry type.
6407c478bd9Sstevel@tonic-gate 		*/
6417c478bd9Sstevel@tonic-gate 
6427c478bd9Sstevel@tonic-gate 		switch (up->udb_type)
6437c478bd9Sstevel@tonic-gate 		{
6447c478bd9Sstevel@tonic-gate # if NEWDB
6457c478bd9Sstevel@tonic-gate 		  case UDB_DBFETCH:
646*058561cbSjbeck 			memset(&key, '\0', sizeof(key));
647*058561cbSjbeck 			memset(&info, '\0', sizeof(info));
6487c478bd9Sstevel@tonic-gate 			key.data = keybuf;
6497c478bd9Sstevel@tonic-gate 			key.size = keylen;
6507c478bd9Sstevel@tonic-gate #  if DB_VERSION_MAJOR < 2
6517c478bd9Sstevel@tonic-gate 			i = (*up->udb_dbp->get)(up->udb_dbp, &key, &info, 0);
6527c478bd9Sstevel@tonic-gate #  else /* DB_VERSION_MAJOR < 2 */
6537c478bd9Sstevel@tonic-gate 			i = errno = (*up->udb_dbp->get)(up->udb_dbp, NULL,
6547c478bd9Sstevel@tonic-gate 							&key, &info, 0);
6557c478bd9Sstevel@tonic-gate #  endif /* DB_VERSION_MAJOR < 2 */
6567c478bd9Sstevel@tonic-gate 			if (i != 0 || info.size <= 0)
6577c478bd9Sstevel@tonic-gate 			{
6587c478bd9Sstevel@tonic-gate 				if (tTd(28, 2))
6597c478bd9Sstevel@tonic-gate 					sm_dprintf("udbmatch: no match on %s (%d) via db\n",
6607c478bd9Sstevel@tonic-gate 						keybuf, keylen);
6617c478bd9Sstevel@tonic-gate 				continue;
6627c478bd9Sstevel@tonic-gate 			}
6637c478bd9Sstevel@tonic-gate 
6647c478bd9Sstevel@tonic-gate 			p = sm_rpool_malloc_x(rpool, info.size + 1);
6657c478bd9Sstevel@tonic-gate 			memmove(p, info.data, info.size);
6667c478bd9Sstevel@tonic-gate 			p[info.size] = '\0';
6677c478bd9Sstevel@tonic-gate 			if (tTd(28, 1))
6687c478bd9Sstevel@tonic-gate 				sm_dprintf("udbmatch ==> %s\n", p);
6697c478bd9Sstevel@tonic-gate 			return p;
6707c478bd9Sstevel@tonic-gate # endif /* NEWDB */
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate # if HESIOD
6737c478bd9Sstevel@tonic-gate 		  case UDB_HESIOD:
6747c478bd9Sstevel@tonic-gate 			key.data = keybuf;
6757c478bd9Sstevel@tonic-gate 			key.size = keylen;
6767c478bd9Sstevel@tonic-gate 			i = hes_udb_get(&key, &info);
6777c478bd9Sstevel@tonic-gate 			if (i != 0 || info.size <= 0)
6787c478bd9Sstevel@tonic-gate 			{
6797c478bd9Sstevel@tonic-gate 				if (tTd(28, 2))
6807c478bd9Sstevel@tonic-gate 					sm_dprintf("udbmatch: no match on %s (%d) via hesiod\n",
6817c478bd9Sstevel@tonic-gate 						keybuf, keylen);
6827c478bd9Sstevel@tonic-gate 				continue;
6837c478bd9Sstevel@tonic-gate 			}
6847c478bd9Sstevel@tonic-gate 
6857c478bd9Sstevel@tonic-gate 			p = sm_rpool_malloc_x(rpool, info.size + 1);
6867c478bd9Sstevel@tonic-gate 			memmove(p, info.data, info.size);
6877c478bd9Sstevel@tonic-gate 			p[info.size] = '\0';
6887c478bd9Sstevel@tonic-gate 			if (tTd(28, 1))
6897c478bd9Sstevel@tonic-gate 				sm_dprintf("udbmatch ==> %s\n", p);
6907c478bd9Sstevel@tonic-gate 			return p;
6917c478bd9Sstevel@tonic-gate # endif /* HESIOD */
6927c478bd9Sstevel@tonic-gate 		}
6937c478bd9Sstevel@tonic-gate 	}
6947c478bd9Sstevel@tonic-gate 
6957c478bd9Sstevel@tonic-gate 	if (strcmp(field, "mailname") != 0)
6967c478bd9Sstevel@tonic-gate 		return NULL;
6977c478bd9Sstevel@tonic-gate 
6987c478bd9Sstevel@tonic-gate 	/*
6997c478bd9Sstevel@tonic-gate 	**  Nothing yet.  Search again for a default case.  But only
7007c478bd9Sstevel@tonic-gate 	**  use it if we also have a forward (:maildrop) pointer already
7017c478bd9Sstevel@tonic-gate 	**  in the database.
7027c478bd9Sstevel@tonic-gate 	*/
7037c478bd9Sstevel@tonic-gate 
7047c478bd9Sstevel@tonic-gate 	/* build database key */
705*058561cbSjbeck 	(void) sm_strlcpyn(keybuf, sizeof(keybuf), 2, user, ":maildrop");
7067c478bd9Sstevel@tonic-gate 	keylen = strlen(keybuf);
7077c478bd9Sstevel@tonic-gate 
7087c478bd9Sstevel@tonic-gate 	for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
7097c478bd9Sstevel@tonic-gate 	{
7107c478bd9Sstevel@tonic-gate 		switch (up->udb_type)
7117c478bd9Sstevel@tonic-gate 		{
7127c478bd9Sstevel@tonic-gate # if NEWDB
7137c478bd9Sstevel@tonic-gate 		  case UDB_DBFETCH:
7147c478bd9Sstevel@tonic-gate 			/* get the default case for this database */
7157c478bd9Sstevel@tonic-gate 			if (up->udb_default == NULL)
7167c478bd9Sstevel@tonic-gate 			{
717*058561cbSjbeck 				memset(&key, '\0', sizeof(key));
718*058561cbSjbeck 				memset(&info, '\0', sizeof(info));
7197c478bd9Sstevel@tonic-gate 				key.data = ":default:mailname";
7207c478bd9Sstevel@tonic-gate 				key.size = strlen(key.data);
7217c478bd9Sstevel@tonic-gate #  if DB_VERSION_MAJOR < 2
7227c478bd9Sstevel@tonic-gate 				i = (*up->udb_dbp->get)(up->udb_dbp,
7237c478bd9Sstevel@tonic-gate 							&key, &info, 0);
7247c478bd9Sstevel@tonic-gate #  else /* DB_VERSION_MAJOR < 2 */
7257c478bd9Sstevel@tonic-gate 				i = errno = (*up->udb_dbp->get)(up->udb_dbp,
7267c478bd9Sstevel@tonic-gate 								NULL, &key,
7277c478bd9Sstevel@tonic-gate 								&info, 0);
7287c478bd9Sstevel@tonic-gate #  endif /* DB_VERSION_MAJOR < 2 */
7297c478bd9Sstevel@tonic-gate 				if (i != 0 || info.size <= 0)
7307c478bd9Sstevel@tonic-gate 				{
7317c478bd9Sstevel@tonic-gate 					/* no default case */
7327c478bd9Sstevel@tonic-gate 					up->udb_default = "";
7337c478bd9Sstevel@tonic-gate 					continue;
7347c478bd9Sstevel@tonic-gate 				}
7357c478bd9Sstevel@tonic-gate 
7367c478bd9Sstevel@tonic-gate 				/* save the default case */
7377c478bd9Sstevel@tonic-gate 				up->udb_default = sm_pmalloc_x(info.size + 1);
7387c478bd9Sstevel@tonic-gate 				memmove(up->udb_default, info.data, info.size);
7397c478bd9Sstevel@tonic-gate 				up->udb_default[info.size] = '\0';
7407c478bd9Sstevel@tonic-gate 			}
7417c478bd9Sstevel@tonic-gate 			else if (up->udb_default[0] == '\0')
7427c478bd9Sstevel@tonic-gate 				continue;
7437c478bd9Sstevel@tonic-gate 
7447c478bd9Sstevel@tonic-gate 			/* we have a default case -- verify user:maildrop */
745*058561cbSjbeck 			memset(&key, '\0', sizeof(key));
746*058561cbSjbeck 			memset(&info, '\0', sizeof(info));
7477c478bd9Sstevel@tonic-gate 			key.data = keybuf;
7487c478bd9Sstevel@tonic-gate 			key.size = keylen;
7497c478bd9Sstevel@tonic-gate #  if DB_VERSION_MAJOR < 2
7507c478bd9Sstevel@tonic-gate 			i = (*up->udb_dbp->get)(up->udb_dbp, &key, &info, 0);
7517c478bd9Sstevel@tonic-gate #  else /* DB_VERSION_MAJOR < 2 */
7527c478bd9Sstevel@tonic-gate 			i = errno = (*up->udb_dbp->get)(up->udb_dbp, NULL,
7537c478bd9Sstevel@tonic-gate 							&key, &info, 0);
7547c478bd9Sstevel@tonic-gate #  endif /* DB_VERSION_MAJOR < 2 */
7557c478bd9Sstevel@tonic-gate 			if (i != 0 || info.size <= 0)
7567c478bd9Sstevel@tonic-gate 			{
7577c478bd9Sstevel@tonic-gate 				/* nope -- no aliasing for this user */
7587c478bd9Sstevel@tonic-gate 				continue;
7597c478bd9Sstevel@tonic-gate 			}
7607c478bd9Sstevel@tonic-gate 
7617c478bd9Sstevel@tonic-gate 			/* they exist -- build the actual address */
7627c478bd9Sstevel@tonic-gate 			i = strlen(user) + strlen(up->udb_default) + 2;
7637c478bd9Sstevel@tonic-gate 			p = sm_rpool_malloc_x(rpool, i);
7647c478bd9Sstevel@tonic-gate 			(void) sm_strlcpyn(p, i, 3, user, "@", up->udb_default);
7657c478bd9Sstevel@tonic-gate 			if (tTd(28, 1))
7667c478bd9Sstevel@tonic-gate 				sm_dprintf("udbmatch ==> %s\n", p);
7677c478bd9Sstevel@tonic-gate 			return p;
7687c478bd9Sstevel@tonic-gate # endif /* NEWDB */
7697c478bd9Sstevel@tonic-gate 
7707c478bd9Sstevel@tonic-gate # if HESIOD
7717c478bd9Sstevel@tonic-gate 		  case UDB_HESIOD:
7727c478bd9Sstevel@tonic-gate 			/* get the default case for this database */
7737c478bd9Sstevel@tonic-gate 			if (up->udb_default == NULL)
7747c478bd9Sstevel@tonic-gate 			{
7757c478bd9Sstevel@tonic-gate 				key.data = ":default:mailname";
7767c478bd9Sstevel@tonic-gate 				key.size = strlen(key.data);
7777c478bd9Sstevel@tonic-gate 				i = hes_udb_get(&key, &info);
7787c478bd9Sstevel@tonic-gate 
7797c478bd9Sstevel@tonic-gate 				if (i != 0 || info.size <= 0)
7807c478bd9Sstevel@tonic-gate 				{
7817c478bd9Sstevel@tonic-gate 					/* no default case */
7827c478bd9Sstevel@tonic-gate 					up->udb_default = "";
7837c478bd9Sstevel@tonic-gate 					continue;
7847c478bd9Sstevel@tonic-gate 				}
7857c478bd9Sstevel@tonic-gate 
7867c478bd9Sstevel@tonic-gate 				/* save the default case */
7877c478bd9Sstevel@tonic-gate 				up->udb_default = sm_pmalloc_x(info.size + 1);
7887c478bd9Sstevel@tonic-gate 				memmove(up->udb_default, info.data, info.size);
7897c478bd9Sstevel@tonic-gate 				up->udb_default[info.size] = '\0';
7907c478bd9Sstevel@tonic-gate 			}
7917c478bd9Sstevel@tonic-gate 			else if (up->udb_default[0] == '\0')
7927c478bd9Sstevel@tonic-gate 				continue;
7937c478bd9Sstevel@tonic-gate 
7947c478bd9Sstevel@tonic-gate 			/* we have a default case -- verify user:maildrop */
7957c478bd9Sstevel@tonic-gate 			key.data = keybuf;
7967c478bd9Sstevel@tonic-gate 			key.size = keylen;
7977c478bd9Sstevel@tonic-gate 			i = hes_udb_get(&key, &info);
7987c478bd9Sstevel@tonic-gate 			if (i != 0 || info.size <= 0)
7997c478bd9Sstevel@tonic-gate 			{
8007c478bd9Sstevel@tonic-gate 				/* nope -- no aliasing for this user */
8017c478bd9Sstevel@tonic-gate 				continue;
8027c478bd9Sstevel@tonic-gate 			}
8037c478bd9Sstevel@tonic-gate 
8047c478bd9Sstevel@tonic-gate 			/* they exist -- build the actual address */
8057c478bd9Sstevel@tonic-gate 			i = strlen(user) + strlen(up->udb_default) + 2;
8067c478bd9Sstevel@tonic-gate 			p = sm_rpool_malloc_x(rpool, i);
8077c478bd9Sstevel@tonic-gate 			(void) sm_strlcpyn(p, i, 3, user, "@", up->udb_default);
8087c478bd9Sstevel@tonic-gate 			if (tTd(28, 1))
8097c478bd9Sstevel@tonic-gate 				sm_dprintf("udbmatch ==> %s\n", p);
8107c478bd9Sstevel@tonic-gate 			return p;
8117c478bd9Sstevel@tonic-gate 			break;
8127c478bd9Sstevel@tonic-gate # endif /* HESIOD */
8137c478bd9Sstevel@tonic-gate 		}
8147c478bd9Sstevel@tonic-gate 	}
8157c478bd9Sstevel@tonic-gate 
8167c478bd9Sstevel@tonic-gate 	/* still nothing....  too bad */
8177c478bd9Sstevel@tonic-gate 	return NULL;
8187c478bd9Sstevel@tonic-gate }
8197c478bd9Sstevel@tonic-gate /*
8207c478bd9Sstevel@tonic-gate **  UDB_MAP_LOOKUP -- look up arbitrary entry in user database map
8217c478bd9Sstevel@tonic-gate **
8227c478bd9Sstevel@tonic-gate **	Parameters:
8237c478bd9Sstevel@tonic-gate **		map -- the map being queried.
8247c478bd9Sstevel@tonic-gate **		name -- the name to look up.
8257c478bd9Sstevel@tonic-gate **		av -- arguments to the map lookup.
8267c478bd9Sstevel@tonic-gate **		statp -- to get any error status.
8277c478bd9Sstevel@tonic-gate **
8287c478bd9Sstevel@tonic-gate **	Returns:
8297c478bd9Sstevel@tonic-gate **		NULL if name not found in map.
8307c478bd9Sstevel@tonic-gate **		The rewritten name otherwise.
8317c478bd9Sstevel@tonic-gate */
8327c478bd9Sstevel@tonic-gate 
8337c478bd9Sstevel@tonic-gate /* ARGSUSED3 */
8347c478bd9Sstevel@tonic-gate char *
udb_map_lookup(map,name,av,statp)8357c478bd9Sstevel@tonic-gate udb_map_lookup(map, name, av, statp)
8367c478bd9Sstevel@tonic-gate 	MAP *map;
8377c478bd9Sstevel@tonic-gate 	char *name;
8387c478bd9Sstevel@tonic-gate 	char **av;
8397c478bd9Sstevel@tonic-gate 	int *statp;
8407c478bd9Sstevel@tonic-gate {
8417c478bd9Sstevel@tonic-gate 	char *val;
8427c478bd9Sstevel@tonic-gate 	char *key;
8437c478bd9Sstevel@tonic-gate 	char *SM_NONVOLATILE result = NULL;
8447c478bd9Sstevel@tonic-gate 	char keybuf[MAXNAME + 1];
8457c478bd9Sstevel@tonic-gate 
8467c478bd9Sstevel@tonic-gate 	if (tTd(28, 20) || tTd(38, 20))
8477c478bd9Sstevel@tonic-gate 		sm_dprintf("udb_map_lookup(%s, %s)\n", map->map_mname, name);
8487c478bd9Sstevel@tonic-gate 
8497c478bd9Sstevel@tonic-gate 	if (bitset(MF_NOFOLDCASE, map->map_mflags))
8507c478bd9Sstevel@tonic-gate 	{
8517c478bd9Sstevel@tonic-gate 		key = name;
8527c478bd9Sstevel@tonic-gate 	}
8537c478bd9Sstevel@tonic-gate 	else
8547c478bd9Sstevel@tonic-gate 	{
8557c478bd9Sstevel@tonic-gate 		int keysize = strlen(name);
8567c478bd9Sstevel@tonic-gate 
857*058561cbSjbeck 		if (keysize > sizeof(keybuf) - 1)
858*058561cbSjbeck 			keysize = sizeof(keybuf) - 1;
8597c478bd9Sstevel@tonic-gate 		memmove(keybuf, name, keysize);
8607c478bd9Sstevel@tonic-gate 		keybuf[keysize] = '\0';
8617c478bd9Sstevel@tonic-gate 		makelower(keybuf);
8627c478bd9Sstevel@tonic-gate 		key = keybuf;
8637c478bd9Sstevel@tonic-gate 	}
8647c478bd9Sstevel@tonic-gate 	val = udbmatch(key, map->map_file, NULL);
8657c478bd9Sstevel@tonic-gate 	if (val == NULL)
8667c478bd9Sstevel@tonic-gate 		return NULL;
8677c478bd9Sstevel@tonic-gate 	SM_TRY
8687c478bd9Sstevel@tonic-gate 		if (bitset(MF_MATCHONLY, map->map_mflags))
8697c478bd9Sstevel@tonic-gate 			result = map_rewrite(map, name, strlen(name), NULL);
8707c478bd9Sstevel@tonic-gate 		else
8717c478bd9Sstevel@tonic-gate 			result = map_rewrite(map, val, strlen(val), av);
8727c478bd9Sstevel@tonic-gate 	SM_FINALLY
8737c478bd9Sstevel@tonic-gate 		sm_free(val);
8747c478bd9Sstevel@tonic-gate 	SM_END_TRY
8757c478bd9Sstevel@tonic-gate 	return result;
8767c478bd9Sstevel@tonic-gate }
8777c478bd9Sstevel@tonic-gate /*
8787c478bd9Sstevel@tonic-gate **  _UDBX_INIT -- parse the UDB specification, opening any valid entries.
8797c478bd9Sstevel@tonic-gate **
8807c478bd9Sstevel@tonic-gate **	Parameters:
8817c478bd9Sstevel@tonic-gate **		e -- the current envelope.
8827c478bd9Sstevel@tonic-gate **
8837c478bd9Sstevel@tonic-gate **	Returns:
8847c478bd9Sstevel@tonic-gate **		EX_TEMPFAIL -- if it appeared it couldn't get hold of a
8857c478bd9Sstevel@tonic-gate **			database due to a host being down or some similar
8867c478bd9Sstevel@tonic-gate **			(recoverable) situation.
8877c478bd9Sstevel@tonic-gate **		EX_OK -- otherwise.
8887c478bd9Sstevel@tonic-gate **
8897c478bd9Sstevel@tonic-gate **	Side Effects:
8907c478bd9Sstevel@tonic-gate **		Fills in the UdbEnts structure from UdbSpec.
8917c478bd9Sstevel@tonic-gate */
8927c478bd9Sstevel@tonic-gate 
8937c478bd9Sstevel@tonic-gate # define MAXUDBOPTS	27
8947c478bd9Sstevel@tonic-gate 
8957c478bd9Sstevel@tonic-gate static int
_udbx_init(e)8967c478bd9Sstevel@tonic-gate _udbx_init(e)
8977c478bd9Sstevel@tonic-gate 	ENVELOPE *e;
8987c478bd9Sstevel@tonic-gate {
8997c478bd9Sstevel@tonic-gate 	int ents = 0;
9007c478bd9Sstevel@tonic-gate 	register char *p;
9017c478bd9Sstevel@tonic-gate 	register struct udbent *up;
9027c478bd9Sstevel@tonic-gate 
9037c478bd9Sstevel@tonic-gate 	if (UdbInitialized)
9047c478bd9Sstevel@tonic-gate 		return EX_OK;
9057c478bd9Sstevel@tonic-gate 
9067c478bd9Sstevel@tonic-gate # ifdef UDB_DEFAULT_SPEC
9077c478bd9Sstevel@tonic-gate 	if (UdbSpec == NULL)
9087c478bd9Sstevel@tonic-gate 		UdbSpec = UDB_DEFAULT_SPEC;
9097c478bd9Sstevel@tonic-gate # endif /* UDB_DEFAULT_SPEC */
9107c478bd9Sstevel@tonic-gate 
9117c478bd9Sstevel@tonic-gate 	p = UdbSpec;
9127c478bd9Sstevel@tonic-gate 	up = UdbEnts;
9137c478bd9Sstevel@tonic-gate 	while (p != NULL)
9147c478bd9Sstevel@tonic-gate 	{
9157c478bd9Sstevel@tonic-gate 		char *spec;
9167c478bd9Sstevel@tonic-gate 		int l;
9177c478bd9Sstevel@tonic-gate 		struct udb_option opts[MAXUDBOPTS + 1];
9187c478bd9Sstevel@tonic-gate 
9197c478bd9Sstevel@tonic-gate 		while (*p == ' ' || *p == '\t' || *p == ',')
9207c478bd9Sstevel@tonic-gate 			p++;
9217c478bd9Sstevel@tonic-gate 		if (*p == '\0')
9227c478bd9Sstevel@tonic-gate 			break;
9237c478bd9Sstevel@tonic-gate 		spec = p;
9247c478bd9Sstevel@tonic-gate 		p = strchr(p, ',');
9257c478bd9Sstevel@tonic-gate 		if (p != NULL)
9267c478bd9Sstevel@tonic-gate 			*p++ = '\0';
9277c478bd9Sstevel@tonic-gate 
9287c478bd9Sstevel@tonic-gate 		if (ents >= MAXUDBENT)
9297c478bd9Sstevel@tonic-gate 		{
9307c478bd9Sstevel@tonic-gate 			syserr("Maximum number of UDB entries exceeded");
9317c478bd9Sstevel@tonic-gate 			break;
9327c478bd9Sstevel@tonic-gate 		}
9337c478bd9Sstevel@tonic-gate 
9347c478bd9Sstevel@tonic-gate 		/* extract options */
9357c478bd9Sstevel@tonic-gate 		(void) _udb_parsespec(spec, opts, MAXUDBOPTS);
9367c478bd9Sstevel@tonic-gate 
9377c478bd9Sstevel@tonic-gate 		/*
9387c478bd9Sstevel@tonic-gate 		**  Decode database specification.
9397c478bd9Sstevel@tonic-gate 		**
9407c478bd9Sstevel@tonic-gate 		**	In the sendmail tradition, the leading character
9417c478bd9Sstevel@tonic-gate 		**	defines the semantics of the rest of the entry.
9427c478bd9Sstevel@tonic-gate 		**
9437c478bd9Sstevel@tonic-gate 		**	@hostname --	forward email to the indicated host.
9447c478bd9Sstevel@tonic-gate 		**			This should be the last in the list,
9457c478bd9Sstevel@tonic-gate 		**			since it always matches the input.
9467c478bd9Sstevel@tonic-gate 		**	/dbname	 --	search the named database on the local
9477c478bd9Sstevel@tonic-gate 		**			host using the Berkeley db package.
9487c478bd9Sstevel@tonic-gate 		**	Hesiod --	search the named database with BIND
9497c478bd9Sstevel@tonic-gate 		**			using the MIT Hesiod package.
9507c478bd9Sstevel@tonic-gate 		*/
9517c478bd9Sstevel@tonic-gate 
9527c478bd9Sstevel@tonic-gate 		switch (*spec)
9537c478bd9Sstevel@tonic-gate 		{
9547c478bd9Sstevel@tonic-gate 		  case '@':	/* forward to remote host */
9557c478bd9Sstevel@tonic-gate 			up->udb_type = UDB_FORWARD;
9567c478bd9Sstevel@tonic-gate 			up->udb_pid = CurrentPid;
9577c478bd9Sstevel@tonic-gate 			up->udb_fwdhost = spec + 1;
9587c478bd9Sstevel@tonic-gate 			ents++;
9597c478bd9Sstevel@tonic-gate 			up++;
9607c478bd9Sstevel@tonic-gate 			break;
9617c478bd9Sstevel@tonic-gate 
9627c478bd9Sstevel@tonic-gate # if HESIOD
9637c478bd9Sstevel@tonic-gate 		  case 'h':	/* use hesiod */
9647c478bd9Sstevel@tonic-gate 		  case 'H':
9657c478bd9Sstevel@tonic-gate 			if (sm_strcasecmp(spec, "hesiod") != 0)
9667c478bd9Sstevel@tonic-gate 				goto badspec;
9677c478bd9Sstevel@tonic-gate 			up->udb_type = UDB_HESIOD;
9687c478bd9Sstevel@tonic-gate 			up->udb_pid = CurrentPid;
9697c478bd9Sstevel@tonic-gate 			ents++;
9707c478bd9Sstevel@tonic-gate 			up++;
9717c478bd9Sstevel@tonic-gate 			break;
9727c478bd9Sstevel@tonic-gate # endif /* HESIOD */
9737c478bd9Sstevel@tonic-gate 
9747c478bd9Sstevel@tonic-gate # if NEWDB
9757c478bd9Sstevel@tonic-gate 		  case '/':	/* look up remote name */
9767c478bd9Sstevel@tonic-gate 			l = strlen(spec);
9777c478bd9Sstevel@tonic-gate 			if (l > 3 && strcmp(&spec[l - 3], ".db") == 0)
9787c478bd9Sstevel@tonic-gate 			{
9797c478bd9Sstevel@tonic-gate 				up->udb_dbname = spec;
9807c478bd9Sstevel@tonic-gate 			}
9817c478bd9Sstevel@tonic-gate 			else
9827c478bd9Sstevel@tonic-gate 			{
9837c478bd9Sstevel@tonic-gate 				up->udb_dbname = sm_pmalloc_x(l + 4);
9847c478bd9Sstevel@tonic-gate 				(void) sm_strlcpyn(up->udb_dbname, l + 4, 2,
9857c478bd9Sstevel@tonic-gate 						   spec, ".db");
9867c478bd9Sstevel@tonic-gate 			}
9877c478bd9Sstevel@tonic-gate 			errno = 0;
9887c478bd9Sstevel@tonic-gate #  if DB_VERSION_MAJOR < 2
9897c478bd9Sstevel@tonic-gate 			up->udb_dbp = dbopen(up->udb_dbname, O_RDONLY,
9907c478bd9Sstevel@tonic-gate 					     0644, DB_BTREE, NULL);
9917c478bd9Sstevel@tonic-gate #  else /* DB_VERSION_MAJOR < 2 */
9927c478bd9Sstevel@tonic-gate 			{
9937c478bd9Sstevel@tonic-gate 				int flags = DB_RDONLY;
9947c478bd9Sstevel@tonic-gate #  if DB_VERSION_MAJOR > 2
9957c478bd9Sstevel@tonic-gate 				int ret;
9967c478bd9Sstevel@tonic-gate #  endif /* DB_VERSION_MAJOR > 2 */
9977c478bd9Sstevel@tonic-gate 
9987c478bd9Sstevel@tonic-gate 				SM_DB_FLAG_ADD(flags);
9997c478bd9Sstevel@tonic-gate 				up->udb_dbp = NULL;
10007c478bd9Sstevel@tonic-gate #  if DB_VERSION_MAJOR > 2
10017c478bd9Sstevel@tonic-gate 				ret = db_create(&up->udb_dbp, NULL, 0);
10027c478bd9Sstevel@tonic-gate 				if (ret != 0)
10037c478bd9Sstevel@tonic-gate 				{
10047c478bd9Sstevel@tonic-gate 					(void) up->udb_dbp->close(up->udb_dbp,
10057c478bd9Sstevel@tonic-gate 								  0);
10067c478bd9Sstevel@tonic-gate 					up->udb_dbp = NULL;
10077c478bd9Sstevel@tonic-gate 				}
10087c478bd9Sstevel@tonic-gate 				else
10097c478bd9Sstevel@tonic-gate 				{
10107c478bd9Sstevel@tonic-gate 					ret = up->udb_dbp->open(up->udb_dbp,
10117c478bd9Sstevel@tonic-gate 								DBTXN
10127c478bd9Sstevel@tonic-gate 								up->udb_dbname,
10137c478bd9Sstevel@tonic-gate 								NULL,
10147c478bd9Sstevel@tonic-gate 								DB_BTREE,
10157c478bd9Sstevel@tonic-gate 								flags,
10167c478bd9Sstevel@tonic-gate 								0644);
10177c478bd9Sstevel@tonic-gate 					if (ret != 0)
10187c478bd9Sstevel@tonic-gate 					{
10197c478bd9Sstevel@tonic-gate #ifdef DB_OLD_VERSION
10207c478bd9Sstevel@tonic-gate 						if (ret == DB_OLD_VERSION)
10217c478bd9Sstevel@tonic-gate 							ret = EINVAL;
10227c478bd9Sstevel@tonic-gate #endif /* DB_OLD_VERSION */
10237c478bd9Sstevel@tonic-gate 						(void) up->udb_dbp->close(up->udb_dbp, 0);
10247c478bd9Sstevel@tonic-gate 						up->udb_dbp = NULL;
10257c478bd9Sstevel@tonic-gate 					}
10267c478bd9Sstevel@tonic-gate 				}
10277c478bd9Sstevel@tonic-gate 				errno = ret;
10287c478bd9Sstevel@tonic-gate #  else /* DB_VERSION_MAJOR > 2 */
10297c478bd9Sstevel@tonic-gate 				errno = db_open(up->udb_dbname, DB_BTREE,
10307c478bd9Sstevel@tonic-gate 						flags, 0644, NULL,
10317c478bd9Sstevel@tonic-gate 						NULL, &up->udb_dbp);
10327c478bd9Sstevel@tonic-gate #  endif /* DB_VERSION_MAJOR > 2 */
10337c478bd9Sstevel@tonic-gate 			}
10347c478bd9Sstevel@tonic-gate #  endif /* DB_VERSION_MAJOR < 2 */
10357c478bd9Sstevel@tonic-gate 			if (up->udb_dbp == NULL)
10367c478bd9Sstevel@tonic-gate 			{
10377c478bd9Sstevel@tonic-gate 				if (tTd(28, 1))
10387c478bd9Sstevel@tonic-gate 				{
10397c478bd9Sstevel@tonic-gate 					int save_errno = errno;
10407c478bd9Sstevel@tonic-gate 
10417c478bd9Sstevel@tonic-gate #  if DB_VERSION_MAJOR < 2
10427c478bd9Sstevel@tonic-gate 					sm_dprintf("dbopen(%s): %s\n",
10437c478bd9Sstevel@tonic-gate #  else /* DB_VERSION_MAJOR < 2 */
10447c478bd9Sstevel@tonic-gate 					sm_dprintf("db_open(%s): %s\n",
10457c478bd9Sstevel@tonic-gate #  endif /* DB_VERSION_MAJOR < 2 */
10467c478bd9Sstevel@tonic-gate 						up->udb_dbname,
10477c478bd9Sstevel@tonic-gate 						sm_errstring(errno));
10487c478bd9Sstevel@tonic-gate 					errno = save_errno;
10497c478bd9Sstevel@tonic-gate 				}
10507c478bd9Sstevel@tonic-gate 				if (errno != ENOENT && errno != EACCES)
10517c478bd9Sstevel@tonic-gate 				{
10527c478bd9Sstevel@tonic-gate 					if (LogLevel > 2)
10537c478bd9Sstevel@tonic-gate 						sm_syslog(LOG_ERR, e->e_id,
10547c478bd9Sstevel@tonic-gate #  if DB_VERSION_MAJOR < 2
10557c478bd9Sstevel@tonic-gate 							  "dbopen(%s): %s",
10567c478bd9Sstevel@tonic-gate #  else /* DB_VERSION_MAJOR < 2 */
10577c478bd9Sstevel@tonic-gate 							  "db_open(%s): %s",
10587c478bd9Sstevel@tonic-gate #  endif /* DB_VERSION_MAJOR < 2 */
10597c478bd9Sstevel@tonic-gate 							  up->udb_dbname,
10607c478bd9Sstevel@tonic-gate 							  sm_errstring(errno));
10617c478bd9Sstevel@tonic-gate 					up->udb_type = UDB_EOLIST;
10627c478bd9Sstevel@tonic-gate 					if (up->udb_dbname != spec)
10637c478bd9Sstevel@tonic-gate 						sm_free(up->udb_dbname); /* XXX */
10647c478bd9Sstevel@tonic-gate 					goto tempfail;
10657c478bd9Sstevel@tonic-gate 				}
10667c478bd9Sstevel@tonic-gate 				if (up->udb_dbname != spec)
10677c478bd9Sstevel@tonic-gate 					sm_free(up->udb_dbname); /* XXX */
10687c478bd9Sstevel@tonic-gate 				break;
10697c478bd9Sstevel@tonic-gate 			}
10707c478bd9Sstevel@tonic-gate 			if (tTd(28, 1))
10717c478bd9Sstevel@tonic-gate 			{
10727c478bd9Sstevel@tonic-gate #  if DB_VERSION_MAJOR < 2
10737c478bd9Sstevel@tonic-gate 				sm_dprintf("_udbx_init: dbopen(%s)\n",
10747c478bd9Sstevel@tonic-gate #  else /* DB_VERSION_MAJOR < 2 */
10757c478bd9Sstevel@tonic-gate 				sm_dprintf("_udbx_init: db_open(%s)\n",
10767c478bd9Sstevel@tonic-gate #  endif /* DB_VERSION_MAJOR < 2 */
10777c478bd9Sstevel@tonic-gate 					up->udb_dbname);
10787c478bd9Sstevel@tonic-gate 			}
10797c478bd9Sstevel@tonic-gate 			up->udb_type = UDB_DBFETCH;
10807c478bd9Sstevel@tonic-gate 			up->udb_pid = CurrentPid;
10817c478bd9Sstevel@tonic-gate 			ents++;
10827c478bd9Sstevel@tonic-gate 			up++;
10837c478bd9Sstevel@tonic-gate 			break;
10847c478bd9Sstevel@tonic-gate # endif /* NEWDB */
10857c478bd9Sstevel@tonic-gate 
10867c478bd9Sstevel@tonic-gate 		  default:
10877c478bd9Sstevel@tonic-gate # if HESIOD
10887c478bd9Sstevel@tonic-gate badspec:
10897c478bd9Sstevel@tonic-gate # endif /* HESIOD */
10907c478bd9Sstevel@tonic-gate 			syserr("Unknown UDB spec %s", spec);
10917c478bd9Sstevel@tonic-gate 			break;
10927c478bd9Sstevel@tonic-gate 		}
10937c478bd9Sstevel@tonic-gate 	}
10947c478bd9Sstevel@tonic-gate 	up->udb_type = UDB_EOLIST;
10957c478bd9Sstevel@tonic-gate 
10967c478bd9Sstevel@tonic-gate 	if (tTd(28, 4))
10977c478bd9Sstevel@tonic-gate 	{
10987c478bd9Sstevel@tonic-gate 		for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
10997c478bd9Sstevel@tonic-gate 		{
11007c478bd9Sstevel@tonic-gate 			switch (up->udb_type)
11017c478bd9Sstevel@tonic-gate 			{
11027c478bd9Sstevel@tonic-gate 			  case UDB_REMOTE:
11037c478bd9Sstevel@tonic-gate 				sm_dprintf("REMOTE: addr %s, timeo %d\n",
11047c478bd9Sstevel@tonic-gate 					   anynet_ntoa((SOCKADDR *) &up->udb_addr),
11057c478bd9Sstevel@tonic-gate 					   up->udb_timeout);
11067c478bd9Sstevel@tonic-gate 				break;
11077c478bd9Sstevel@tonic-gate 
11087c478bd9Sstevel@tonic-gate 			  case UDB_DBFETCH:
11097c478bd9Sstevel@tonic-gate # if NEWDB
11107c478bd9Sstevel@tonic-gate 				sm_dprintf("FETCH: file %s\n",
11117c478bd9Sstevel@tonic-gate 					up->udb_dbname);
11127c478bd9Sstevel@tonic-gate # else /* NEWDB */
11137c478bd9Sstevel@tonic-gate 				sm_dprintf("FETCH\n");
11147c478bd9Sstevel@tonic-gate # endif /* NEWDB */
11157c478bd9Sstevel@tonic-gate 				break;
11167c478bd9Sstevel@tonic-gate 
11177c478bd9Sstevel@tonic-gate 			  case UDB_FORWARD:
11187c478bd9Sstevel@tonic-gate 				sm_dprintf("FORWARD: host %s\n",
11197c478bd9Sstevel@tonic-gate 					up->udb_fwdhost);
11207c478bd9Sstevel@tonic-gate 				break;
11217c478bd9Sstevel@tonic-gate 
11227c478bd9Sstevel@tonic-gate 			  case UDB_HESIOD:
11237c478bd9Sstevel@tonic-gate 				sm_dprintf("HESIOD\n");
11247c478bd9Sstevel@tonic-gate 				break;
11257c478bd9Sstevel@tonic-gate 
11267c478bd9Sstevel@tonic-gate 			  default:
11277c478bd9Sstevel@tonic-gate 				sm_dprintf("UNKNOWN\n");
11287c478bd9Sstevel@tonic-gate 				break;
11297c478bd9Sstevel@tonic-gate 			}
11307c478bd9Sstevel@tonic-gate 		}
11317c478bd9Sstevel@tonic-gate 	}
11327c478bd9Sstevel@tonic-gate 
11337c478bd9Sstevel@tonic-gate 	UdbInitialized = true;
11347c478bd9Sstevel@tonic-gate 	errno = 0;
11357c478bd9Sstevel@tonic-gate 	return EX_OK;
11367c478bd9Sstevel@tonic-gate 
11377c478bd9Sstevel@tonic-gate 	/*
11387c478bd9Sstevel@tonic-gate 	**  On temporary failure, back out anything we've already done
11397c478bd9Sstevel@tonic-gate 	*/
11407c478bd9Sstevel@tonic-gate 
11417c478bd9Sstevel@tonic-gate   tempfail:
11427c478bd9Sstevel@tonic-gate # if NEWDB
11437c478bd9Sstevel@tonic-gate 	for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
11447c478bd9Sstevel@tonic-gate 	{
11457c478bd9Sstevel@tonic-gate 		if (up->udb_type == UDB_DBFETCH)
11467c478bd9Sstevel@tonic-gate 		{
11477c478bd9Sstevel@tonic-gate #  if DB_VERSION_MAJOR < 2
11487c478bd9Sstevel@tonic-gate 			(*up->udb_dbp->close)(up->udb_dbp);
11497c478bd9Sstevel@tonic-gate #  else /* DB_VERSION_MAJOR < 2 */
11507c478bd9Sstevel@tonic-gate 			errno = (*up->udb_dbp->close)(up->udb_dbp, 0);
11517c478bd9Sstevel@tonic-gate #  endif /* DB_VERSION_MAJOR < 2 */
11527c478bd9Sstevel@tonic-gate 			if (tTd(28, 1))
11537c478bd9Sstevel@tonic-gate 				sm_dprintf("_udbx_init: db->close(%s)\n",
11547c478bd9Sstevel@tonic-gate 					up->udb_dbname);
11557c478bd9Sstevel@tonic-gate 		}
11567c478bd9Sstevel@tonic-gate 	}
11577c478bd9Sstevel@tonic-gate # endif /* NEWDB */
11587c478bd9Sstevel@tonic-gate 	return EX_TEMPFAIL;
11597c478bd9Sstevel@tonic-gate }
11607c478bd9Sstevel@tonic-gate 
11617c478bd9Sstevel@tonic-gate static int
_udb_parsespec(udbspec,opt,maxopts)11627c478bd9Sstevel@tonic-gate _udb_parsespec(udbspec, opt, maxopts)
11637c478bd9Sstevel@tonic-gate 	char *udbspec;
11647c478bd9Sstevel@tonic-gate 	struct udb_option opt[];
11657c478bd9Sstevel@tonic-gate 	int maxopts;
11667c478bd9Sstevel@tonic-gate {
11677c478bd9Sstevel@tonic-gate 	register char *spec;
11687c478bd9Sstevel@tonic-gate 	register char *spec_end;
11697c478bd9Sstevel@tonic-gate 	register int optnum;
11707c478bd9Sstevel@tonic-gate 
11717c478bd9Sstevel@tonic-gate 	spec_end = strchr(udbspec, ':');
11727c478bd9Sstevel@tonic-gate 	for (optnum = 0; optnum < maxopts && (spec = spec_end) != NULL; optnum++)
11737c478bd9Sstevel@tonic-gate 	{
11747c478bd9Sstevel@tonic-gate 		register char *p;
11757c478bd9Sstevel@tonic-gate 
11767c478bd9Sstevel@tonic-gate 		while (isascii(*spec) && isspace(*spec))
11777c478bd9Sstevel@tonic-gate 			spec++;
11787c478bd9Sstevel@tonic-gate 		spec_end = strchr(spec, ':');
11797c478bd9Sstevel@tonic-gate 		if (spec_end != NULL)
11807c478bd9Sstevel@tonic-gate 			*spec_end++ = '\0';
11817c478bd9Sstevel@tonic-gate 
11827c478bd9Sstevel@tonic-gate 		opt[optnum].udbo_name = spec;
11837c478bd9Sstevel@tonic-gate 		opt[optnum].udbo_val = NULL;
11847c478bd9Sstevel@tonic-gate 		p = strchr(spec, '=');
11857c478bd9Sstevel@tonic-gate 		if (p != NULL)
11867c478bd9Sstevel@tonic-gate 			opt[optnum].udbo_val = ++p;
11877c478bd9Sstevel@tonic-gate 	}
11887c478bd9Sstevel@tonic-gate 	return optnum;
11897c478bd9Sstevel@tonic-gate }
11907c478bd9Sstevel@tonic-gate /*
11917c478bd9Sstevel@tonic-gate **  _UDBX_CLOSE -- close all file based UDB entries.
11927c478bd9Sstevel@tonic-gate **
11937c478bd9Sstevel@tonic-gate **	Parameters:
11947c478bd9Sstevel@tonic-gate **		none
11957c478bd9Sstevel@tonic-gate **
11967c478bd9Sstevel@tonic-gate **	Returns:
11977c478bd9Sstevel@tonic-gate **		none
11987c478bd9Sstevel@tonic-gate */
11997c478bd9Sstevel@tonic-gate void
_udbx_close()12007c478bd9Sstevel@tonic-gate _udbx_close()
12017c478bd9Sstevel@tonic-gate {
12027c478bd9Sstevel@tonic-gate 	struct udbent *up;
12037c478bd9Sstevel@tonic-gate 
12047c478bd9Sstevel@tonic-gate 	if (!UdbInitialized)
12057c478bd9Sstevel@tonic-gate 		return;
12067c478bd9Sstevel@tonic-gate 
12077c478bd9Sstevel@tonic-gate 	for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
12087c478bd9Sstevel@tonic-gate 	{
12097c478bd9Sstevel@tonic-gate 		if (up->udb_pid != CurrentPid)
12107c478bd9Sstevel@tonic-gate 			continue;
12117c478bd9Sstevel@tonic-gate 
12127c478bd9Sstevel@tonic-gate # if NEWDB
12137c478bd9Sstevel@tonic-gate 		if (up->udb_type == UDB_DBFETCH)
12147c478bd9Sstevel@tonic-gate 		{
12157c478bd9Sstevel@tonic-gate #  if DB_VERSION_MAJOR < 2
12167c478bd9Sstevel@tonic-gate 			(*up->udb_dbp->close)(up->udb_dbp);
12177c478bd9Sstevel@tonic-gate #  else /* DB_VERSION_MAJOR < 2 */
12187c478bd9Sstevel@tonic-gate 			errno = (*up->udb_dbp->close)(up->udb_dbp, 0);
12197c478bd9Sstevel@tonic-gate #  endif /* DB_VERSION_MAJOR < 2 */
12207c478bd9Sstevel@tonic-gate 		}
12217c478bd9Sstevel@tonic-gate 		if (tTd(28, 1))
12227c478bd9Sstevel@tonic-gate 			sm_dprintf("_udbx_init: db->close(%s)\n",
12237c478bd9Sstevel@tonic-gate 				up->udb_dbname);
12247c478bd9Sstevel@tonic-gate # endif /* NEWDB */
12257c478bd9Sstevel@tonic-gate 	}
12267c478bd9Sstevel@tonic-gate }
12277c478bd9Sstevel@tonic-gate 
12287c478bd9Sstevel@tonic-gate # if HESIOD
12297c478bd9Sstevel@tonic-gate 
12307c478bd9Sstevel@tonic-gate static int
hes_udb_get(key,info)12317c478bd9Sstevel@tonic-gate hes_udb_get(key, info)
12327c478bd9Sstevel@tonic-gate 	DBT *key;
12337c478bd9Sstevel@tonic-gate 	DBT *info;
12347c478bd9Sstevel@tonic-gate {
12357c478bd9Sstevel@tonic-gate 	char *name, *type;
12367c478bd9Sstevel@tonic-gate 	char **hp;
123749218d4fSjbeck 	char kbuf[MAXUDBKEY + 1];
12387c478bd9Sstevel@tonic-gate 
1239*058561cbSjbeck 	if (sm_strlcpy(kbuf, key->data, sizeof(kbuf)) >= sizeof(kbuf))
12407c478bd9Sstevel@tonic-gate 		return 0;
12417c478bd9Sstevel@tonic-gate 	name = kbuf;
12427c478bd9Sstevel@tonic-gate 	type = strrchr(name, ':');
12437c478bd9Sstevel@tonic-gate 	if (type == NULL)
12447c478bd9Sstevel@tonic-gate 		return 1;
12457c478bd9Sstevel@tonic-gate 	*type++ = '\0';
12467c478bd9Sstevel@tonic-gate 	if (strchr(name, '@') != NULL)
12477c478bd9Sstevel@tonic-gate 		return 1;
12487c478bd9Sstevel@tonic-gate 
12497c478bd9Sstevel@tonic-gate 	if (tTd(28, 1))
12507c478bd9Sstevel@tonic-gate 		sm_dprintf("hes_udb_get(%s, %s)\n", name, type);
12517c478bd9Sstevel@tonic-gate 
12527c478bd9Sstevel@tonic-gate 	/* make the hesiod query */
12537c478bd9Sstevel@tonic-gate #  ifdef HESIOD_INIT
12547c478bd9Sstevel@tonic-gate 	if (HesiodContext == NULL && hesiod_init(&HesiodContext) != 0)
12557c478bd9Sstevel@tonic-gate 		return -1;
12567c478bd9Sstevel@tonic-gate 	hp = hesiod_resolve(HesiodContext, name, type);
12577c478bd9Sstevel@tonic-gate #  else /* HESIOD_INIT */
12587c478bd9Sstevel@tonic-gate 	hp = hes_resolve(name, type);
12597c478bd9Sstevel@tonic-gate #  endif /* HESIOD_INIT */
12607c478bd9Sstevel@tonic-gate 	*--type = ':';
12617c478bd9Sstevel@tonic-gate #  ifdef HESIOD_INIT
12627c478bd9Sstevel@tonic-gate 	if (hp == NULL)
12637c478bd9Sstevel@tonic-gate 		return 1;
12647c478bd9Sstevel@tonic-gate 	if (*hp == NULL)
12657c478bd9Sstevel@tonic-gate 	{
12667c478bd9Sstevel@tonic-gate 		hesiod_free_list(HesiodContext, hp);
12677c478bd9Sstevel@tonic-gate 		if (errno == ECONNREFUSED || errno == EMSGSIZE)
12687c478bd9Sstevel@tonic-gate 			return -1;
12697c478bd9Sstevel@tonic-gate 		return 1;
12707c478bd9Sstevel@tonic-gate 	}
12717c478bd9Sstevel@tonic-gate #  else /* HESIOD_INIT */
12727c478bd9Sstevel@tonic-gate 	if (hp == NULL || hp[0] == NULL)
12737c478bd9Sstevel@tonic-gate 	{
12747c478bd9Sstevel@tonic-gate 		/* network problem or timeout */
12757c478bd9Sstevel@tonic-gate 		if (hes_error() == HES_ER_NET)
12767c478bd9Sstevel@tonic-gate 			return -1;
12777c478bd9Sstevel@tonic-gate 
12787c478bd9Sstevel@tonic-gate 		return 1;
12797c478bd9Sstevel@tonic-gate 	}
12807c478bd9Sstevel@tonic-gate #  endif /* HESIOD_INIT */
12817c478bd9Sstevel@tonic-gate 	else
12827c478bd9Sstevel@tonic-gate 	{
12837c478bd9Sstevel@tonic-gate 		/*
12847c478bd9Sstevel@tonic-gate 		**  If there are multiple matches, just return the
12857c478bd9Sstevel@tonic-gate 		**  first one.
12867c478bd9Sstevel@tonic-gate 		**
12877c478bd9Sstevel@tonic-gate 		**  XXX These should really be returned; for example,
12887c478bd9Sstevel@tonic-gate 		**  XXX it is legal for :maildrop to be multi-valued.
12897c478bd9Sstevel@tonic-gate 		*/
12907c478bd9Sstevel@tonic-gate 
12917c478bd9Sstevel@tonic-gate 		info->data = hp[0];
12927c478bd9Sstevel@tonic-gate 		info->size = (size_t) strlen(info->data);
12937c478bd9Sstevel@tonic-gate 	}
12947c478bd9Sstevel@tonic-gate 
12957c478bd9Sstevel@tonic-gate 	if (tTd(28, 80))
12967c478bd9Sstevel@tonic-gate 		sm_dprintf("hes_udb_get => %s\n", *hp);
12977c478bd9Sstevel@tonic-gate 
12987c478bd9Sstevel@tonic-gate 	return 0;
12997c478bd9Sstevel@tonic-gate }
13007c478bd9Sstevel@tonic-gate # endif /* HESIOD */
13017c478bd9Sstevel@tonic-gate 
13027c478bd9Sstevel@tonic-gate #else /* USERDB */
13037c478bd9Sstevel@tonic-gate 
13047c478bd9Sstevel@tonic-gate int
13057c478bd9Sstevel@tonic-gate udbexpand(a, sendq, aliaslevel, e)
13067c478bd9Sstevel@tonic-gate 	ADDRESS *a;
13077c478bd9Sstevel@tonic-gate 	ADDRESS **sendq;
13087c478bd9Sstevel@tonic-gate 	int aliaslevel;
13097c478bd9Sstevel@tonic-gate 	ENVELOPE *e;
13107c478bd9Sstevel@tonic-gate {
13117c478bd9Sstevel@tonic-gate 	return EX_OK;
13127c478bd9Sstevel@tonic-gate }
13137c478bd9Sstevel@tonic-gate 
13147c478bd9Sstevel@tonic-gate #endif /* USERDB */
1315