xref: /titanic_52/usr/src/cmd/sendmail/aux/editmap.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1998-2002, 2004 Sendmail, Inc. and its suppliers.
3*7c478bd9Sstevel@tonic-gate  *	All rights reserved.
4*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1992 Eric P. Allman.  All rights reserved.
5*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1992, 1993
6*7c478bd9Sstevel@tonic-gate  *	The Regents of the University of California.  All rights reserved.
7*7c478bd9Sstevel@tonic-gate  *
8*7c478bd9Sstevel@tonic-gate  * By using this file, you agree to the terms and conditions set
9*7c478bd9Sstevel@tonic-gate  * forth in the LICENSE file which can be found at the top level of
10*7c478bd9Sstevel@tonic-gate  * the sendmail distribution.
11*7c478bd9Sstevel@tonic-gate  *
12*7c478bd9Sstevel@tonic-gate  */
13*7c478bd9Sstevel@tonic-gate 
14*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
15*7c478bd9Sstevel@tonic-gate 
16*7c478bd9Sstevel@tonic-gate #include <sm/gen.h>
17*7c478bd9Sstevel@tonic-gate #ifndef lint
18*7c478bd9Sstevel@tonic-gate SM_UNUSED(static char copyright[]) =
19*7c478bd9Sstevel@tonic-gate "@(#) Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers.\n\
20*7c478bd9Sstevel@tonic-gate 	All rights reserved.\n\
21*7c478bd9Sstevel@tonic-gate      Copyright (c) 1992 Eric P. Allman.  All rights reserved.\n\
22*7c478bd9Sstevel@tonic-gate      Copyright (c) 1992, 1993\n\
23*7c478bd9Sstevel@tonic-gate 	The Regents of the University of California.  All rights reserved.\n";
24*7c478bd9Sstevel@tonic-gate #endif /* ! lint */
25*7c478bd9Sstevel@tonic-gate 
26*7c478bd9Sstevel@tonic-gate #ifndef lint
27*7c478bd9Sstevel@tonic-gate SM_UNUSED(static char id[]) = "@(#)$Id: editmap.c,v 1.24 2004/08/03 18:40:10 ca Exp $";
28*7c478bd9Sstevel@tonic-gate #endif /* ! lint */
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
32*7c478bd9Sstevel@tonic-gate #ifndef ISC_UNIX
33*7c478bd9Sstevel@tonic-gate # include <sys/file.h>
34*7c478bd9Sstevel@tonic-gate #endif /* ! ISC_UNIX */
35*7c478bd9Sstevel@tonic-gate #include <ctype.h>
36*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
37*7c478bd9Sstevel@tonic-gate #include <unistd.h>
38*7c478bd9Sstevel@tonic-gate #ifdef EX_OK
39*7c478bd9Sstevel@tonic-gate # undef EX_OK		/* unistd.h may have another use for this */
40*7c478bd9Sstevel@tonic-gate #endif /* EX_OK */
41*7c478bd9Sstevel@tonic-gate #include <sysexits.h>
42*7c478bd9Sstevel@tonic-gate #include <assert.h>
43*7c478bd9Sstevel@tonic-gate #include <sendmail/sendmail.h>
44*7c478bd9Sstevel@tonic-gate #include <sendmail/pathnames.h>
45*7c478bd9Sstevel@tonic-gate #include <libsmdb/smdb.h>
46*7c478bd9Sstevel@tonic-gate 
47*7c478bd9Sstevel@tonic-gate uid_t	RealUid;
48*7c478bd9Sstevel@tonic-gate gid_t	RealGid;
49*7c478bd9Sstevel@tonic-gate char	*RealUserName;
50*7c478bd9Sstevel@tonic-gate uid_t	RunAsUid;
51*7c478bd9Sstevel@tonic-gate uid_t	RunAsGid;
52*7c478bd9Sstevel@tonic-gate char	*RunAsUserName;
53*7c478bd9Sstevel@tonic-gate int	Verbose = 2;
54*7c478bd9Sstevel@tonic-gate bool	DontInitGroups = false;
55*7c478bd9Sstevel@tonic-gate uid_t	TrustedUid = 0;
56*7c478bd9Sstevel@tonic-gate BITMAP256 DontBlameSendmail;
57*7c478bd9Sstevel@tonic-gate 
58*7c478bd9Sstevel@tonic-gate #define BUFSIZE		1024
59*7c478bd9Sstevel@tonic-gate #define ISSEP(c) (isascii(c) && isspace(c))
60*7c478bd9Sstevel@tonic-gate 
61*7c478bd9Sstevel@tonic-gate 
62*7c478bd9Sstevel@tonic-gate static void usage __P((char *));
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate static void
65*7c478bd9Sstevel@tonic-gate usage(progname)
66*7c478bd9Sstevel@tonic-gate 	char *progname;
67*7c478bd9Sstevel@tonic-gate {
68*7c478bd9Sstevel@tonic-gate 	fprintf(stderr,
69*7c478bd9Sstevel@tonic-gate 		"Usage: %s [-C cffile] [-N] [-f] [-q|-u|-x] maptype mapname key [ \"value ...\" ]\n",
70*7c478bd9Sstevel@tonic-gate 		progname);
71*7c478bd9Sstevel@tonic-gate 	exit(EX_USAGE);
72*7c478bd9Sstevel@tonic-gate }
73*7c478bd9Sstevel@tonic-gate 
74*7c478bd9Sstevel@tonic-gate int
75*7c478bd9Sstevel@tonic-gate main(argc, argv)
76*7c478bd9Sstevel@tonic-gate 	int argc;
77*7c478bd9Sstevel@tonic-gate 	char **argv;
78*7c478bd9Sstevel@tonic-gate {
79*7c478bd9Sstevel@tonic-gate 	char *progname;
80*7c478bd9Sstevel@tonic-gate 	char *cfile;
81*7c478bd9Sstevel@tonic-gate 	bool verbose = false;
82*7c478bd9Sstevel@tonic-gate 	bool query = false;
83*7c478bd9Sstevel@tonic-gate 	bool update = false;
84*7c478bd9Sstevel@tonic-gate 	bool remove = false;
85*7c478bd9Sstevel@tonic-gate 	bool inclnull = false;
86*7c478bd9Sstevel@tonic-gate 	bool foldcase = true;
87*7c478bd9Sstevel@tonic-gate 	unsigned int nops = 0;
88*7c478bd9Sstevel@tonic-gate 	int exitstat;
89*7c478bd9Sstevel@tonic-gate 	int opt;
90*7c478bd9Sstevel@tonic-gate 	char *typename = NULL;
91*7c478bd9Sstevel@tonic-gate 	char *mapname = NULL;
92*7c478bd9Sstevel@tonic-gate 	char *keyname = NULL;
93*7c478bd9Sstevel@tonic-gate 	char *value = NULL;
94*7c478bd9Sstevel@tonic-gate 	int mode;
95*7c478bd9Sstevel@tonic-gate 	int smode;
96*7c478bd9Sstevel@tonic-gate 	int putflags = 0;
97*7c478bd9Sstevel@tonic-gate 	long sff = SFF_ROOTOK|SFF_REGONLY;
98*7c478bd9Sstevel@tonic-gate 	struct passwd *pw;
99*7c478bd9Sstevel@tonic-gate 	SMDB_DATABASE *database;
100*7c478bd9Sstevel@tonic-gate 	SMDB_DBENT db_key, db_val;
101*7c478bd9Sstevel@tonic-gate 	SMDB_DBPARAMS params;
102*7c478bd9Sstevel@tonic-gate 	SMDB_USER_INFO user_info;
103*7c478bd9Sstevel@tonic-gate #if HASFCHOWN
104*7c478bd9Sstevel@tonic-gate 	FILE *cfp;
105*7c478bd9Sstevel@tonic-gate 	char buf[MAXLINE];
106*7c478bd9Sstevel@tonic-gate #endif /* HASFCHOWN */
107*7c478bd9Sstevel@tonic-gate 	static char rnamebuf[MAXNAME];	/* holds RealUserName */
108*7c478bd9Sstevel@tonic-gate 	extern char *optarg;
109*7c478bd9Sstevel@tonic-gate 	extern int optind;
110*7c478bd9Sstevel@tonic-gate 
111*7c478bd9Sstevel@tonic-gate 	memset(&params, '\0', sizeof params);
112*7c478bd9Sstevel@tonic-gate 	params.smdbp_cache_size = 1024 * 1024;
113*7c478bd9Sstevel@tonic-gate 
114*7c478bd9Sstevel@tonic-gate 	progname = strrchr(argv[0], '/');
115*7c478bd9Sstevel@tonic-gate 	if (progname != NULL)
116*7c478bd9Sstevel@tonic-gate 		progname++;
117*7c478bd9Sstevel@tonic-gate 	else
118*7c478bd9Sstevel@tonic-gate 		progname = argv[0];
119*7c478bd9Sstevel@tonic-gate 	cfile = _PATH_SENDMAILCF;
120*7c478bd9Sstevel@tonic-gate 
121*7c478bd9Sstevel@tonic-gate 	clrbitmap(DontBlameSendmail);
122*7c478bd9Sstevel@tonic-gate 	RunAsUid = RealUid = getuid();
123*7c478bd9Sstevel@tonic-gate 	RunAsGid = RealGid = getgid();
124*7c478bd9Sstevel@tonic-gate 	pw = getpwuid(RealUid);
125*7c478bd9Sstevel@tonic-gate 	if (pw != NULL)
126*7c478bd9Sstevel@tonic-gate 		(void) sm_strlcpy(rnamebuf, pw->pw_name, sizeof rnamebuf);
127*7c478bd9Sstevel@tonic-gate 	else
128*7c478bd9Sstevel@tonic-gate 		(void) sm_snprintf(rnamebuf, sizeof rnamebuf,
129*7c478bd9Sstevel@tonic-gate 				   "Unknown UID %d", (int) RealUid);
130*7c478bd9Sstevel@tonic-gate 	RunAsUserName = RealUserName = rnamebuf;
131*7c478bd9Sstevel@tonic-gate 	user_info.smdbu_id = RunAsUid;
132*7c478bd9Sstevel@tonic-gate 	user_info.smdbu_group_id = RunAsGid;
133*7c478bd9Sstevel@tonic-gate 	(void) sm_strlcpy(user_info.smdbu_name, RunAsUserName,
134*7c478bd9Sstevel@tonic-gate 			  SMDB_MAX_USER_NAME_LEN);
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate #define OPTIONS		"C:fquxvN"
137*7c478bd9Sstevel@tonic-gate 	while ((opt = getopt(argc, argv, OPTIONS)) != -1)
138*7c478bd9Sstevel@tonic-gate 	{
139*7c478bd9Sstevel@tonic-gate 		switch (opt)
140*7c478bd9Sstevel@tonic-gate 		{
141*7c478bd9Sstevel@tonic-gate 		  case 'C':
142*7c478bd9Sstevel@tonic-gate 			cfile = optarg;
143*7c478bd9Sstevel@tonic-gate 			break;
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate 		  case 'f':
146*7c478bd9Sstevel@tonic-gate 			foldcase = false;
147*7c478bd9Sstevel@tonic-gate 			break;
148*7c478bd9Sstevel@tonic-gate 
149*7c478bd9Sstevel@tonic-gate 		  case 'q':
150*7c478bd9Sstevel@tonic-gate 			query = true;
151*7c478bd9Sstevel@tonic-gate 			nops++;
152*7c478bd9Sstevel@tonic-gate 			break;
153*7c478bd9Sstevel@tonic-gate 
154*7c478bd9Sstevel@tonic-gate 		  case 'u':
155*7c478bd9Sstevel@tonic-gate 			update = true;
156*7c478bd9Sstevel@tonic-gate 			nops++;
157*7c478bd9Sstevel@tonic-gate 			break;
158*7c478bd9Sstevel@tonic-gate 
159*7c478bd9Sstevel@tonic-gate 		  case 'x':
160*7c478bd9Sstevel@tonic-gate 			remove = true;
161*7c478bd9Sstevel@tonic-gate 			nops++;
162*7c478bd9Sstevel@tonic-gate 			break;
163*7c478bd9Sstevel@tonic-gate 
164*7c478bd9Sstevel@tonic-gate 		  case 'v':
165*7c478bd9Sstevel@tonic-gate 			verbose = true;
166*7c478bd9Sstevel@tonic-gate 			break;
167*7c478bd9Sstevel@tonic-gate 
168*7c478bd9Sstevel@tonic-gate 		  case 'N':
169*7c478bd9Sstevel@tonic-gate 			inclnull = true;
170*7c478bd9Sstevel@tonic-gate 			break;
171*7c478bd9Sstevel@tonic-gate 
172*7c478bd9Sstevel@tonic-gate 		  default:
173*7c478bd9Sstevel@tonic-gate 			usage(progname);
174*7c478bd9Sstevel@tonic-gate 			assert(0);  /* NOTREACHED */
175*7c478bd9Sstevel@tonic-gate 		}
176*7c478bd9Sstevel@tonic-gate 	}
177*7c478bd9Sstevel@tonic-gate 
178*7c478bd9Sstevel@tonic-gate 	if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail))
179*7c478bd9Sstevel@tonic-gate 		sff |= SFF_NOSLINK;
180*7c478bd9Sstevel@tonic-gate 	if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail))
181*7c478bd9Sstevel@tonic-gate 		sff |= SFF_NOHLINK;
182*7c478bd9Sstevel@tonic-gate 	if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail))
183*7c478bd9Sstevel@tonic-gate 		sff |= SFF_NOWLINK;
184*7c478bd9Sstevel@tonic-gate 
185*7c478bd9Sstevel@tonic-gate 	argc -= optind;
186*7c478bd9Sstevel@tonic-gate 	argv += optind;
187*7c478bd9Sstevel@tonic-gate 	if ((nops != 1) ||
188*7c478bd9Sstevel@tonic-gate 	    (query && argc != 3) ||
189*7c478bd9Sstevel@tonic-gate 	    (remove && argc != 3) ||
190*7c478bd9Sstevel@tonic-gate 	    (update && argc <= 3))
191*7c478bd9Sstevel@tonic-gate 	{
192*7c478bd9Sstevel@tonic-gate 		usage(progname);
193*7c478bd9Sstevel@tonic-gate 		assert(0);  /* NOTREACHED */
194*7c478bd9Sstevel@tonic-gate 	}
195*7c478bd9Sstevel@tonic-gate 
196*7c478bd9Sstevel@tonic-gate 	typename = argv[0];
197*7c478bd9Sstevel@tonic-gate 	mapname = argv[1];
198*7c478bd9Sstevel@tonic-gate 	keyname = argv[2];
199*7c478bd9Sstevel@tonic-gate 	if (update)
200*7c478bd9Sstevel@tonic-gate 		value = argv[3];
201*7c478bd9Sstevel@tonic-gate 
202*7c478bd9Sstevel@tonic-gate 	if (foldcase)
203*7c478bd9Sstevel@tonic-gate 	{
204*7c478bd9Sstevel@tonic-gate 		char *p;
205*7c478bd9Sstevel@tonic-gate 
206*7c478bd9Sstevel@tonic-gate 		for (p = keyname; *p != '\0'; p++)
207*7c478bd9Sstevel@tonic-gate 		{
208*7c478bd9Sstevel@tonic-gate 			if (isascii(*p) && isupper(*p))
209*7c478bd9Sstevel@tonic-gate 				*p = tolower(*p);
210*7c478bd9Sstevel@tonic-gate 		}
211*7c478bd9Sstevel@tonic-gate 	}
212*7c478bd9Sstevel@tonic-gate 
213*7c478bd9Sstevel@tonic-gate 
214*7c478bd9Sstevel@tonic-gate #if HASFCHOWN
215*7c478bd9Sstevel@tonic-gate 	/* Find TrustedUser value in sendmail.cf */
216*7c478bd9Sstevel@tonic-gate 	if ((cfp = fopen(cfile, "r")) == NULL)
217*7c478bd9Sstevel@tonic-gate 	{
218*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%s: %s: %s\n", progname,
219*7c478bd9Sstevel@tonic-gate 			cfile, sm_errstring(errno));
220*7c478bd9Sstevel@tonic-gate 		exit(EX_NOINPUT);
221*7c478bd9Sstevel@tonic-gate 	}
222*7c478bd9Sstevel@tonic-gate 	while (fgets(buf, sizeof(buf), cfp) != NULL)
223*7c478bd9Sstevel@tonic-gate 	{
224*7c478bd9Sstevel@tonic-gate 		register char *b;
225*7c478bd9Sstevel@tonic-gate 
226*7c478bd9Sstevel@tonic-gate 		if ((b = strchr(buf, '\n')) != NULL)
227*7c478bd9Sstevel@tonic-gate 			*b = '\0';
228*7c478bd9Sstevel@tonic-gate 
229*7c478bd9Sstevel@tonic-gate 		b = buf;
230*7c478bd9Sstevel@tonic-gate 		switch (*b++)
231*7c478bd9Sstevel@tonic-gate 		{
232*7c478bd9Sstevel@tonic-gate 		  case 'O':		/* option */
233*7c478bd9Sstevel@tonic-gate 			if (strncasecmp(b, " TrustedUser", 12) == 0 &&
234*7c478bd9Sstevel@tonic-gate 			    !(isascii(b[12]) && isalnum(b[12])))
235*7c478bd9Sstevel@tonic-gate 			{
236*7c478bd9Sstevel@tonic-gate 				b = strchr(b, '=');
237*7c478bd9Sstevel@tonic-gate 				if (b == NULL)
238*7c478bd9Sstevel@tonic-gate 					continue;
239*7c478bd9Sstevel@tonic-gate 				while (isascii(*++b) && isspace(*b))
240*7c478bd9Sstevel@tonic-gate 					continue;
241*7c478bd9Sstevel@tonic-gate 				if (isascii(*b) && isdigit(*b))
242*7c478bd9Sstevel@tonic-gate 					TrustedUid = atoi(b);
243*7c478bd9Sstevel@tonic-gate 				else
244*7c478bd9Sstevel@tonic-gate 				{
245*7c478bd9Sstevel@tonic-gate 					TrustedUid = 0;
246*7c478bd9Sstevel@tonic-gate 					pw = getpwnam(b);
247*7c478bd9Sstevel@tonic-gate 					if (pw == NULL)
248*7c478bd9Sstevel@tonic-gate 						fprintf(stderr,
249*7c478bd9Sstevel@tonic-gate 							"TrustedUser: unknown user %s\n", b);
250*7c478bd9Sstevel@tonic-gate 					else
251*7c478bd9Sstevel@tonic-gate 						TrustedUid = pw->pw_uid;
252*7c478bd9Sstevel@tonic-gate 				}
253*7c478bd9Sstevel@tonic-gate 
254*7c478bd9Sstevel@tonic-gate # ifdef UID_MAX
255*7c478bd9Sstevel@tonic-gate 				if (TrustedUid > UID_MAX)
256*7c478bd9Sstevel@tonic-gate 				{
257*7c478bd9Sstevel@tonic-gate 					fprintf(stderr,
258*7c478bd9Sstevel@tonic-gate 						"TrustedUser: uid value (%ld) > UID_MAX (%ld)",
259*7c478bd9Sstevel@tonic-gate 						(long) TrustedUid,
260*7c478bd9Sstevel@tonic-gate 						(long) UID_MAX);
261*7c478bd9Sstevel@tonic-gate 					TrustedUid = 0;
262*7c478bd9Sstevel@tonic-gate 				}
263*7c478bd9Sstevel@tonic-gate # endif /* UID_MAX */
264*7c478bd9Sstevel@tonic-gate 				break;
265*7c478bd9Sstevel@tonic-gate 			}
266*7c478bd9Sstevel@tonic-gate 
267*7c478bd9Sstevel@tonic-gate 
268*7c478bd9Sstevel@tonic-gate 		  default:
269*7c478bd9Sstevel@tonic-gate 			continue;
270*7c478bd9Sstevel@tonic-gate 		}
271*7c478bd9Sstevel@tonic-gate 	}
272*7c478bd9Sstevel@tonic-gate 	(void) fclose(cfp);
273*7c478bd9Sstevel@tonic-gate #endif /* HASFCHOWN */
274*7c478bd9Sstevel@tonic-gate 
275*7c478bd9Sstevel@tonic-gate 	if (query)
276*7c478bd9Sstevel@tonic-gate 	{
277*7c478bd9Sstevel@tonic-gate 		mode = O_RDONLY;
278*7c478bd9Sstevel@tonic-gate 		smode = S_IRUSR;
279*7c478bd9Sstevel@tonic-gate 	}
280*7c478bd9Sstevel@tonic-gate 	else
281*7c478bd9Sstevel@tonic-gate 	{
282*7c478bd9Sstevel@tonic-gate 		mode = O_RDWR | O_CREAT;
283*7c478bd9Sstevel@tonic-gate 		sff |= SFF_CREAT|SFF_NOTEXCL;
284*7c478bd9Sstevel@tonic-gate 		smode = S_IWUSR;
285*7c478bd9Sstevel@tonic-gate 	}
286*7c478bd9Sstevel@tonic-gate 
287*7c478bd9Sstevel@tonic-gate 	params.smdbp_num_elements = 4096;
288*7c478bd9Sstevel@tonic-gate 
289*7c478bd9Sstevel@tonic-gate 	errno = smdb_open_database(&database, mapname, mode, smode, sff,
290*7c478bd9Sstevel@tonic-gate 				   typename, &user_info, &params);
291*7c478bd9Sstevel@tonic-gate 	if (errno != SMDBE_OK)
292*7c478bd9Sstevel@tonic-gate 	{
293*7c478bd9Sstevel@tonic-gate 		char *hint;
294*7c478bd9Sstevel@tonic-gate 
295*7c478bd9Sstevel@tonic-gate 		if (errno == SMDBE_UNSUPPORTED_DB_TYPE &&
296*7c478bd9Sstevel@tonic-gate 		    (hint = smdb_db_definition(typename)) != NULL)
297*7c478bd9Sstevel@tonic-gate 			fprintf(stderr,
298*7c478bd9Sstevel@tonic-gate 				"%s: Need to recompile with -D%s for %s support\n",
299*7c478bd9Sstevel@tonic-gate 				progname, hint, typename);
300*7c478bd9Sstevel@tonic-gate 		else
301*7c478bd9Sstevel@tonic-gate 			fprintf(stderr,
302*7c478bd9Sstevel@tonic-gate 				"%s: error opening type %s map %s: %s\n",
303*7c478bd9Sstevel@tonic-gate 				progname, typename, mapname,
304*7c478bd9Sstevel@tonic-gate 				sm_errstring(errno));
305*7c478bd9Sstevel@tonic-gate 		exit(EX_CANTCREAT);
306*7c478bd9Sstevel@tonic-gate 	}
307*7c478bd9Sstevel@tonic-gate 
308*7c478bd9Sstevel@tonic-gate 	(void) database->smdb_sync(database, 0);
309*7c478bd9Sstevel@tonic-gate 
310*7c478bd9Sstevel@tonic-gate 	if (geteuid() == 0 && TrustedUid != 0)
311*7c478bd9Sstevel@tonic-gate 	{
312*7c478bd9Sstevel@tonic-gate 		errno = database->smdb_set_owner(database, TrustedUid, -1);
313*7c478bd9Sstevel@tonic-gate 		if (errno != SMDBE_OK)
314*7c478bd9Sstevel@tonic-gate 		{
315*7c478bd9Sstevel@tonic-gate 			fprintf(stderr,
316*7c478bd9Sstevel@tonic-gate 				"WARNING: ownership change on %s failed %s",
317*7c478bd9Sstevel@tonic-gate 				mapname, sm_errstring(errno));
318*7c478bd9Sstevel@tonic-gate 		}
319*7c478bd9Sstevel@tonic-gate 	}
320*7c478bd9Sstevel@tonic-gate 
321*7c478bd9Sstevel@tonic-gate 	exitstat = EX_OK;
322*7c478bd9Sstevel@tonic-gate 	if (query)
323*7c478bd9Sstevel@tonic-gate 	{
324*7c478bd9Sstevel@tonic-gate 		memset(&db_key, '\0', sizeof db_key);
325*7c478bd9Sstevel@tonic-gate 		memset(&db_val, '\0', sizeof db_val);
326*7c478bd9Sstevel@tonic-gate 
327*7c478bd9Sstevel@tonic-gate 		db_key.data = keyname;
328*7c478bd9Sstevel@tonic-gate 		db_key.size = strlen(keyname);
329*7c478bd9Sstevel@tonic-gate 		if (inclnull)
330*7c478bd9Sstevel@tonic-gate 			db_key.size++;
331*7c478bd9Sstevel@tonic-gate 
332*7c478bd9Sstevel@tonic-gate 		errno = database->smdb_get(database, &db_key, &db_val, 0);
333*7c478bd9Sstevel@tonic-gate 		if (errno != SMDBE_OK)
334*7c478bd9Sstevel@tonic-gate 		{
335*7c478bd9Sstevel@tonic-gate 			/* XXX - Need to distinguish between not found */
336*7c478bd9Sstevel@tonic-gate 			fprintf(stderr,
337*7c478bd9Sstevel@tonic-gate 				"%s: couldn't find key %s in map %s\n",
338*7c478bd9Sstevel@tonic-gate 				progname, keyname, mapname);
339*7c478bd9Sstevel@tonic-gate 			exitstat = EX_UNAVAILABLE;
340*7c478bd9Sstevel@tonic-gate 		}
341*7c478bd9Sstevel@tonic-gate 		else
342*7c478bd9Sstevel@tonic-gate 		{
343*7c478bd9Sstevel@tonic-gate 			printf("%.*s\n", (int) db_val.size,
344*7c478bd9Sstevel@tonic-gate 			       (char *) db_val.data);
345*7c478bd9Sstevel@tonic-gate 		}
346*7c478bd9Sstevel@tonic-gate 	}
347*7c478bd9Sstevel@tonic-gate 	else if (update)
348*7c478bd9Sstevel@tonic-gate 	{
349*7c478bd9Sstevel@tonic-gate 		memset(&db_key, '\0', sizeof db_key);
350*7c478bd9Sstevel@tonic-gate 		memset(&db_val, '\0', sizeof db_val);
351*7c478bd9Sstevel@tonic-gate 
352*7c478bd9Sstevel@tonic-gate 		db_key.data = keyname;
353*7c478bd9Sstevel@tonic-gate 		db_key.size = strlen(keyname);
354*7c478bd9Sstevel@tonic-gate 		if (inclnull)
355*7c478bd9Sstevel@tonic-gate 			db_key.size++;
356*7c478bd9Sstevel@tonic-gate 		db_val.data = value;
357*7c478bd9Sstevel@tonic-gate 		db_val.size = strlen(value);
358*7c478bd9Sstevel@tonic-gate 		if (inclnull)
359*7c478bd9Sstevel@tonic-gate 			db_val.size++;
360*7c478bd9Sstevel@tonic-gate 
361*7c478bd9Sstevel@tonic-gate 		errno = database->smdb_put(database, &db_key, &db_val,
362*7c478bd9Sstevel@tonic-gate 					   putflags);
363*7c478bd9Sstevel@tonic-gate 		if (errno != SMDBE_OK)
364*7c478bd9Sstevel@tonic-gate 		{
365*7c478bd9Sstevel@tonic-gate 			fprintf(stderr,
366*7c478bd9Sstevel@tonic-gate 				"%s: error updating (%s, %s) in map %s: %s\n",
367*7c478bd9Sstevel@tonic-gate 				progname, keyname, value, mapname,
368*7c478bd9Sstevel@tonic-gate 				sm_errstring(errno));
369*7c478bd9Sstevel@tonic-gate 			exitstat = EX_IOERR;
370*7c478bd9Sstevel@tonic-gate 		}
371*7c478bd9Sstevel@tonic-gate 	}
372*7c478bd9Sstevel@tonic-gate 	else if (remove)
373*7c478bd9Sstevel@tonic-gate 	{
374*7c478bd9Sstevel@tonic-gate 		memset(&db_key, '\0', sizeof db_key);
375*7c478bd9Sstevel@tonic-gate 		memset(&db_val, '\0', sizeof db_val);
376*7c478bd9Sstevel@tonic-gate 
377*7c478bd9Sstevel@tonic-gate 		db_key.data = keyname;
378*7c478bd9Sstevel@tonic-gate 		db_key.size = strlen(keyname);
379*7c478bd9Sstevel@tonic-gate 		if (inclnull)
380*7c478bd9Sstevel@tonic-gate 			db_key.size++;
381*7c478bd9Sstevel@tonic-gate 
382*7c478bd9Sstevel@tonic-gate 		errno = database->smdb_del(database, &db_key, 0);
383*7c478bd9Sstevel@tonic-gate 
384*7c478bd9Sstevel@tonic-gate 		switch (errno)
385*7c478bd9Sstevel@tonic-gate 		{
386*7c478bd9Sstevel@tonic-gate 		case SMDBE_NOT_FOUND:
387*7c478bd9Sstevel@tonic-gate 			fprintf(stderr,
388*7c478bd9Sstevel@tonic-gate 				"%s: key %s doesn't exist in map %s\n",
389*7c478bd9Sstevel@tonic-gate 				progname, keyname, mapname);
390*7c478bd9Sstevel@tonic-gate 			/* Don't set exitstat */
391*7c478bd9Sstevel@tonic-gate 			break;
392*7c478bd9Sstevel@tonic-gate 		case SMDBE_OK:
393*7c478bd9Sstevel@tonic-gate 			/* All's well */
394*7c478bd9Sstevel@tonic-gate 			break;
395*7c478bd9Sstevel@tonic-gate 		default:
396*7c478bd9Sstevel@tonic-gate 			fprintf(stderr,
397*7c478bd9Sstevel@tonic-gate 				"%s: couldn't remove key %s in map %s (error)\n",
398*7c478bd9Sstevel@tonic-gate 				progname, keyname, mapname);
399*7c478bd9Sstevel@tonic-gate 			exitstat = EX_IOERR;
400*7c478bd9Sstevel@tonic-gate 			break;
401*7c478bd9Sstevel@tonic-gate 		}
402*7c478bd9Sstevel@tonic-gate 	}
403*7c478bd9Sstevel@tonic-gate 	else
404*7c478bd9Sstevel@tonic-gate 	{
405*7c478bd9Sstevel@tonic-gate 		assert(0);  /* NOT REACHED */
406*7c478bd9Sstevel@tonic-gate 	}
407*7c478bd9Sstevel@tonic-gate 
408*7c478bd9Sstevel@tonic-gate 	/*
409*7c478bd9Sstevel@tonic-gate 	**  Now close the database.
410*7c478bd9Sstevel@tonic-gate 	*/
411*7c478bd9Sstevel@tonic-gate 
412*7c478bd9Sstevel@tonic-gate 	errno = database->smdb_close(database);
413*7c478bd9Sstevel@tonic-gate 	if (errno != SMDBE_OK)
414*7c478bd9Sstevel@tonic-gate 	{
415*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%s: close(%s): %s\n",
416*7c478bd9Sstevel@tonic-gate 			progname, mapname, sm_errstring(errno));
417*7c478bd9Sstevel@tonic-gate 		exitstat = EX_IOERR;
418*7c478bd9Sstevel@tonic-gate 	}
419*7c478bd9Sstevel@tonic-gate 	smdb_free_database(database);
420*7c478bd9Sstevel@tonic-gate 
421*7c478bd9Sstevel@tonic-gate 	exit(exitstat);
422*7c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
423*7c478bd9Sstevel@tonic-gate 	return exitstat;
424*7c478bd9Sstevel@tonic-gate }
425