xref: /freebsd/contrib/sendmail/editmap/editmap.c (revision ffb836234b94e17739bac88bfd7f51f5ae49e3bc)
140266059SGregory Neil Shapiro /*
2b6bacd31SGregory Neil Shapiro  * Copyright (c) 1998-2002, 2004 Sendmail, Inc. and its suppliers.
340266059SGregory Neil Shapiro  *	All rights reserved.
440266059SGregory Neil Shapiro  * Copyright (c) 1992 Eric P. Allman.  All rights reserved.
540266059SGregory Neil Shapiro  * Copyright (c) 1992, 1993
640266059SGregory Neil Shapiro  *	The Regents of the University of California.  All rights reserved.
740266059SGregory Neil Shapiro  *
840266059SGregory Neil Shapiro  * By using this file, you agree to the terms and conditions set
940266059SGregory Neil Shapiro  * forth in the LICENSE file which can be found at the top level of
1040266059SGregory Neil Shapiro  * the sendmail distribution.
1140266059SGregory Neil Shapiro  *
1240266059SGregory Neil Shapiro  */
1340266059SGregory Neil Shapiro 
1440266059SGregory Neil Shapiro #include <sm/gen.h>
1540266059SGregory Neil Shapiro #ifndef lint
1640266059SGregory Neil Shapiro SM_UNUSED(static char copyright[]) =
1740266059SGregory Neil Shapiro "@(#) Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers.\n\
1840266059SGregory Neil Shapiro 	All rights reserved.\n\
1940266059SGregory Neil Shapiro      Copyright (c) 1992 Eric P. Allman.  All rights reserved.\n\
2040266059SGregory Neil Shapiro      Copyright (c) 1992, 1993\n\
2140266059SGregory Neil Shapiro 	The Regents of the University of California.  All rights reserved.\n";
2240266059SGregory Neil Shapiro #endif /* ! lint */
2340266059SGregory Neil Shapiro 
2440266059SGregory Neil Shapiro #ifndef lint
25ffb83623SGregory Neil Shapiro SM_UNUSED(static char id[]) = "@(#)$Id: editmap.c,v 1.25 2007/05/11 18:50:35 ca Exp $";
2640266059SGregory Neil Shapiro #endif /* ! lint */
2740266059SGregory Neil Shapiro 
2840266059SGregory Neil Shapiro 
2940266059SGregory Neil Shapiro #include <sys/types.h>
3040266059SGregory Neil Shapiro #ifndef ISC_UNIX
3140266059SGregory Neil Shapiro # include <sys/file.h>
3240266059SGregory Neil Shapiro #endif /* ! ISC_UNIX */
3340266059SGregory Neil Shapiro #include <ctype.h>
3440266059SGregory Neil Shapiro #include <stdlib.h>
3540266059SGregory Neil Shapiro #include <unistd.h>
3640266059SGregory Neil Shapiro #ifdef EX_OK
3740266059SGregory Neil Shapiro # undef EX_OK		/* unistd.h may have another use for this */
3840266059SGregory Neil Shapiro #endif /* EX_OK */
3940266059SGregory Neil Shapiro #include <sysexits.h>
4040266059SGregory Neil Shapiro #include <assert.h>
4140266059SGregory Neil Shapiro #include <sendmail/sendmail.h>
4240266059SGregory Neil Shapiro #include <sendmail/pathnames.h>
4340266059SGregory Neil Shapiro #include <libsmdb/smdb.h>
4440266059SGregory Neil Shapiro 
4540266059SGregory Neil Shapiro uid_t	RealUid;
4640266059SGregory Neil Shapiro gid_t	RealGid;
4740266059SGregory Neil Shapiro char	*RealUserName;
4840266059SGregory Neil Shapiro uid_t	RunAsUid;
49ffb83623SGregory Neil Shapiro gid_t	RunAsGid;
5040266059SGregory Neil Shapiro char	*RunAsUserName;
5140266059SGregory Neil Shapiro int	Verbose = 2;
5240266059SGregory Neil Shapiro bool	DontInitGroups = false;
5340266059SGregory Neil Shapiro uid_t	TrustedUid = 0;
5440266059SGregory Neil Shapiro BITMAP256 DontBlameSendmail;
5540266059SGregory Neil Shapiro 
5640266059SGregory Neil Shapiro #define BUFSIZE		1024
5740266059SGregory Neil Shapiro #define ISSEP(c) (isascii(c) && isspace(c))
5840266059SGregory Neil Shapiro 
5940266059SGregory Neil Shapiro 
60b6bacd31SGregory Neil Shapiro static void usage __P((char *));
61b6bacd31SGregory Neil Shapiro 
6240266059SGregory Neil Shapiro static void
6340266059SGregory Neil Shapiro usage(progname)
6440266059SGregory Neil Shapiro 	char *progname;
6540266059SGregory Neil Shapiro {
6640266059SGregory Neil Shapiro 	fprintf(stderr,
6740266059SGregory Neil Shapiro 		"Usage: %s [-C cffile] [-N] [-f] [-q|-u|-x] maptype mapname key [ \"value ...\" ]\n",
6840266059SGregory Neil Shapiro 		progname);
6940266059SGregory Neil Shapiro 	exit(EX_USAGE);
7040266059SGregory Neil Shapiro }
7140266059SGregory Neil Shapiro 
7240266059SGregory Neil Shapiro int
7340266059SGregory Neil Shapiro main(argc, argv)
7440266059SGregory Neil Shapiro 	int argc;
7540266059SGregory Neil Shapiro 	char **argv;
7640266059SGregory Neil Shapiro {
7740266059SGregory Neil Shapiro 	char *progname;
7840266059SGregory Neil Shapiro 	char *cfile;
7940266059SGregory Neil Shapiro 	bool verbose = false;
8040266059SGregory Neil Shapiro 	bool query = false;
8140266059SGregory Neil Shapiro 	bool update = false;
8240266059SGregory Neil Shapiro 	bool remove = false;
8340266059SGregory Neil Shapiro 	bool inclnull = false;
8440266059SGregory Neil Shapiro 	bool foldcase = true;
8540266059SGregory Neil Shapiro 	unsigned int nops = 0;
8640266059SGregory Neil Shapiro 	int exitstat;
8740266059SGregory Neil Shapiro 	int opt;
8840266059SGregory Neil Shapiro 	char *typename = NULL;
8940266059SGregory Neil Shapiro 	char *mapname = NULL;
9040266059SGregory Neil Shapiro 	char *keyname = NULL;
9140266059SGregory Neil Shapiro 	char *value = NULL;
9240266059SGregory Neil Shapiro 	int mode;
9340266059SGregory Neil Shapiro 	int smode;
9440266059SGregory Neil Shapiro 	int putflags = 0;
9540266059SGregory Neil Shapiro 	long sff = SFF_ROOTOK|SFF_REGONLY;
9640266059SGregory Neil Shapiro 	struct passwd *pw;
9740266059SGregory Neil Shapiro 	SMDB_DATABASE *database;
9840266059SGregory Neil Shapiro 	SMDB_DBENT db_key, db_val;
9940266059SGregory Neil Shapiro 	SMDB_DBPARAMS params;
10040266059SGregory Neil Shapiro 	SMDB_USER_INFO user_info;
10140266059SGregory Neil Shapiro #if HASFCHOWN
10240266059SGregory Neil Shapiro 	FILE *cfp;
10340266059SGregory Neil Shapiro 	char buf[MAXLINE];
10440266059SGregory Neil Shapiro #endif /* HASFCHOWN */
10540266059SGregory Neil Shapiro 	static char rnamebuf[MAXNAME];	/* holds RealUserName */
10640266059SGregory Neil Shapiro 	extern char *optarg;
10740266059SGregory Neil Shapiro 	extern int optind;
10840266059SGregory Neil Shapiro 
10940266059SGregory Neil Shapiro 	memset(&params, '\0', sizeof params);
11040266059SGregory Neil Shapiro 	params.smdbp_cache_size = 1024 * 1024;
11140266059SGregory Neil Shapiro 
11240266059SGregory Neil Shapiro 	progname = strrchr(argv[0], '/');
11340266059SGregory Neil Shapiro 	if (progname != NULL)
11440266059SGregory Neil Shapiro 		progname++;
11540266059SGregory Neil Shapiro 	else
11640266059SGregory Neil Shapiro 		progname = argv[0];
11740266059SGregory Neil Shapiro 	cfile = _PATH_SENDMAILCF;
11840266059SGregory Neil Shapiro 
11940266059SGregory Neil Shapiro 	clrbitmap(DontBlameSendmail);
12040266059SGregory Neil Shapiro 	RunAsUid = RealUid = getuid();
12140266059SGregory Neil Shapiro 	RunAsGid = RealGid = getgid();
12240266059SGregory Neil Shapiro 	pw = getpwuid(RealUid);
12340266059SGregory Neil Shapiro 	if (pw != NULL)
12440266059SGregory Neil Shapiro 		(void) sm_strlcpy(rnamebuf, pw->pw_name, sizeof rnamebuf);
12540266059SGregory Neil Shapiro 	else
12640266059SGregory Neil Shapiro 		(void) sm_snprintf(rnamebuf, sizeof rnamebuf,
12740266059SGregory Neil Shapiro 				   "Unknown UID %d", (int) RealUid);
12840266059SGregory Neil Shapiro 	RunAsUserName = RealUserName = rnamebuf;
12940266059SGregory Neil Shapiro 	user_info.smdbu_id = RunAsUid;
13040266059SGregory Neil Shapiro 	user_info.smdbu_group_id = RunAsGid;
13140266059SGregory Neil Shapiro 	(void) sm_strlcpy(user_info.smdbu_name, RunAsUserName,
13240266059SGregory Neil Shapiro 			  SMDB_MAX_USER_NAME_LEN);
13340266059SGregory Neil Shapiro 
13440266059SGregory Neil Shapiro #define OPTIONS		"C:fquxvN"
13540266059SGregory Neil Shapiro 	while ((opt = getopt(argc, argv, OPTIONS)) != -1)
13640266059SGregory Neil Shapiro 	{
13740266059SGregory Neil Shapiro 		switch (opt)
13840266059SGregory Neil Shapiro 		{
13940266059SGregory Neil Shapiro 		  case 'C':
14040266059SGregory Neil Shapiro 			cfile = optarg;
14140266059SGregory Neil Shapiro 			break;
14240266059SGregory Neil Shapiro 
14340266059SGregory Neil Shapiro 		  case 'f':
14440266059SGregory Neil Shapiro 			foldcase = false;
14540266059SGregory Neil Shapiro 			break;
14640266059SGregory Neil Shapiro 
14740266059SGregory Neil Shapiro 		  case 'q':
14840266059SGregory Neil Shapiro 			query = true;
14940266059SGregory Neil Shapiro 			nops++;
15040266059SGregory Neil Shapiro 			break;
15140266059SGregory Neil Shapiro 
15240266059SGregory Neil Shapiro 		  case 'u':
15340266059SGregory Neil Shapiro 			update = true;
15440266059SGregory Neil Shapiro 			nops++;
15540266059SGregory Neil Shapiro 			break;
15640266059SGregory Neil Shapiro 
15740266059SGregory Neil Shapiro 		  case 'x':
15840266059SGregory Neil Shapiro 			remove = true;
15940266059SGregory Neil Shapiro 			nops++;
16040266059SGregory Neil Shapiro 			break;
16140266059SGregory Neil Shapiro 
16240266059SGregory Neil Shapiro 		  case 'v':
16340266059SGregory Neil Shapiro 			verbose = true;
16440266059SGregory Neil Shapiro 			break;
16540266059SGregory Neil Shapiro 
16640266059SGregory Neil Shapiro 		  case 'N':
16740266059SGregory Neil Shapiro 			inclnull = true;
16840266059SGregory Neil Shapiro 			break;
16940266059SGregory Neil Shapiro 
17040266059SGregory Neil Shapiro 		  default:
17140266059SGregory Neil Shapiro 			usage(progname);
17240266059SGregory Neil Shapiro 			assert(0);  /* NOTREACHED */
17340266059SGregory Neil Shapiro 		}
17440266059SGregory Neil Shapiro 	}
17540266059SGregory Neil Shapiro 
17640266059SGregory Neil Shapiro 	if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail))
17740266059SGregory Neil Shapiro 		sff |= SFF_NOSLINK;
17840266059SGregory Neil Shapiro 	if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail))
17940266059SGregory Neil Shapiro 		sff |= SFF_NOHLINK;
18040266059SGregory Neil Shapiro 	if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail))
18140266059SGregory Neil Shapiro 		sff |= SFF_NOWLINK;
18240266059SGregory Neil Shapiro 
18340266059SGregory Neil Shapiro 	argc -= optind;
18440266059SGregory Neil Shapiro 	argv += optind;
18540266059SGregory Neil Shapiro 	if ((nops != 1) ||
18640266059SGregory Neil Shapiro 	    (query && argc != 3) ||
18740266059SGregory Neil Shapiro 	    (remove && argc != 3) ||
18840266059SGregory Neil Shapiro 	    (update && argc <= 3))
18940266059SGregory Neil Shapiro 	{
19040266059SGregory Neil Shapiro 		usage(progname);
19140266059SGregory Neil Shapiro 		assert(0);  /* NOTREACHED */
19240266059SGregory Neil Shapiro 	}
19340266059SGregory Neil Shapiro 
19440266059SGregory Neil Shapiro 	typename = argv[0];
19540266059SGregory Neil Shapiro 	mapname = argv[1];
19640266059SGregory Neil Shapiro 	keyname = argv[2];
19740266059SGregory Neil Shapiro 	if (update)
19840266059SGregory Neil Shapiro 		value = argv[3];
19940266059SGregory Neil Shapiro 
20040266059SGregory Neil Shapiro 	if (foldcase)
20140266059SGregory Neil Shapiro 	{
20240266059SGregory Neil Shapiro 		char *p;
20340266059SGregory Neil Shapiro 
20440266059SGregory Neil Shapiro 		for (p = keyname; *p != '\0'; p++)
20540266059SGregory Neil Shapiro 		{
20640266059SGregory Neil Shapiro 			if (isascii(*p) && isupper(*p))
20740266059SGregory Neil Shapiro 				*p = tolower(*p);
20840266059SGregory Neil Shapiro 		}
20940266059SGregory Neil Shapiro 	}
21040266059SGregory Neil Shapiro 
21140266059SGregory Neil Shapiro 
21240266059SGregory Neil Shapiro #if HASFCHOWN
21340266059SGregory Neil Shapiro 	/* Find TrustedUser value in sendmail.cf */
21440266059SGregory Neil Shapiro 	if ((cfp = fopen(cfile, "r")) == NULL)
21540266059SGregory Neil Shapiro 	{
21640266059SGregory Neil Shapiro 		fprintf(stderr, "%s: %s: %s\n", progname,
21740266059SGregory Neil Shapiro 			cfile, sm_errstring(errno));
21840266059SGregory Neil Shapiro 		exit(EX_NOINPUT);
21940266059SGregory Neil Shapiro 	}
22040266059SGregory Neil Shapiro 	while (fgets(buf, sizeof(buf), cfp) != NULL)
22140266059SGregory Neil Shapiro 	{
22240266059SGregory Neil Shapiro 		register char *b;
22340266059SGregory Neil Shapiro 
22440266059SGregory Neil Shapiro 		if ((b = strchr(buf, '\n')) != NULL)
22540266059SGregory Neil Shapiro 			*b = '\0';
22640266059SGregory Neil Shapiro 
22740266059SGregory Neil Shapiro 		b = buf;
22840266059SGregory Neil Shapiro 		switch (*b++)
22940266059SGregory Neil Shapiro 		{
23040266059SGregory Neil Shapiro 		  case 'O':		/* option */
23140266059SGregory Neil Shapiro 			if (strncasecmp(b, " TrustedUser", 12) == 0 &&
23240266059SGregory Neil Shapiro 			    !(isascii(b[12]) && isalnum(b[12])))
23340266059SGregory Neil Shapiro 			{
23440266059SGregory Neil Shapiro 				b = strchr(b, '=');
23540266059SGregory Neil Shapiro 				if (b == NULL)
23640266059SGregory Neil Shapiro 					continue;
23740266059SGregory Neil Shapiro 				while (isascii(*++b) && isspace(*b))
23840266059SGregory Neil Shapiro 					continue;
23940266059SGregory Neil Shapiro 				if (isascii(*b) && isdigit(*b))
24040266059SGregory Neil Shapiro 					TrustedUid = atoi(b);
24140266059SGregory Neil Shapiro 				else
24240266059SGregory Neil Shapiro 				{
24340266059SGregory Neil Shapiro 					TrustedUid = 0;
24440266059SGregory Neil Shapiro 					pw = getpwnam(b);
24540266059SGregory Neil Shapiro 					if (pw == NULL)
24640266059SGregory Neil Shapiro 						fprintf(stderr,
24740266059SGregory Neil Shapiro 							"TrustedUser: unknown user %s\n", b);
24840266059SGregory Neil Shapiro 					else
24940266059SGregory Neil Shapiro 						TrustedUid = pw->pw_uid;
25040266059SGregory Neil Shapiro 				}
25140266059SGregory Neil Shapiro 
25240266059SGregory Neil Shapiro # ifdef UID_MAX
25340266059SGregory Neil Shapiro 				if (TrustedUid > UID_MAX)
25440266059SGregory Neil Shapiro 				{
25540266059SGregory Neil Shapiro 					fprintf(stderr,
25640266059SGregory Neil Shapiro 						"TrustedUser: uid value (%ld) > UID_MAX (%ld)",
25740266059SGregory Neil Shapiro 						(long) TrustedUid,
25840266059SGregory Neil Shapiro 						(long) UID_MAX);
25940266059SGregory Neil Shapiro 					TrustedUid = 0;
26040266059SGregory Neil Shapiro 				}
26140266059SGregory Neil Shapiro # endif /* UID_MAX */
26240266059SGregory Neil Shapiro 				break;
26340266059SGregory Neil Shapiro 			}
26440266059SGregory Neil Shapiro 
26540266059SGregory Neil Shapiro 
26640266059SGregory Neil Shapiro 		  default:
26740266059SGregory Neil Shapiro 			continue;
26840266059SGregory Neil Shapiro 		}
26940266059SGregory Neil Shapiro 	}
27040266059SGregory Neil Shapiro 	(void) fclose(cfp);
27140266059SGregory Neil Shapiro #endif /* HASFCHOWN */
27240266059SGregory Neil Shapiro 
27340266059SGregory Neil Shapiro 	if (query)
27440266059SGregory Neil Shapiro 	{
27540266059SGregory Neil Shapiro 		mode = O_RDONLY;
27640266059SGregory Neil Shapiro 		smode = S_IRUSR;
27740266059SGregory Neil Shapiro 	}
27840266059SGregory Neil Shapiro 	else
27940266059SGregory Neil Shapiro 	{
28040266059SGregory Neil Shapiro 		mode = O_RDWR | O_CREAT;
28140266059SGregory Neil Shapiro 		sff |= SFF_CREAT|SFF_NOTEXCL;
28240266059SGregory Neil Shapiro 		smode = S_IWUSR;
28340266059SGregory Neil Shapiro 	}
28440266059SGregory Neil Shapiro 
28540266059SGregory Neil Shapiro 	params.smdbp_num_elements = 4096;
28640266059SGregory Neil Shapiro 
28740266059SGregory Neil Shapiro 	errno = smdb_open_database(&database, mapname, mode, smode, sff,
28840266059SGregory Neil Shapiro 				   typename, &user_info, &params);
28940266059SGregory Neil Shapiro 	if (errno != SMDBE_OK)
29040266059SGregory Neil Shapiro 	{
29140266059SGregory Neil Shapiro 		char *hint;
29240266059SGregory Neil Shapiro 
29340266059SGregory Neil Shapiro 		if (errno == SMDBE_UNSUPPORTED_DB_TYPE &&
29440266059SGregory Neil Shapiro 		    (hint = smdb_db_definition(typename)) != NULL)
29540266059SGregory Neil Shapiro 			fprintf(stderr,
29640266059SGregory Neil Shapiro 				"%s: Need to recompile with -D%s for %s support\n",
29740266059SGregory Neil Shapiro 				progname, hint, typename);
29840266059SGregory Neil Shapiro 		else
29940266059SGregory Neil Shapiro 			fprintf(stderr,
30040266059SGregory Neil Shapiro 				"%s: error opening type %s map %s: %s\n",
30140266059SGregory Neil Shapiro 				progname, typename, mapname,
30240266059SGregory Neil Shapiro 				sm_errstring(errno));
30340266059SGregory Neil Shapiro 		exit(EX_CANTCREAT);
30440266059SGregory Neil Shapiro 	}
30540266059SGregory Neil Shapiro 
30640266059SGregory Neil Shapiro 	(void) database->smdb_sync(database, 0);
30740266059SGregory Neil Shapiro 
30840266059SGregory Neil Shapiro 	if (geteuid() == 0 && TrustedUid != 0)
30940266059SGregory Neil Shapiro 	{
31040266059SGregory Neil Shapiro 		errno = database->smdb_set_owner(database, TrustedUid, -1);
31140266059SGregory Neil Shapiro 		if (errno != SMDBE_OK)
31240266059SGregory Neil Shapiro 		{
31340266059SGregory Neil Shapiro 			fprintf(stderr,
31440266059SGregory Neil Shapiro 				"WARNING: ownership change on %s failed %s",
31540266059SGregory Neil Shapiro 				mapname, sm_errstring(errno));
31640266059SGregory Neil Shapiro 		}
31740266059SGregory Neil Shapiro 	}
31840266059SGregory Neil Shapiro 
31940266059SGregory Neil Shapiro 	exitstat = EX_OK;
32040266059SGregory Neil Shapiro 	if (query)
32140266059SGregory Neil Shapiro 	{
32240266059SGregory Neil Shapiro 		memset(&db_key, '\0', sizeof db_key);
32340266059SGregory Neil Shapiro 		memset(&db_val, '\0', sizeof db_val);
32440266059SGregory Neil Shapiro 
32540266059SGregory Neil Shapiro 		db_key.data = keyname;
32640266059SGregory Neil Shapiro 		db_key.size = strlen(keyname);
32740266059SGregory Neil Shapiro 		if (inclnull)
32840266059SGregory Neil Shapiro 			db_key.size++;
32940266059SGregory Neil Shapiro 
33040266059SGregory Neil Shapiro 		errno = database->smdb_get(database, &db_key, &db_val, 0);
33140266059SGregory Neil Shapiro 		if (errno != SMDBE_OK)
33240266059SGregory Neil Shapiro 		{
33340266059SGregory Neil Shapiro 			/* XXX - Need to distinguish between not found */
33440266059SGregory Neil Shapiro 			fprintf(stderr,
33540266059SGregory Neil Shapiro 				"%s: couldn't find key %s in map %s\n",
33640266059SGregory Neil Shapiro 				progname, keyname, mapname);
33740266059SGregory Neil Shapiro 			exitstat = EX_UNAVAILABLE;
33840266059SGregory Neil Shapiro 		}
33940266059SGregory Neil Shapiro 		else
34040266059SGregory Neil Shapiro 		{
34140266059SGregory Neil Shapiro 			printf("%.*s\n", (int) db_val.size,
34240266059SGregory Neil Shapiro 			       (char *) db_val.data);
34340266059SGregory Neil Shapiro 		}
34440266059SGregory Neil Shapiro 	}
34540266059SGregory Neil Shapiro 	else if (update)
34640266059SGregory Neil Shapiro 	{
34740266059SGregory Neil Shapiro 		memset(&db_key, '\0', sizeof db_key);
34840266059SGregory Neil Shapiro 		memset(&db_val, '\0', sizeof db_val);
34940266059SGregory Neil Shapiro 
35040266059SGregory Neil Shapiro 		db_key.data = keyname;
35140266059SGregory Neil Shapiro 		db_key.size = strlen(keyname);
35240266059SGregory Neil Shapiro 		if (inclnull)
35340266059SGregory Neil Shapiro 			db_key.size++;
35440266059SGregory Neil Shapiro 		db_val.data = value;
35540266059SGregory Neil Shapiro 		db_val.size = strlen(value);
35640266059SGregory Neil Shapiro 		if (inclnull)
35740266059SGregory Neil Shapiro 			db_val.size++;
35840266059SGregory Neil Shapiro 
35940266059SGregory Neil Shapiro 		errno = database->smdb_put(database, &db_key, &db_val,
36040266059SGregory Neil Shapiro 					   putflags);
36140266059SGregory Neil Shapiro 		if (errno != SMDBE_OK)
36240266059SGregory Neil Shapiro 		{
36340266059SGregory Neil Shapiro 			fprintf(stderr,
36440266059SGregory Neil Shapiro 				"%s: error updating (%s, %s) in map %s: %s\n",
36540266059SGregory Neil Shapiro 				progname, keyname, value, mapname,
36640266059SGregory Neil Shapiro 				sm_errstring(errno));
36740266059SGregory Neil Shapiro 			exitstat = EX_IOERR;
36840266059SGregory Neil Shapiro 		}
36940266059SGregory Neil Shapiro 	}
37040266059SGregory Neil Shapiro 	else if (remove)
37140266059SGregory Neil Shapiro 	{
37240266059SGregory Neil Shapiro 		memset(&db_key, '\0', sizeof db_key);
37340266059SGregory Neil Shapiro 		memset(&db_val, '\0', sizeof db_val);
37440266059SGregory Neil Shapiro 
37540266059SGregory Neil Shapiro 		db_key.data = keyname;
37640266059SGregory Neil Shapiro 		db_key.size = strlen(keyname);
37740266059SGregory Neil Shapiro 		if (inclnull)
37840266059SGregory Neil Shapiro 			db_key.size++;
37940266059SGregory Neil Shapiro 
38040266059SGregory Neil Shapiro 		errno = database->smdb_del(database, &db_key, 0);
38140266059SGregory Neil Shapiro 
38240266059SGregory Neil Shapiro 		switch (errno)
38340266059SGregory Neil Shapiro 		{
38440266059SGregory Neil Shapiro 		case SMDBE_NOT_FOUND:
38540266059SGregory Neil Shapiro 			fprintf(stderr,
38640266059SGregory Neil Shapiro 				"%s: key %s doesn't exist in map %s\n",
38740266059SGregory Neil Shapiro 				progname, keyname, mapname);
38840266059SGregory Neil Shapiro 			/* Don't set exitstat */
38940266059SGregory Neil Shapiro 			break;
39040266059SGregory Neil Shapiro 		case SMDBE_OK:
39140266059SGregory Neil Shapiro 			/* All's well */
39240266059SGregory Neil Shapiro 			break;
39340266059SGregory Neil Shapiro 		default:
39440266059SGregory Neil Shapiro 			fprintf(stderr,
39540266059SGregory Neil Shapiro 				"%s: couldn't remove key %s in map %s (error)\n",
39640266059SGregory Neil Shapiro 				progname, keyname, mapname);
39740266059SGregory Neil Shapiro 			exitstat = EX_IOERR;
39840266059SGregory Neil Shapiro 			break;
39940266059SGregory Neil Shapiro 		}
40040266059SGregory Neil Shapiro 	}
40140266059SGregory Neil Shapiro 	else
40240266059SGregory Neil Shapiro 	{
40340266059SGregory Neil Shapiro 		assert(0);  /* NOT REACHED */
40440266059SGregory Neil Shapiro 	}
40540266059SGregory Neil Shapiro 
40640266059SGregory Neil Shapiro 	/*
40740266059SGregory Neil Shapiro 	**  Now close the database.
40840266059SGregory Neil Shapiro 	*/
40940266059SGregory Neil Shapiro 
41040266059SGregory Neil Shapiro 	errno = database->smdb_close(database);
41140266059SGregory Neil Shapiro 	if (errno != SMDBE_OK)
41240266059SGregory Neil Shapiro 	{
41340266059SGregory Neil Shapiro 		fprintf(stderr, "%s: close(%s): %s\n",
41440266059SGregory Neil Shapiro 			progname, mapname, sm_errstring(errno));
41540266059SGregory Neil Shapiro 		exitstat = EX_IOERR;
41640266059SGregory Neil Shapiro 	}
41740266059SGregory Neil Shapiro 	smdb_free_database(database);
41840266059SGregory Neil Shapiro 
41940266059SGregory Neil Shapiro 	exit(exitstat);
42040266059SGregory Neil Shapiro 	/* NOTREACHED */
42140266059SGregory Neil Shapiro 	return exitstat;
42240266059SGregory Neil Shapiro }
423