2 * Copyright (c) 1998-2002, 2004, 2008 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.
17 "@(#) Copyright (c) 1998-2002, 2004 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")
23 SM_IDSTR(id, "@(#)$Id: makemap.c,v 8.183 2013-11-22 20:51:52 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\n",
242 cfile, sm_errstring(errno));
245 while (sm_io_fgets(cfp, SM_TIME_DEFAULT, buf, sizeof(buf)) >= 0)
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,
384 (sep != '\0') ? sep : '\t',
386 (char *)db_val.data);
389 (void) cursor->smdbc_close(cursor);
394 while (sm_io_fgets(smioin, SM_TIME_DEFAULT, ibuf, sizeof ibuf)
405 p = strchr(ibuf, '\n');
408 else if (!sm_io_eof(smioin))
410 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
411 "%s: %s: line %u: line too long (%ld bytes max)\n",
412 progname, mapname, lineno,
414 exitstat = EX_DATAERR;
418 if (ibuf[0] == '\0' || ibuf[0] == comment)
420 if (sep == '\0' && isascii(ibuf[0]) && isspace(ibuf[0]))
422 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
423 "%s: %s: line %u: syntax error (leading space)\n",
424 progname, mapname, lineno);
425 exitstat = EX_DATAERR;
429 memset(&db_key, '\0', sizeof db_key);
430 memset(&db_val, '\0', sizeof db_val);
433 for (p = ibuf; *p != '\0' && !(ISSEP(*p)); p++)
435 if (foldcase && isascii(*p) && isupper(*p))
438 db_key.size = p - ibuf;
444 while (*p != '\0' && ISSEP(*p))
446 if (!allowempty && *p == '\0')
448 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
449 "%s: %s: line %u: no RHS for LHS %s\n",
450 progname, mapname, lineno,
451 (char *) db_key.data);
452 exitstat = EX_DATAERR;
457 db_val.size = strlen(p);
462 ** Do the database insert.
467 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
468 "key=`%s', val=`%s'\n",
469 (char *) db_key.data,
470 (char *) db_val.data);
473 errno = database->smdb_put(database, &db_key, &db_val,
477 case SMDBE_KEY_EXIST:
492 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
493 "%s: %s: line %u: key %s: put error: %s\n",
494 progname, mapname, lineno,
495 (char *) db_key.data,
496 sm_errstring(errno));
501 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
502 "%s: %s: line %u: key %s: duplicate key\n",
505 (char *) db_key.data);
506 exitstat = EX_DATAERR;
512 ** Now close the database.
515 errno = database->smdb_close(database);
516 if (errno != SMDBE_OK)
518 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
519 "%s: close(%s): %s\n",
520 progname, mapname, sm_errstring(errno));
523 smdb_free_database(database);