Sync glob(3) with FreeBSD:
[dragonfly.git] / contrib / sendmail-8.14 / editmap / editmap.c
blob18c352c9be68f47a75ec105b9f87cdbc4dfd9018
1 /*
2 * Copyright (c) 1998-2002, 2004 Sendmail, Inc. and its suppliers.
3 * All rights reserved.
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.
14 #include <sm/gen.h>
15 #ifndef lint
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";
22 #endif /* ! lint */
24 #ifndef lint
25 SM_UNUSED(static char id[]) = "@(#)$Id: editmap.c,v 1.25 2007/05/11 18:50:35 ca Exp $";
26 #endif /* ! lint */
29 #include <sys/types.h>
30 #ifndef ISC_UNIX
31 # include <sys/file.h>
32 #endif /* ! ISC_UNIX */
33 #include <ctype.h>
34 #include <stdlib.h>
35 #include <unistd.h>
36 #ifdef EX_OK
37 # undef EX_OK /* unistd.h may have another use for this */
38 #endif /* EX_OK */
39 #include <sysexits.h>
40 #include <assert.h>
41 #include <sendmail/sendmail.h>
42 #include <sendmail/pathnames.h>
43 #include <libsmdb/smdb.h>
45 uid_t RealUid;
46 gid_t RealGid;
47 char *RealUserName;
48 uid_t RunAsUid;
49 gid_t RunAsGid;
50 char *RunAsUserName;
51 int Verbose = 2;
52 bool DontInitGroups = false;
53 uid_t TrustedUid = 0;
54 BITMAP256 DontBlameSendmail;
56 #define BUFSIZE 1024
57 #define ISSEP(c) (isascii(c) && isspace(c))
60 static void usage __P((char *));
62 static void
63 usage(progname)
64 char *progname;
66 fprintf(stderr,
67 "Usage: %s [-C cffile] [-N] [-f] [-q|-u|-x] maptype mapname key [ \"value ...\" ]\n",
68 progname);
69 exit(EX_USAGE);
72 int
73 main(argc, argv)
74 int argc;
75 char **argv;
77 char *progname;
78 char *cfile;
79 bool verbose = false;
80 bool query = false;
81 bool update = false;
82 bool remove = false;
83 bool inclnull = false;
84 bool foldcase = true;
85 unsigned int nops = 0;
86 int exitstat;
87 int opt;
88 char *typename = NULL;
89 char *mapname = NULL;
90 char *keyname = NULL;
91 char *value = NULL;
92 int mode;
93 int smode;
94 int putflags = 0;
95 long sff = SFF_ROOTOK|SFF_REGONLY;
96 struct passwd *pw;
97 SMDB_DATABASE *database;
98 SMDB_DBENT db_key, db_val;
99 SMDB_DBPARAMS params;
100 SMDB_USER_INFO user_info;
101 #if HASFCHOWN
102 FILE *cfp;
103 char buf[MAXLINE];
104 #endif /* HASFCHOWN */
105 static char rnamebuf[MAXNAME]; /* holds RealUserName */
106 extern char *optarg;
107 extern int optind;
109 memset(&params, '\0', sizeof params);
110 params.smdbp_cache_size = 1024 * 1024;
112 progname = strrchr(argv[0], '/');
113 if (progname != NULL)
114 progname++;
115 else
116 progname = argv[0];
117 cfile = _PATH_SENDMAILCF;
119 clrbitmap(DontBlameSendmail);
120 RunAsUid = RealUid = getuid();
121 RunAsGid = RealGid = getgid();
122 pw = getpwuid(RealUid);
123 if (pw != NULL)
124 (void) sm_strlcpy(rnamebuf, pw->pw_name, sizeof rnamebuf);
125 else
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)
137 switch (opt)
139 case 'C':
140 cfile = optarg;
141 break;
143 case 'f':
144 foldcase = false;
145 break;
147 case 'q':
148 query = true;
149 nops++;
150 break;
152 case 'u':
153 update = true;
154 nops++;
155 break;
157 case 'x':
158 remove = true;
159 nops++;
160 break;
162 case 'v':
163 verbose = true;
164 break;
166 case 'N':
167 inclnull = true;
168 break;
170 default:
171 usage(progname);
172 assert(0); /* NOTREACHED */
176 if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail))
177 sff |= SFF_NOSLINK;
178 if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail))
179 sff |= SFF_NOHLINK;
180 if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail))
181 sff |= SFF_NOWLINK;
183 argc -= optind;
184 argv += optind;
185 if ((nops != 1) ||
186 (query && argc != 3) ||
187 (remove && argc != 3) ||
188 (update && argc <= 3))
190 usage(progname);
191 assert(0); /* NOTREACHED */
194 typename = argv[0];
195 mapname = argv[1];
196 keyname = argv[2];
197 if (update)
198 value = argv[3];
200 if (foldcase)
202 char *p;
204 for (p = keyname; *p != '\0'; p++)
206 if (isascii(*p) && isupper(*p))
207 *p = tolower(*p);
212 #if HASFCHOWN
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));
218 exit(EX_NOINPUT);
220 while (fgets(buf, sizeof(buf), cfp) != NULL)
222 register char *b;
224 if ((b = strchr(buf, '\n')) != NULL)
225 *b = '\0';
227 b = buf;
228 switch (*b++)
230 case 'O': /* option */
231 if (strncasecmp(b, " TrustedUser", 12) == 0 &&
232 !(isascii(b[12]) && isalnum(b[12])))
234 b = strchr(b, '=');
235 if (b == NULL)
236 continue;
237 while (isascii(*++b) && isspace(*b))
238 continue;
239 if (isascii(*b) && isdigit(*b))
240 TrustedUid = atoi(b);
241 else
243 TrustedUid = 0;
244 pw = getpwnam(b);
245 if (pw == NULL)
246 fprintf(stderr,
247 "TrustedUser: unknown user %s\n", b);
248 else
249 TrustedUid = pw->pw_uid;
252 # ifdef UID_MAX
253 if (TrustedUid > UID_MAX)
255 fprintf(stderr,
256 "TrustedUser: uid value (%ld) > UID_MAX (%ld)",
257 (long) TrustedUid,
258 (long) UID_MAX);
259 TrustedUid = 0;
261 # endif /* UID_MAX */
262 break;
266 default:
267 continue;
270 (void) fclose(cfp);
271 #endif /* HASFCHOWN */
273 if (query)
275 mode = O_RDONLY;
276 smode = S_IRUSR;
278 else
280 mode = O_RDWR | O_CREAT;
281 sff |= SFF_CREAT|SFF_NOTEXCL;
282 smode = S_IWUSR;
285 params.smdbp_num_elements = 4096;
287 errno = smdb_open_database(&database, mapname, mode, smode, sff,
288 typename, &user_info, &params);
289 if (errno != SMDBE_OK)
291 char *hint;
293 if (errno == SMDBE_UNSUPPORTED_DB_TYPE &&
294 (hint = smdb_db_definition(typename)) != NULL)
295 fprintf(stderr,
296 "%s: Need to recompile with -D%s for %s support\n",
297 progname, hint, typename);
298 else
299 fprintf(stderr,
300 "%s: error opening type %s map %s: %s\n",
301 progname, typename, mapname,
302 sm_errstring(errno));
303 exit(EX_CANTCREAT);
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)
313 fprintf(stderr,
314 "WARNING: ownership change on %s failed %s",
315 mapname, sm_errstring(errno));
319 exitstat = EX_OK;
320 if (query)
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);
327 if (inclnull)
328 db_key.size++;
330 errno = database->smdb_get(database, &db_key, &db_val, 0);
331 if (errno != SMDBE_OK)
333 /* XXX - Need to distinguish between not found */
334 fprintf(stderr,
335 "%s: couldn't find key %s in map %s\n",
336 progname, keyname, mapname);
337 exitstat = EX_UNAVAILABLE;
339 else
341 printf("%.*s\n", (int) db_val.size,
342 (char *) db_val.data);
345 else if (update)
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);
352 if (inclnull)
353 db_key.size++;
354 db_val.data = value;
355 db_val.size = strlen(value);
356 if (inclnull)
357 db_val.size++;
359 errno = database->smdb_put(database, &db_key, &db_val,
360 putflags);
361 if (errno != SMDBE_OK)
363 fprintf(stderr,
364 "%s: error updating (%s, %s) in map %s: %s\n",
365 progname, keyname, value, mapname,
366 sm_errstring(errno));
367 exitstat = EX_IOERR;
370 else if (remove)
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);
377 if (inclnull)
378 db_key.size++;
380 errno = database->smdb_del(database, &db_key, 0);
382 switch (errno)
384 case SMDBE_NOT_FOUND:
385 fprintf(stderr,
386 "%s: key %s doesn't exist in map %s\n",
387 progname, keyname, mapname);
388 /* Don't set exitstat */
389 break;
390 case SMDBE_OK:
391 /* All's well */
392 break;
393 default:
394 fprintf(stderr,
395 "%s: couldn't remove key %s in map %s (error)\n",
396 progname, keyname, mapname);
397 exitstat = EX_IOERR;
398 break;
401 else
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));
415 exitstat = EX_IOERR;
417 smdb_free_database(database);
419 exit(exitstat);
420 /* NOTREACHED */
421 return exitstat;