2 * Copyright (c) 1998-2002 Sendmail, Inc. and its suppliers.
4 * Copyright (c) 1992 Eric P. Allman. All rights reserved.
5 * Copyright (c) 1992, 1993
6 * The Regents of the University of California. All rights reserved.
8 * By using this file, you agree to the terms and conditions set
9 * forth in the LICENSE file which can be found at the top level of
10 * the sendmail distribution.
16 SM_UNUSED(static char copyright[]) =
17 "@(#) Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers.\n\
18 All rights reserved.\n\
19 Copyright (c) 1992 Eric P. Allman. All rights reserved.\n\
20 Copyright (c) 1992, 1993\n\
21 The Regents of the University of California. All rights reserved.\n";
25 SM_UNUSED(static char id[]) = "@(#)$Id: editmap.c,v 1.23 2002/03/28 17:49:33 gshapiro Exp $";
29 #include <sys/types.h>
31 # include <sys/file.h>
32 #endif /* ! ISC_UNIX */
37 # undef EX_OK /* unistd.h may have another use for this */
41 #include <sendmail/sendmail.h>
42 #include <sendmail/pathnames.h>
43 #include <libsmdb/smdb.h>
52 bool DontInitGroups = false;
54 BITMAP256 DontBlameSendmail;
57 #define ISSEP(c) (isascii(c) && isspace(c))
65 "Usage: %s [-C cffile] [-N] [-f] [-q|-u|-x] maptype mapname key [ \"value ...\" ]\n",
81 bool inclnull = false;
83 unsigned int nops = 0;
86 char *typename = NULL;
93 long sff = SFF_ROOTOK|SFF_REGONLY;
95 SMDB_DATABASE *database;
96 SMDB_DBENT db_key, db_val;
98 SMDB_USER_INFO user_info;
102 #endif /* HASFCHOWN */
103 static char rnamebuf[MAXNAME]; /* holds RealUserName */
107 memset(¶ms, '\0', sizeof params);
108 params.smdbp_cache_size = 1024 * 1024;
110 progname = strrchr(argv[0], '/');
111 if (progname != NULL)
115 cfile = _PATH_SENDMAILCF;
117 clrbitmap(DontBlameSendmail);
118 RunAsUid = RealUid = getuid();
119 RunAsGid = RealGid = getgid();
120 pw = getpwuid(RealUid);
122 (void) sm_strlcpy(rnamebuf, pw->pw_name, sizeof rnamebuf);
124 (void) sm_snprintf(rnamebuf, sizeof rnamebuf,
125 "Unknown UID %d", (int) RealUid);
126 RunAsUserName = RealUserName = rnamebuf;
127 user_info.smdbu_id = RunAsUid;
128 user_info.smdbu_group_id = RunAsGid;
129 (void) sm_strlcpy(user_info.smdbu_name, RunAsUserName,
130 SMDB_MAX_USER_NAME_LEN);
132 #define OPTIONS "C:fquxvN"
133 while ((opt = getopt(argc, argv, OPTIONS)) != -1)
170 assert(0); /* NOTREACHED */
174 if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail))
176 if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail))
178 if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail))
184 (query && argc != 3) ||
185 (remove && argc != 3) ||
186 (update && argc <= 3))
189 assert(0); /* NOTREACHED */
202 for (p = keyname; *p != '\0'; p++)
204 if (isascii(*p) && isupper(*p))
211 /* Find TrustedUser value in sendmail.cf */
212 if ((cfp = fopen(cfile, "r")) == NULL)
214 fprintf(stderr, "%s: %s: %s\n", progname,
215 cfile, sm_errstring(errno));
218 while (fgets(buf, sizeof(buf), cfp) != NULL)
222 if ((b = strchr(buf, '\n')) != NULL)
228 case 'O': /* option */
229 if (strncasecmp(b, " TrustedUser", 12) == 0 &&
230 !(isascii(b[12]) && isalnum(b[12])))
235 while (isascii(*++b) && isspace(*b))
237 if (isascii(*b) && isdigit(*b))
238 TrustedUid = atoi(b);
245 "TrustedUser: unknown user %s\n", b);
247 TrustedUid = pw->pw_uid;
251 if (TrustedUid > UID_MAX)
254 "TrustedUser: uid value (%ld) > UID_MAX (%ld)",
259 # endif /* UID_MAX */
269 #endif /* HASFCHOWN */
278 mode = O_RDWR | O_CREAT;
279 sff |= SFF_CREAT|SFF_NOTEXCL;
283 params.smdbp_num_elements = 4096;
285 errno = smdb_open_database(&database, mapname, mode, smode, sff,
286 typename, &user_info, ¶ms);
287 if (errno != SMDBE_OK)
291 if (errno == SMDBE_UNSUPPORTED_DB_TYPE &&
292 (hint = smdb_db_definition(typename)) != NULL)
294 "%s: Need to recompile with -D%s for %s support\n",
295 progname, hint, typename);
298 "%s: error opening type %s map %s: %s\n",
299 progname, typename, mapname,
300 sm_errstring(errno));
304 (void) database->smdb_sync(database, 0);
306 if (geteuid() == 0 && TrustedUid != 0)
308 errno = database->smdb_set_owner(database, TrustedUid, -1);
309 if (errno != SMDBE_OK)
312 "WARNING: ownership change on %s failed %s",
313 mapname, sm_errstring(errno));
320 memset(&db_key, '\0', sizeof db_key);
321 memset(&db_val, '\0', sizeof db_val);
323 db_key.data = keyname;
324 db_key.size = strlen(keyname);
328 errno = database->smdb_get(database, &db_key, &db_val, 0);
329 if (errno != SMDBE_OK)
331 /* XXX - Need to distinguish between not found */
333 "%s: couldn't find key %s in map %s\n",
334 progname, keyname, mapname);
335 exitstat = EX_UNAVAILABLE;
339 printf("%.*s\n", (int) db_val.size,
340 (char *) db_val.data);
345 memset(&db_key, '\0', sizeof db_key);
346 memset(&db_val, '\0', sizeof db_val);
348 db_key.data = keyname;
349 db_key.size = strlen(keyname);
353 db_val.size = strlen(value);
357 errno = database->smdb_put(database, &db_key, &db_val,
359 if (errno != SMDBE_OK)
362 "%s: error updating (%s, %s) in map %s: %s\n",
363 progname, keyname, value, mapname,
364 sm_errstring(errno));
370 memset(&db_key, '\0', sizeof db_key);
371 memset(&db_val, '\0', sizeof db_val);
373 db_key.data = keyname;
374 db_key.size = strlen(keyname);
378 errno = database->smdb_del(database, &db_key, 0);
382 case SMDBE_NOT_FOUND:
384 "%s: key %s doesn't exist in map %s\n",
385 progname, keyname, mapname);
386 /* Don't set exitstat */
393 "%s: couldn't remove key %s in map %s (error)\n",
394 progname, keyname, mapname);
401 assert(0); /* NOT REACHED */
405 ** Now close the database.
408 errno = database->smdb_close(database);
409 if (errno != SMDBE_OK)
411 fprintf(stderr, "%s: close(%s): %s\n",
412 progname, mapname, sm_errstring(errno));
415 smdb_free_database(database);