2 * Copyright (c) 1998-2002, 2004 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.25 2007/05/11 18:50:35 ca 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))
60 static void usage
__P((char *));
67 "Usage: %s [-C cffile] [-N] [-f] [-q|-u|-x] maptype mapname key [ \"value ...\" ]\n",
83 bool inclnull
= false;
85 unsigned int nops
= 0;
88 char *typename
= NULL
;
95 long sff
= SFF_ROOTOK
|SFF_REGONLY
;
97 SMDB_DATABASE
*database
;
98 SMDB_DBENT db_key
, db_val
;
100 SMDB_USER_INFO user_info
;
104 #endif /* HASFCHOWN */
105 static char rnamebuf
[MAXNAME
]; /* holds RealUserName */
109 memset(¶ms
, '\0', sizeof params
);
110 params
.smdbp_cache_size
= 1024 * 1024;
112 progname
= strrchr(argv
[0], '/');
113 if (progname
!= NULL
)
117 cfile
= _PATH_SENDMAILCF
;
119 clrbitmap(DontBlameSendmail
);
120 RunAsUid
= RealUid
= getuid();
121 RunAsGid
= RealGid
= getgid();
122 pw
= getpwuid(RealUid
);
124 (void) sm_strlcpy(rnamebuf
, pw
->pw_name
, sizeof rnamebuf
);
126 (void) sm_snprintf(rnamebuf
, sizeof rnamebuf
,
127 "Unknown UID %d", (int) RealUid
);
128 RunAsUserName
= RealUserName
= rnamebuf
;
129 user_info
.smdbu_id
= RunAsUid
;
130 user_info
.smdbu_group_id
= RunAsGid
;
131 (void) sm_strlcpy(user_info
.smdbu_name
, RunAsUserName
,
132 SMDB_MAX_USER_NAME_LEN
);
134 #define OPTIONS "C:fquxvN"
135 while ((opt
= getopt(argc
, argv
, OPTIONS
)) != -1)
172 assert(0); /* NOTREACHED */
176 if (!bitnset(DBS_WRITEMAPTOSYMLINK
, DontBlameSendmail
))
178 if (!bitnset(DBS_WRITEMAPTOHARDLINK
, DontBlameSendmail
))
180 if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR
, DontBlameSendmail
))
186 (query
&& argc
!= 3) ||
187 (remove
&& argc
!= 3) ||
188 (update
&& argc
<= 3))
191 assert(0); /* NOTREACHED */
204 for (p
= keyname
; *p
!= '\0'; p
++)
206 if (isascii(*p
) && isupper(*p
))
213 /* Find TrustedUser value in sendmail.cf */
214 if ((cfp
= fopen(cfile
, "r")) == NULL
)
216 fprintf(stderr
, "%s: %s: %s\n", progname
,
217 cfile
, sm_errstring(errno
));
220 while (fgets(buf
, sizeof(buf
), cfp
) != NULL
)
224 if ((b
= strchr(buf
, '\n')) != NULL
)
230 case 'O': /* option */
231 if (strncasecmp(b
, " TrustedUser", 12) == 0 &&
232 !(isascii(b
[12]) && isalnum(b
[12])))
237 while (isascii(*++b
) && isspace(*b
))
239 if (isascii(*b
) && isdigit(*b
))
240 TrustedUid
= atoi(b
);
247 "TrustedUser: unknown user %s\n", b
);
249 TrustedUid
= pw
->pw_uid
;
253 if (TrustedUid
> UID_MAX
)
256 "TrustedUser: uid value (%ld) > UID_MAX (%ld)",
261 # endif /* UID_MAX */
271 #endif /* HASFCHOWN */
280 mode
= O_RDWR
| O_CREAT
;
281 sff
|= SFF_CREAT
|SFF_NOTEXCL
;
285 params
.smdbp_num_elements
= 4096;
287 errno
= smdb_open_database(&database
, mapname
, mode
, smode
, sff
,
288 typename
, &user_info
, ¶ms
);
289 if (errno
!= SMDBE_OK
)
293 if (errno
== SMDBE_UNSUPPORTED_DB_TYPE
&&
294 (hint
= smdb_db_definition(typename
)) != NULL
)
296 "%s: Need to recompile with -D%s for %s support\n",
297 progname
, hint
, typename
);
300 "%s: error opening type %s map %s: %s\n",
301 progname
, typename
, mapname
,
302 sm_errstring(errno
));
306 (void) database
->smdb_sync(database
, 0);
308 if (geteuid() == 0 && TrustedUid
!= 0)
310 errno
= database
->smdb_set_owner(database
, TrustedUid
, -1);
311 if (errno
!= SMDBE_OK
)
314 "WARNING: ownership change on %s failed %s",
315 mapname
, sm_errstring(errno
));
322 memset(&db_key
, '\0', sizeof db_key
);
323 memset(&db_val
, '\0', sizeof db_val
);
325 db_key
.data
= keyname
;
326 db_key
.size
= strlen(keyname
);
330 errno
= database
->smdb_get(database
, &db_key
, &db_val
, 0);
331 if (errno
!= SMDBE_OK
)
333 /* XXX - Need to distinguish between not found */
335 "%s: couldn't find key %s in map %s\n",
336 progname
, keyname
, mapname
);
337 exitstat
= EX_UNAVAILABLE
;
341 printf("%.*s\n", (int) db_val
.size
,
342 (char *) db_val
.data
);
347 memset(&db_key
, '\0', sizeof db_key
);
348 memset(&db_val
, '\0', sizeof db_val
);
350 db_key
.data
= keyname
;
351 db_key
.size
= strlen(keyname
);
355 db_val
.size
= strlen(value
);
359 errno
= database
->smdb_put(database
, &db_key
, &db_val
,
361 if (errno
!= SMDBE_OK
)
364 "%s: error updating (%s, %s) in map %s: %s\n",
365 progname
, keyname
, value
, mapname
,
366 sm_errstring(errno
));
372 memset(&db_key
, '\0', sizeof db_key
);
373 memset(&db_val
, '\0', sizeof db_val
);
375 db_key
.data
= keyname
;
376 db_key
.size
= strlen(keyname
);
380 errno
= database
->smdb_del(database
, &db_key
, 0);
384 case SMDBE_NOT_FOUND
:
386 "%s: key %s doesn't exist in map %s\n",
387 progname
, keyname
, mapname
);
388 /* Don't set exitstat */
395 "%s: couldn't remove key %s in map %s (error)\n",
396 progname
, keyname
, mapname
);
403 assert(0); /* NOT REACHED */
407 ** Now close the database.
410 errno
= database
->smdb_close(database
);
411 if (errno
!= SMDBE_OK
)
413 fprintf(stderr
, "%s: close(%s): %s\n",
414 progname
, mapname
, sm_errstring(errno
));
417 smdb_free_database(database
);