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.
17 "@(#) Copyright (c) 1998-2002, 2004 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")
23 SM_IDSTR(id, "@(#)$Id: makemap.c,v 8.177 2004/08/03 23:57:24 ca Exp $")
26 #include <sys/types.h>
28 # include <sys/file.h>
29 #endif /* ! ISC_UNIX */
34 # undef EX_OK /* unistd.h may have another use for this */
37 #include <sendmail/sendmail.h>
38 #include <sendmail/pathnames.h>
39 #include <libsmdb/smdb.h>
48 bool DontInitGroups = false;
50 BITMAP256 DontBlameSendmail;
53 #define ISSEP(c) (sep == '\0' ? isascii(c) && isspace(c) : (c) == sep)
55 static void usage __P((char *));
61 sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
62 "Usage: %s [-C cffile] [-N] [-c cachesize] [-D commentchar]\n",
64 sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
65 " %*s [-d] [-e] [-f] [-l] [-o] [-r] [-s] [-t delimiter]\n",
66 (int) strlen(progname), "");
67 sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
68 " %*s [-u] [-v] type mapname\n",
69 (int) strlen(progname), "");
80 bool inclnull = false;
82 bool allowreplace = false;
83 bool allowempty = false;
91 char *typename = NULL;
98 long sff = SFF_ROOTOK|SFF_REGONLY;
100 SMDB_DATABASE *database;
102 SMDB_DBENT db_key, db_val;
103 SMDB_DBPARAMS params;
104 SMDB_USER_INFO user_info;
109 #endif /* HASFCHOWN */
110 static char rnamebuf[MAXNAME]; /* holds RealUserName */
114 memset(¶ms, '\0', sizeof params);
115 params.smdbp_cache_size = 1024 * 1024;
117 progname = strrchr(argv[0], '/');
118 if (progname != NULL)
122 cfile = getcfname(0, 0, SM_GET_SENDMAIL_CF, NULL);
124 clrbitmap(DontBlameSendmail);
125 RunAsUid = RealUid = getuid();
126 RunAsGid = RealGid = getgid();
127 pw = getpwuid(RealUid);
129 (void) sm_strlcpy(rnamebuf, pw->pw_name, sizeof rnamebuf);
131 (void) sm_snprintf(rnamebuf, sizeof rnamebuf,
132 "Unknown UID %d", (int) RealUid);
133 RunAsUserName = RealUserName = rnamebuf;
134 user_info.smdbu_id = RunAsUid;
135 user_info.smdbu_group_id = RunAsGid;
136 (void) sm_strlcpy(user_info.smdbu_name, RunAsUserName,
137 SMDB_MAX_USER_NAME_LEN);
139 #define OPTIONS "C:D:Nc:deflorst:uv"
140 while ((opt = getopt(argc, argv, OPTIONS)) != -1)
153 params.smdbp_cache_size = atol(optarg);
157 params.smdbp_allow_dup = true;
173 smdb_print_available_types();
186 setbitn(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail);
187 setbitn(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail);
188 setbitn(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail);
189 setbitn(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail);
193 if (optarg == NULL || *optarg == '\0')
195 sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
196 "Invalid separator\n");
216 if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail))
218 if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail))
220 if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail))
237 /* Find TrustedUser value in sendmail.cf */
238 if ((cfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, cfile, SM_IO_RDONLY,
241 sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "makemap: %s: %s",
242 cfile, sm_errstring(errno));
245 while (sm_io_fgets(cfp, SM_TIME_DEFAULT, buf, sizeof(buf)) != NULL)
249 if ((b = strchr(buf, '\n')) != NULL)
255 case 'O': /* option */
256 if (strncasecmp(b, " TrustedUser", 12) == 0 &&
257 !(isascii(b[12]) && isalnum(b[12])))
262 while (isascii(*++b) && isspace(*b))
264 if (isascii(*b) && isdigit(*b))
265 TrustedUid = atoi(b);
271 (void) sm_io_fprintf(smioerr,
273 "TrustedUser: unknown user %s\n", b);
275 TrustedUid = pw->pw_uid;
279 if (TrustedUid > UID_MAX)
281 (void) sm_io_fprintf(smioerr,
283 "TrustedUser: uid value (%ld) > UID_MAX (%ld)",
288 # endif /* UID_MAX */
297 (void) sm_io_close(cfp, SM_TIME_DEFAULT);
298 #endif /* HASFCHOWN */
300 if (!params.smdbp_allow_dup && !allowreplace)
301 putflags = SMDBF_NO_OVERWRITE;
313 mode |= O_CREAT|O_TRUNC;
319 params.smdbp_num_elements = 4096;
321 errno = smdb_open_database(&database, mapname, mode, smode, sff,
322 typename, &user_info, ¶ms);
323 if (errno != SMDBE_OK)
327 if (errno == SMDBE_UNSUPPORTED_DB_TYPE &&
328 (hint = smdb_db_definition(typename)) != NULL)
329 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
330 "%s: Need to recompile with -D%s for %s support\n",
331 progname, hint, typename);
333 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
334 "%s: error opening type %s map %s: %s\n",
335 progname, typename, mapname,
336 sm_errstring(errno));
340 (void) database->smdb_sync(database, 0);
342 if (!unmake && geteuid() == 0 && TrustedUid != 0)
344 errno = database->smdb_set_owner(database, TrustedUid, -1);
345 if (errno != SMDBE_OK)
347 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
348 "WARNING: ownership change on %s failed %s",
349 mapname, sm_errstring(errno));
360 errno = database->smdb_cursor(database, &cursor, 0);
361 if (errno != SMDBE_OK)
364 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
365 "%s: cannot make cursor for type %s map %s\n",
366 progname, typename, mapname);
370 memset(&db_key, '\0', sizeof db_key);
371 memset(&db_val, '\0', sizeof db_val);
373 for (lineno = 0; ; lineno++)
375 errno = cursor->smdbc_get(cursor, &db_key, &db_val,
376 SMDB_CURSOR_GET_NEXT);
377 if (errno != SMDBE_OK)
380 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
383 (char *) db_key.data,
385 (char *)db_val.data);
388 (void) cursor->smdbc_close(cursor);
393 while (sm_io_fgets(smioin, SM_TIME_DEFAULT, ibuf, sizeof ibuf)
404 p = strchr(ibuf, '\n');
407 else if (!sm_io_eof(smioin))
409 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
410 "%s: %s: line %u: line too long (%ld bytes max)\n",
411 progname, mapname, lineno,
413 exitstat = EX_DATAERR;
417 if (ibuf[0] == '\0' || ibuf[0] == comment)
419 if (sep == '\0' && isascii(ibuf[0]) && isspace(ibuf[0]))
421 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
422 "%s: %s: line %u: syntax error (leading space)\n",
423 progname, mapname, lineno);
424 exitstat = EX_DATAERR;
428 memset(&db_key, '\0', sizeof db_key);
429 memset(&db_val, '\0', sizeof db_val);
432 for (p = ibuf; *p != '\0' && !(ISSEP(*p)); p++)
434 if (foldcase && isascii(*p) && isupper(*p))
437 db_key.size = p - ibuf;
443 while (*p != '\0' && ISSEP(*p))
445 if (!allowempty && *p == '\0')
447 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
448 "%s: %s: line %u: no RHS for LHS %s\n",
449 progname, mapname, lineno,
450 (char *) db_key.data);
451 exitstat = EX_DATAERR;
456 db_val.size = strlen(p);
461 ** Do the database insert.
466 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
467 "key=`%s', val=`%s'\n",
468 (char *) db_key.data,
469 (char *) db_val.data);
472 errno = database->smdb_put(database, &db_key, &db_val,
476 case SMDBE_KEY_EXIST:
491 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
492 "%s: %s: line %u: key %s: put error: %s\n",
493 progname, mapname, lineno,
494 (char *) db_key.data,
495 sm_errstring(errno));
500 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
501 "%s: %s: line %u: key %s: duplicate key\n",
504 (char *) db_key.data);
505 exitstat = EX_DATAERR;
511 ** Now close the database.
514 errno = database->smdb_close(database);
515 if (errno != SMDBE_OK)
517 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
518 "%s: close(%s): %s\n",
519 progname, mapname, sm_errstring(errno));
522 smdb_free_database(database);