xref: /titanic_52/usr/src/cmd/sendmail/aux/editmap.c (revision 7800901e60d340b6af88e94a2149805dcfcaaf56)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * Copyright (c) 1998-2002, 2004 Sendmail, Inc. and its suppliers.
37c478bd9Sstevel@tonic-gate  *	All rights reserved.
47c478bd9Sstevel@tonic-gate  * Copyright (c) 1992 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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
157c478bd9Sstevel@tonic-gate 
167c478bd9Sstevel@tonic-gate #include <sm/gen.h>
177c478bd9Sstevel@tonic-gate #ifndef lint
187c478bd9Sstevel@tonic-gate SM_UNUSED(static char copyright[]) =
197c478bd9Sstevel@tonic-gate "@(#) Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers.\n\
207c478bd9Sstevel@tonic-gate 	All rights reserved.\n\
217c478bd9Sstevel@tonic-gate      Copyright (c) 1992 Eric P. Allman.  All rights reserved.\n\
227c478bd9Sstevel@tonic-gate      Copyright (c) 1992, 1993\n\
237c478bd9Sstevel@tonic-gate 	The Regents of the University of California.  All rights reserved.\n";
247c478bd9Sstevel@tonic-gate #endif /* ! lint */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #ifndef lint
27*7800901eSjbeck SM_UNUSED(static char id[]) = "@(#)$Id: editmap.c,v 1.25 2007/05/11 18:50:35 ca Exp $";
287c478bd9Sstevel@tonic-gate #endif /* ! lint */
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate #include <sys/types.h>
327c478bd9Sstevel@tonic-gate #ifndef ISC_UNIX
337c478bd9Sstevel@tonic-gate # include <sys/file.h>
347c478bd9Sstevel@tonic-gate #endif /* ! ISC_UNIX */
357c478bd9Sstevel@tonic-gate #include <ctype.h>
367c478bd9Sstevel@tonic-gate #include <stdlib.h>
377c478bd9Sstevel@tonic-gate #include <unistd.h>
387c478bd9Sstevel@tonic-gate #ifdef EX_OK
397c478bd9Sstevel@tonic-gate # undef EX_OK		/* unistd.h may have another use for this */
407c478bd9Sstevel@tonic-gate #endif /* EX_OK */
417c478bd9Sstevel@tonic-gate #include <sysexits.h>
427c478bd9Sstevel@tonic-gate #include <assert.h>
437c478bd9Sstevel@tonic-gate #include <sendmail/sendmail.h>
447c478bd9Sstevel@tonic-gate #include <sendmail/pathnames.h>
457c478bd9Sstevel@tonic-gate #include <libsmdb/smdb.h>
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate uid_t	RealUid;
487c478bd9Sstevel@tonic-gate gid_t	RealGid;
497c478bd9Sstevel@tonic-gate char	*RealUserName;
507c478bd9Sstevel@tonic-gate uid_t	RunAsUid;
51*7800901eSjbeck gid_t	RunAsGid;
527c478bd9Sstevel@tonic-gate char	*RunAsUserName;
537c478bd9Sstevel@tonic-gate int	Verbose = 2;
547c478bd9Sstevel@tonic-gate bool	DontInitGroups = false;
557c478bd9Sstevel@tonic-gate uid_t	TrustedUid = 0;
567c478bd9Sstevel@tonic-gate BITMAP256 DontBlameSendmail;
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate #define BUFSIZE		1024
597c478bd9Sstevel@tonic-gate #define ISSEP(c) (isascii(c) && isspace(c))
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate static void usage __P((char *));
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate static void
657c478bd9Sstevel@tonic-gate usage(progname)
667c478bd9Sstevel@tonic-gate 	char *progname;
677c478bd9Sstevel@tonic-gate {
687c478bd9Sstevel@tonic-gate 	fprintf(stderr,
697c478bd9Sstevel@tonic-gate 		"Usage: %s [-C cffile] [-N] [-f] [-q|-u|-x] maptype mapname key [ \"value ...\" ]\n",
707c478bd9Sstevel@tonic-gate 		progname);
717c478bd9Sstevel@tonic-gate 	exit(EX_USAGE);
727c478bd9Sstevel@tonic-gate }
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate int
757c478bd9Sstevel@tonic-gate main(argc, argv)
767c478bd9Sstevel@tonic-gate 	int argc;
777c478bd9Sstevel@tonic-gate 	char **argv;
787c478bd9Sstevel@tonic-gate {
797c478bd9Sstevel@tonic-gate 	char *progname;
807c478bd9Sstevel@tonic-gate 	char *cfile;
817c478bd9Sstevel@tonic-gate 	bool verbose = false;
827c478bd9Sstevel@tonic-gate 	bool query = false;
837c478bd9Sstevel@tonic-gate 	bool update = false;
847c478bd9Sstevel@tonic-gate 	bool remove = false;
857c478bd9Sstevel@tonic-gate 	bool inclnull = false;
867c478bd9Sstevel@tonic-gate 	bool foldcase = true;
877c478bd9Sstevel@tonic-gate 	unsigned int nops = 0;
887c478bd9Sstevel@tonic-gate 	int exitstat;
897c478bd9Sstevel@tonic-gate 	int opt;
907c478bd9Sstevel@tonic-gate 	char *typename = NULL;
917c478bd9Sstevel@tonic-gate 	char *mapname = NULL;
927c478bd9Sstevel@tonic-gate 	char *keyname = NULL;
937c478bd9Sstevel@tonic-gate 	char *value = NULL;
947c478bd9Sstevel@tonic-gate 	int mode;
957c478bd9Sstevel@tonic-gate 	int smode;
967c478bd9Sstevel@tonic-gate 	int putflags = 0;
977c478bd9Sstevel@tonic-gate 	long sff = SFF_ROOTOK|SFF_REGONLY;
987c478bd9Sstevel@tonic-gate 	struct passwd *pw;
997c478bd9Sstevel@tonic-gate 	SMDB_DATABASE *database;
1007c478bd9Sstevel@tonic-gate 	SMDB_DBENT db_key, db_val;
1017c478bd9Sstevel@tonic-gate 	SMDB_DBPARAMS params;
1027c478bd9Sstevel@tonic-gate 	SMDB_USER_INFO user_info;
1037c478bd9Sstevel@tonic-gate #if HASFCHOWN
1047c478bd9Sstevel@tonic-gate 	FILE *cfp;
1057c478bd9Sstevel@tonic-gate 	char buf[MAXLINE];
1067c478bd9Sstevel@tonic-gate #endif /* HASFCHOWN */
1077c478bd9Sstevel@tonic-gate 	static char rnamebuf[MAXNAME];	/* holds RealUserName */
1087c478bd9Sstevel@tonic-gate 	extern char *optarg;
1097c478bd9Sstevel@tonic-gate 	extern int optind;
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate 	memset(&params, '\0', sizeof params);
1127c478bd9Sstevel@tonic-gate 	params.smdbp_cache_size = 1024 * 1024;
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate 	progname = strrchr(argv[0], '/');
1157c478bd9Sstevel@tonic-gate 	if (progname != NULL)
1167c478bd9Sstevel@tonic-gate 		progname++;
1177c478bd9Sstevel@tonic-gate 	else
1187c478bd9Sstevel@tonic-gate 		progname = argv[0];
1197c478bd9Sstevel@tonic-gate 	cfile = _PATH_SENDMAILCF;
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate 	clrbitmap(DontBlameSendmail);
1227c478bd9Sstevel@tonic-gate 	RunAsUid = RealUid = getuid();
1237c478bd9Sstevel@tonic-gate 	RunAsGid = RealGid = getgid();
1247c478bd9Sstevel@tonic-gate 	pw = getpwuid(RealUid);
1257c478bd9Sstevel@tonic-gate 	if (pw != NULL)
1267c478bd9Sstevel@tonic-gate 		(void) sm_strlcpy(rnamebuf, pw->pw_name, sizeof rnamebuf);
1277c478bd9Sstevel@tonic-gate 	else
1287c478bd9Sstevel@tonic-gate 		(void) sm_snprintf(rnamebuf, sizeof rnamebuf,
1297c478bd9Sstevel@tonic-gate 				   "Unknown UID %d", (int) RealUid);
1307c478bd9Sstevel@tonic-gate 	RunAsUserName = RealUserName = rnamebuf;
1317c478bd9Sstevel@tonic-gate 	user_info.smdbu_id = RunAsUid;
1327c478bd9Sstevel@tonic-gate 	user_info.smdbu_group_id = RunAsGid;
1337c478bd9Sstevel@tonic-gate 	(void) sm_strlcpy(user_info.smdbu_name, RunAsUserName,
1347c478bd9Sstevel@tonic-gate 			  SMDB_MAX_USER_NAME_LEN);
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate #define OPTIONS		"C:fquxvN"
1377c478bd9Sstevel@tonic-gate 	while ((opt = getopt(argc, argv, OPTIONS)) != -1)
1387c478bd9Sstevel@tonic-gate 	{
1397c478bd9Sstevel@tonic-gate 		switch (opt)
1407c478bd9Sstevel@tonic-gate 		{
1417c478bd9Sstevel@tonic-gate 		  case 'C':
1427c478bd9Sstevel@tonic-gate 			cfile = optarg;
1437c478bd9Sstevel@tonic-gate 			break;
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate 		  case 'f':
1467c478bd9Sstevel@tonic-gate 			foldcase = false;
1477c478bd9Sstevel@tonic-gate 			break;
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate 		  case 'q':
1507c478bd9Sstevel@tonic-gate 			query = true;
1517c478bd9Sstevel@tonic-gate 			nops++;
1527c478bd9Sstevel@tonic-gate 			break;
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 		  case 'u':
1557c478bd9Sstevel@tonic-gate 			update = true;
1567c478bd9Sstevel@tonic-gate 			nops++;
1577c478bd9Sstevel@tonic-gate 			break;
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate 		  case 'x':
1607c478bd9Sstevel@tonic-gate 			remove = true;
1617c478bd9Sstevel@tonic-gate 			nops++;
1627c478bd9Sstevel@tonic-gate 			break;
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 		  case 'v':
1657c478bd9Sstevel@tonic-gate 			verbose = true;
1667c478bd9Sstevel@tonic-gate 			break;
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate 		  case 'N':
1697c478bd9Sstevel@tonic-gate 			inclnull = true;
1707c478bd9Sstevel@tonic-gate 			break;
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate 		  default:
1737c478bd9Sstevel@tonic-gate 			usage(progname);
1747c478bd9Sstevel@tonic-gate 			assert(0);  /* NOTREACHED */
1757c478bd9Sstevel@tonic-gate 		}
1767c478bd9Sstevel@tonic-gate 	}
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate 	if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail))
1797c478bd9Sstevel@tonic-gate 		sff |= SFF_NOSLINK;
1807c478bd9Sstevel@tonic-gate 	if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail))
1817c478bd9Sstevel@tonic-gate 		sff |= SFF_NOHLINK;
1827c478bd9Sstevel@tonic-gate 	if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail))
1837c478bd9Sstevel@tonic-gate 		sff |= SFF_NOWLINK;
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate 	argc -= optind;
1867c478bd9Sstevel@tonic-gate 	argv += optind;
1877c478bd9Sstevel@tonic-gate 	if ((nops != 1) ||
1887c478bd9Sstevel@tonic-gate 	    (query && argc != 3) ||
1897c478bd9Sstevel@tonic-gate 	    (remove && argc != 3) ||
1907c478bd9Sstevel@tonic-gate 	    (update && argc <= 3))
1917c478bd9Sstevel@tonic-gate 	{
1927c478bd9Sstevel@tonic-gate 		usage(progname);
1937c478bd9Sstevel@tonic-gate 		assert(0);  /* NOTREACHED */
1947c478bd9Sstevel@tonic-gate 	}
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 	typename = argv[0];
1977c478bd9Sstevel@tonic-gate 	mapname = argv[1];
1987c478bd9Sstevel@tonic-gate 	keyname = argv[2];
1997c478bd9Sstevel@tonic-gate 	if (update)
2007c478bd9Sstevel@tonic-gate 		value = argv[3];
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate 	if (foldcase)
2037c478bd9Sstevel@tonic-gate 	{
2047c478bd9Sstevel@tonic-gate 		char *p;
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 		for (p = keyname; *p != '\0'; p++)
2077c478bd9Sstevel@tonic-gate 		{
2087c478bd9Sstevel@tonic-gate 			if (isascii(*p) && isupper(*p))
2097c478bd9Sstevel@tonic-gate 				*p = tolower(*p);
2107c478bd9Sstevel@tonic-gate 		}
2117c478bd9Sstevel@tonic-gate 	}
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate #if HASFCHOWN
2157c478bd9Sstevel@tonic-gate 	/* Find TrustedUser value in sendmail.cf */
2167c478bd9Sstevel@tonic-gate 	if ((cfp = fopen(cfile, "r")) == NULL)
2177c478bd9Sstevel@tonic-gate 	{
2187c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%s: %s: %s\n", progname,
2197c478bd9Sstevel@tonic-gate 			cfile, sm_errstring(errno));
2207c478bd9Sstevel@tonic-gate 		exit(EX_NOINPUT);
2217c478bd9Sstevel@tonic-gate 	}
2227c478bd9Sstevel@tonic-gate 	while (fgets(buf, sizeof(buf), cfp) != NULL)
2237c478bd9Sstevel@tonic-gate 	{
2247c478bd9Sstevel@tonic-gate 		register char *b;
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate 		if ((b = strchr(buf, '\n')) != NULL)
2277c478bd9Sstevel@tonic-gate 			*b = '\0';
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate 		b = buf;
2307c478bd9Sstevel@tonic-gate 		switch (*b++)
2317c478bd9Sstevel@tonic-gate 		{
2327c478bd9Sstevel@tonic-gate 		  case 'O':		/* option */
2337c478bd9Sstevel@tonic-gate 			if (strncasecmp(b, " TrustedUser", 12) == 0 &&
2347c478bd9Sstevel@tonic-gate 			    !(isascii(b[12]) && isalnum(b[12])))
2357c478bd9Sstevel@tonic-gate 			{
2367c478bd9Sstevel@tonic-gate 				b = strchr(b, '=');
2377c478bd9Sstevel@tonic-gate 				if (b == NULL)
2387c478bd9Sstevel@tonic-gate 					continue;
2397c478bd9Sstevel@tonic-gate 				while (isascii(*++b) && isspace(*b))
2407c478bd9Sstevel@tonic-gate 					continue;
2417c478bd9Sstevel@tonic-gate 				if (isascii(*b) && isdigit(*b))
2427c478bd9Sstevel@tonic-gate 					TrustedUid = atoi(b);
2437c478bd9Sstevel@tonic-gate 				else
2447c478bd9Sstevel@tonic-gate 				{
2457c478bd9Sstevel@tonic-gate 					TrustedUid = 0;
2467c478bd9Sstevel@tonic-gate 					pw = getpwnam(b);
2477c478bd9Sstevel@tonic-gate 					if (pw == NULL)
2487c478bd9Sstevel@tonic-gate 						fprintf(stderr,
2497c478bd9Sstevel@tonic-gate 							"TrustedUser: unknown user %s\n", b);
2507c478bd9Sstevel@tonic-gate 					else
2517c478bd9Sstevel@tonic-gate 						TrustedUid = pw->pw_uid;
2527c478bd9Sstevel@tonic-gate 				}
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate # ifdef UID_MAX
2557c478bd9Sstevel@tonic-gate 				if (TrustedUid > UID_MAX)
2567c478bd9Sstevel@tonic-gate 				{
2577c478bd9Sstevel@tonic-gate 					fprintf(stderr,
2587c478bd9Sstevel@tonic-gate 						"TrustedUser: uid value (%ld) > UID_MAX (%ld)",
2597c478bd9Sstevel@tonic-gate 						(long) TrustedUid,
2607c478bd9Sstevel@tonic-gate 						(long) UID_MAX);
2617c478bd9Sstevel@tonic-gate 					TrustedUid = 0;
2627c478bd9Sstevel@tonic-gate 				}
2637c478bd9Sstevel@tonic-gate # endif /* UID_MAX */
2647c478bd9Sstevel@tonic-gate 				break;
2657c478bd9Sstevel@tonic-gate 			}
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 		  default:
2697c478bd9Sstevel@tonic-gate 			continue;
2707c478bd9Sstevel@tonic-gate 		}
2717c478bd9Sstevel@tonic-gate 	}
2727c478bd9Sstevel@tonic-gate 	(void) fclose(cfp);
2737c478bd9Sstevel@tonic-gate #endif /* HASFCHOWN */
2747c478bd9Sstevel@tonic-gate 
2757c478bd9Sstevel@tonic-gate 	if (query)
2767c478bd9Sstevel@tonic-gate 	{
2777c478bd9Sstevel@tonic-gate 		mode = O_RDONLY;
2787c478bd9Sstevel@tonic-gate 		smode = S_IRUSR;
2797c478bd9Sstevel@tonic-gate 	}
2807c478bd9Sstevel@tonic-gate 	else
2817c478bd9Sstevel@tonic-gate 	{
2827c478bd9Sstevel@tonic-gate 		mode = O_RDWR | O_CREAT;
2837c478bd9Sstevel@tonic-gate 		sff |= SFF_CREAT|SFF_NOTEXCL;
2847c478bd9Sstevel@tonic-gate 		smode = S_IWUSR;
2857c478bd9Sstevel@tonic-gate 	}
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate 	params.smdbp_num_elements = 4096;
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate 	errno = smdb_open_database(&database, mapname, mode, smode, sff,
2907c478bd9Sstevel@tonic-gate 				   typename, &user_info, &params);
2917c478bd9Sstevel@tonic-gate 	if (errno != SMDBE_OK)
2927c478bd9Sstevel@tonic-gate 	{
2937c478bd9Sstevel@tonic-gate 		char *hint;
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate 		if (errno == SMDBE_UNSUPPORTED_DB_TYPE &&
2967c478bd9Sstevel@tonic-gate 		    (hint = smdb_db_definition(typename)) != NULL)
2977c478bd9Sstevel@tonic-gate 			fprintf(stderr,
2987c478bd9Sstevel@tonic-gate 				"%s: Need to recompile with -D%s for %s support\n",
2997c478bd9Sstevel@tonic-gate 				progname, hint, typename);
3007c478bd9Sstevel@tonic-gate 		else
3017c478bd9Sstevel@tonic-gate 			fprintf(stderr,
3027c478bd9Sstevel@tonic-gate 				"%s: error opening type %s map %s: %s\n",
3037c478bd9Sstevel@tonic-gate 				progname, typename, mapname,
3047c478bd9Sstevel@tonic-gate 				sm_errstring(errno));
3057c478bd9Sstevel@tonic-gate 		exit(EX_CANTCREAT);
3067c478bd9Sstevel@tonic-gate 	}
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate 	(void) database->smdb_sync(database, 0);
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate 	if (geteuid() == 0 && TrustedUid != 0)
3117c478bd9Sstevel@tonic-gate 	{
3127c478bd9Sstevel@tonic-gate 		errno = database->smdb_set_owner(database, TrustedUid, -1);
3137c478bd9Sstevel@tonic-gate 		if (errno != SMDBE_OK)
3147c478bd9Sstevel@tonic-gate 		{
3157c478bd9Sstevel@tonic-gate 			fprintf(stderr,
3167c478bd9Sstevel@tonic-gate 				"WARNING: ownership change on %s failed %s",
3177c478bd9Sstevel@tonic-gate 				mapname, sm_errstring(errno));
3187c478bd9Sstevel@tonic-gate 		}
3197c478bd9Sstevel@tonic-gate 	}
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate 	exitstat = EX_OK;
3227c478bd9Sstevel@tonic-gate 	if (query)
3237c478bd9Sstevel@tonic-gate 	{
3247c478bd9Sstevel@tonic-gate 		memset(&db_key, '\0', sizeof db_key);
3257c478bd9Sstevel@tonic-gate 		memset(&db_val, '\0', sizeof db_val);
3267c478bd9Sstevel@tonic-gate 
3277c478bd9Sstevel@tonic-gate 		db_key.data = keyname;
3287c478bd9Sstevel@tonic-gate 		db_key.size = strlen(keyname);
3297c478bd9Sstevel@tonic-gate 		if (inclnull)
3307c478bd9Sstevel@tonic-gate 			db_key.size++;
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate 		errno = database->smdb_get(database, &db_key, &db_val, 0);
3337c478bd9Sstevel@tonic-gate 		if (errno != SMDBE_OK)
3347c478bd9Sstevel@tonic-gate 		{
3357c478bd9Sstevel@tonic-gate 			/* XXX - Need to distinguish between not found */
3367c478bd9Sstevel@tonic-gate 			fprintf(stderr,
3377c478bd9Sstevel@tonic-gate 				"%s: couldn't find key %s in map %s\n",
3387c478bd9Sstevel@tonic-gate 				progname, keyname, mapname);
3397c478bd9Sstevel@tonic-gate 			exitstat = EX_UNAVAILABLE;
3407c478bd9Sstevel@tonic-gate 		}
3417c478bd9Sstevel@tonic-gate 		else
3427c478bd9Sstevel@tonic-gate 		{
3437c478bd9Sstevel@tonic-gate 			printf("%.*s\n", (int) db_val.size,
3447c478bd9Sstevel@tonic-gate 			       (char *) db_val.data);
3457c478bd9Sstevel@tonic-gate 		}
3467c478bd9Sstevel@tonic-gate 	}
3477c478bd9Sstevel@tonic-gate 	else if (update)
3487c478bd9Sstevel@tonic-gate 	{
3497c478bd9Sstevel@tonic-gate 		memset(&db_key, '\0', sizeof db_key);
3507c478bd9Sstevel@tonic-gate 		memset(&db_val, '\0', sizeof db_val);
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate 		db_key.data = keyname;
3537c478bd9Sstevel@tonic-gate 		db_key.size = strlen(keyname);
3547c478bd9Sstevel@tonic-gate 		if (inclnull)
3557c478bd9Sstevel@tonic-gate 			db_key.size++;
3567c478bd9Sstevel@tonic-gate 		db_val.data = value;
3577c478bd9Sstevel@tonic-gate 		db_val.size = strlen(value);
3587c478bd9Sstevel@tonic-gate 		if (inclnull)
3597c478bd9Sstevel@tonic-gate 			db_val.size++;
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 		errno = database->smdb_put(database, &db_key, &db_val,
3627c478bd9Sstevel@tonic-gate 					   putflags);
3637c478bd9Sstevel@tonic-gate 		if (errno != SMDBE_OK)
3647c478bd9Sstevel@tonic-gate 		{
3657c478bd9Sstevel@tonic-gate 			fprintf(stderr,
3667c478bd9Sstevel@tonic-gate 				"%s: error updating (%s, %s) in map %s: %s\n",
3677c478bd9Sstevel@tonic-gate 				progname, keyname, value, mapname,
3687c478bd9Sstevel@tonic-gate 				sm_errstring(errno));
3697c478bd9Sstevel@tonic-gate 			exitstat = EX_IOERR;
3707c478bd9Sstevel@tonic-gate 		}
3717c478bd9Sstevel@tonic-gate 	}
3727c478bd9Sstevel@tonic-gate 	else if (remove)
3737c478bd9Sstevel@tonic-gate 	{
3747c478bd9Sstevel@tonic-gate 		memset(&db_key, '\0', sizeof db_key);
3757c478bd9Sstevel@tonic-gate 		memset(&db_val, '\0', sizeof db_val);
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 		db_key.data = keyname;
3787c478bd9Sstevel@tonic-gate 		db_key.size = strlen(keyname);
3797c478bd9Sstevel@tonic-gate 		if (inclnull)
3807c478bd9Sstevel@tonic-gate 			db_key.size++;
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate 		errno = database->smdb_del(database, &db_key, 0);
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate 		switch (errno)
3857c478bd9Sstevel@tonic-gate 		{
3867c478bd9Sstevel@tonic-gate 		case SMDBE_NOT_FOUND:
3877c478bd9Sstevel@tonic-gate 			fprintf(stderr,
3887c478bd9Sstevel@tonic-gate 				"%s: key %s doesn't exist in map %s\n",
3897c478bd9Sstevel@tonic-gate 				progname, keyname, mapname);
3907c478bd9Sstevel@tonic-gate 			/* Don't set exitstat */
3917c478bd9Sstevel@tonic-gate 			break;
3927c478bd9Sstevel@tonic-gate 		case SMDBE_OK:
3937c478bd9Sstevel@tonic-gate 			/* All's well */
3947c478bd9Sstevel@tonic-gate 			break;
3957c478bd9Sstevel@tonic-gate 		default:
3967c478bd9Sstevel@tonic-gate 			fprintf(stderr,
3977c478bd9Sstevel@tonic-gate 				"%s: couldn't remove key %s in map %s (error)\n",
3987c478bd9Sstevel@tonic-gate 				progname, keyname, mapname);
3997c478bd9Sstevel@tonic-gate 			exitstat = EX_IOERR;
4007c478bd9Sstevel@tonic-gate 			break;
4017c478bd9Sstevel@tonic-gate 		}
4027c478bd9Sstevel@tonic-gate 	}
4037c478bd9Sstevel@tonic-gate 	else
4047c478bd9Sstevel@tonic-gate 	{
4057c478bd9Sstevel@tonic-gate 		assert(0);  /* NOT REACHED */
4067c478bd9Sstevel@tonic-gate 	}
4077c478bd9Sstevel@tonic-gate 
4087c478bd9Sstevel@tonic-gate 	/*
4097c478bd9Sstevel@tonic-gate 	**  Now close the database.
4107c478bd9Sstevel@tonic-gate 	*/
4117c478bd9Sstevel@tonic-gate 
4127c478bd9Sstevel@tonic-gate 	errno = database->smdb_close(database);
4137c478bd9Sstevel@tonic-gate 	if (errno != SMDBE_OK)
4147c478bd9Sstevel@tonic-gate 	{
4157c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%s: close(%s): %s\n",
4167c478bd9Sstevel@tonic-gate 			progname, mapname, sm_errstring(errno));
4177c478bd9Sstevel@tonic-gate 		exitstat = EX_IOERR;
4187c478bd9Sstevel@tonic-gate 	}
4197c478bd9Sstevel@tonic-gate 	smdb_free_database(database);
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate 	exit(exitstat);
4227c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
4237c478bd9Sstevel@tonic-gate 	return exitstat;
4247c478bd9Sstevel@tonic-gate }
425