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 if (!unmake && geteuid() == 0)
239 /* Find TrustedUser value in sendmail.cf */
240 if ((cfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, cfile,
241 SM_IO_RDONLY, NULL)) == NULL)
243 sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
245 cfile, sm_errstring(errno));
248 while (sm_io_fgets(cfp, SM_TIME_DEFAULT, buf, sizeof(buf)) >= 0)
252 if ((b = strchr(buf, '\n')) != NULL)
258 case 'O': /* option */
259 if (strncasecmp(b, " TrustedUser", 12) == 0 &&
260 !(isascii(b[12]) && isalnum(b[12])))
265 while (isascii(*++b) && isspace(*b))
267 if (isascii(*b) && isdigit(*b))
268 TrustedUid = atoi(b);
274 (void) sm_io_fprintf(smioerr,
276 "TrustedUser: unknown user %s\n", b);
278 TrustedUid = pw->pw_uid;
282 if (TrustedUid > UID_MAX)
284 (void) sm_io_fprintf(smioerr,
286 "TrustedUser: uid value (%ld) > UID_MAX (%ld)",
291 # endif /* UID_MAX */
300 (void) sm_io_close(cfp, SM_TIME_DEFAULT);
302 #endif /* HASFCHOWN */
304 if (!params.smdbp_allow_dup && !allowreplace)
305 putflags = SMDBF_NO_OVERWRITE;
317 mode |= O_CREAT|O_TRUNC;
323 params.smdbp_num_elements = 4096;
325 errno = smdb_open_database(&database, mapname, mode, smode, sff,
326 typename, &user_info, ¶ms);
327 if (errno != SMDBE_OK)
331 if (errno == SMDBE_UNSUPPORTED_DB_TYPE &&
332 (hint = smdb_db_definition(typename)) != NULL)
333 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
334 "%s: Need to recompile with -D%s for %s support\n",
335 progname, hint, typename);
337 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
338 "%s: error opening type %s map %s: %s\n",
339 progname, typename, mapname,
340 sm_errstring(errno));
344 (void) database->smdb_sync(database, 0);
346 if (!unmake && geteuid() == 0 && TrustedUid != 0)
348 errno = database->smdb_set_owner(database, TrustedUid, -1);
349 if (errno != SMDBE_OK)
351 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
352 "WARNING: ownership change on %s failed %s",
353 mapname, sm_errstring(errno));
364 errno = database->smdb_cursor(database, &cursor, 0);
365 if (errno != SMDBE_OK)
368 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
369 "%s: cannot make cursor for type %s map %s\n",
370 progname, typename, mapname);
374 memset(&db_key, '\0', sizeof db_key);
375 memset(&db_val, '\0', sizeof db_val);
377 for (lineno = 0; ; lineno++)
379 errno = cursor->smdbc_get(cursor, &db_key, &db_val,
380 SMDB_CURSOR_GET_NEXT);
381 if (errno != SMDBE_OK)
384 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
387 (char *) db_key.data,
388 (sep != '\0') ? sep : '\t',
390 (char *)db_val.data);
393 (void) cursor->smdbc_close(cursor);
398 while (sm_io_fgets(smioin, SM_TIME_DEFAULT, ibuf, sizeof ibuf)
409 p = strchr(ibuf, '\n');
412 else if (!sm_io_eof(smioin))
414 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
415 "%s: %s: line %u: line too long (%ld bytes max)\n",
416 progname, mapname, lineno,
418 exitstat = EX_DATAERR;
422 if (ibuf[0] == '\0' || ibuf[0] == comment)
424 if (sep == '\0' && isascii(ibuf[0]) && isspace(ibuf[0]))
426 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
427 "%s: %s: line %u: syntax error (leading space)\n",
428 progname, mapname, lineno);
429 exitstat = EX_DATAERR;
433 memset(&db_key, '\0', sizeof db_key);
434 memset(&db_val, '\0', sizeof db_val);
437 for (p = ibuf; *p != '\0' && !(ISSEP(*p)); p++)
439 if (foldcase && isascii(*p) && isupper(*p))
442 db_key.size = p - ibuf;
448 while (*p != '\0' && ISSEP(*p))
450 if (!allowempty && *p == '\0')
452 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
453 "%s: %s: line %u: no RHS for LHS %s\n",
454 progname, mapname, lineno,
455 (char *) db_key.data);
456 exitstat = EX_DATAERR;
461 db_val.size = strlen(p);
466 ** Do the database insert.
471 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
472 "key=`%s', val=`%s'\n",
473 (char *) db_key.data,
474 (char *) db_val.data);
477 errno = database->smdb_put(database, &db_key, &db_val,
481 case SMDBE_KEY_EXIST:
496 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
497 "%s: %s: line %u: key %s: put error: %s\n",
498 progname, mapname, lineno,
499 (char *) db_key.data,
500 sm_errstring(errno));
505 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
506 "%s: %s: line %u: key %s: duplicate key\n",
509 (char *) db_key.data);
510 exitstat = EX_DATAERR;
516 ** Now close the database.
519 errno = database->smdb_close(database);
520 if (errno != SMDBE_OK)
522 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
523 "%s: close(%s): %s\n",
524 progname, mapname, sm_errstring(errno));
527 smdb_free_database(database);