2 * Copyright (c) 1998-2002, 2004 Proofpoint, 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 Proofpoint, 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.26 2013-11-22 20:51:26 ca Exp $";
29 #include <sys/types.h>
31 # include <sys/file.h>
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))
60 static void usage __P((char *));
67 "Usage: %s [-C cffile] [-N] [-f] [-q|-u|-x] maptype mapname key [ \"value ...\" ]\n",
82 bool inclnull = false;
84 unsigned int nops = 0;
87 char *typename = NULL;
94 long sff = SFF_ROOTOK|SFF_REGONLY;
96 SMDB_DATABASE *database;
97 SMDB_DBENT db_key, db_val;
99 SMDB_USER_INFO user_info;
104 static char rnamebuf[MAXNAME]; /* holds RealUserName */
108 memset(¶ms, '\0', sizeof params);
109 params.smdbp_cache_size = 1024 * 1024;
111 progname = strrchr(argv[0], '/');
112 if (progname != NULL)
116 cfile = _PATH_SENDMAILCF;
118 clrbitmap(DontBlameSendmail);
119 RunAsUid = RealUid = getuid();
120 RunAsGid = RealGid = getgid();
121 pw = getpwuid(RealUid);
123 (void) sm_strlcpy(rnamebuf, pw->pw_name, sizeof rnamebuf);
125 (void) sm_snprintf(rnamebuf, sizeof rnamebuf,
126 "Unknown UID %d", (int) RealUid);
127 RunAsUserName = RealUserName = rnamebuf;
128 user_info.smdbu_id = RunAsUid;
129 user_info.smdbu_group_id = RunAsGid;
130 (void) sm_strlcpy(user_info.smdbu_name, RunAsUserName,
131 SMDB_MAX_USER_NAME_LEN);
133 #define OPTIONS "C:fquxN"
134 while ((opt = getopt(argc, argv, OPTIONS)) != -1)
167 assert(0); /* NOTREACHED */
171 if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail))
173 if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail))
175 if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail))
181 (query && argc != 3) ||
182 (remove && argc != 3) ||
183 (update && argc <= 3))
186 assert(0); /* NOTREACHED */
199 for (p = keyname; *p != '\0'; p++)
201 if (isascii(*p) && isupper(*p))
208 /* Find TrustedUser value in sendmail.cf */
209 if ((cfp = fopen(cfile, "r")) == NULL)
211 fprintf(stderr, "%s: %s: %s\n", progname,
212 cfile, sm_errstring(errno));
215 while (fgets(buf, sizeof(buf), cfp) != NULL)
219 if ((b = strchr(buf, '\n')) != NULL)
225 case 'O': /* option */
226 if (strncasecmp(b, " TrustedUser", 12) == 0 &&
227 !(isascii(b[12]) && isalnum(b[12])))
232 while (isascii(*++b) && isspace(*b))
234 if (isascii(*b) && isdigit(*b))
235 TrustedUid = atoi(b);
242 "TrustedUser: unknown user %s\n", b);
244 TrustedUid = pw->pw_uid;
248 if (TrustedUid > UID_MAX)
251 "TrustedUser: uid value (%ld) > UID_MAX (%ld)",
256 # endif /* UID_MAX */
266 #endif /* HASFCHOWN */
275 mode = O_RDWR | O_CREAT;
276 sff |= SFF_CREAT|SFF_NOTEXCL;
280 params.smdbp_num_elements = 4096;
282 errno = smdb_open_database(&database, mapname, mode, smode, sff,
283 typename, &user_info, ¶ms);
284 if (errno != SMDBE_OK)
288 if (errno == SMDBE_UNSUPPORTED_DB_TYPE &&
289 (hint = smdb_db_definition(typename)) != NULL)
291 "%s: Need to recompile with -D%s for %s support\n",
292 progname, hint, typename);
295 "%s: error opening type %s map %s: %s\n",
296 progname, typename, mapname,
297 sm_errstring(errno));
301 (void) database->smdb_sync(database, 0);
303 if (geteuid() == 0 && TrustedUid != 0)
305 errno = database->smdb_set_owner(database, TrustedUid, -1);
306 if (errno != SMDBE_OK)
309 "WARNING: ownership change on %s failed %s",
310 mapname, sm_errstring(errno));
317 memset(&db_key, '\0', sizeof db_key);
318 memset(&db_val, '\0', sizeof db_val);
320 db_key.data = keyname;
321 db_key.size = strlen(keyname);
325 errno = database->smdb_get(database, &db_key, &db_val, 0);
326 if (errno != SMDBE_OK)
328 /* XXX - Need to distinguish between not found */
330 "%s: couldn't find key %s in map %s\n",
331 progname, keyname, mapname);
332 exitstat = EX_UNAVAILABLE;
336 printf("%.*s\n", (int) db_val.size,
337 (char *) db_val.data);
342 memset(&db_key, '\0', sizeof db_key);
343 memset(&db_val, '\0', sizeof db_val);
345 db_key.data = keyname;
346 db_key.size = strlen(keyname);
350 db_val.size = strlen(value);
354 errno = database->smdb_put(database, &db_key, &db_val,
356 if (errno != SMDBE_OK)
359 "%s: error updating (%s, %s) in map %s: %s\n",
360 progname, keyname, value, mapname,
361 sm_errstring(errno));
367 memset(&db_key, '\0', sizeof db_key);
368 memset(&db_val, '\0', sizeof db_val);
370 db_key.data = keyname;
371 db_key.size = strlen(keyname);
375 errno = database->smdb_del(database, &db_key, 0);
379 case SMDBE_NOT_FOUND:
381 "%s: key %s doesn't exist in map %s\n",
382 progname, keyname, mapname);
383 /* Don't set exitstat */
390 "%s: couldn't remove key %s in map %s (error)\n",
391 progname, keyname, mapname);
398 assert(0); /* NOT REACHED */
402 ** Now close the database.
405 errno = database->smdb_close(database);
406 if (errno != SMDBE_OK)
408 fprintf(stderr, "%s: close(%s): %s\n",
409 progname, mapname, sm_errstring(errno));
412 smdb_free_database(database);