2 * Copyright (c) 1998-2001 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-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")
23 SM_IDSTR(id, "@(#)$Id: makemap.c,v 8.175 2001/12/28 22:44:01 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)
59 /* XXX break the usage output into multiple lines? it's too long */
60 sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
61 "Usage: %s [-C cffile] [-N] [-c cachesize] [-d] [-e] [-f] [-l] [-o] [-r] [-s] [-t delimiter] [-u] [-v] type mapname\n",
64 /* add -D comment-char */
65 #endif /* _FFR_COMMENT_CHAR */
76 bool inclnull = false;
78 bool allowreplace = false;
79 bool allowempty = false;
87 char *typename = NULL;
94 long sff = SFF_ROOTOK|SFF_REGONLY;
96 SMDB_DATABASE *database;
98 SMDB_DBENT db_key, db_val;
100 SMDB_USER_INFO user_info;
105 #endif /* HASFCHOWN */
106 static char rnamebuf[MAXNAME]; /* holds RealUserName */
110 memset(¶ms, '\0', sizeof params);
111 params.smdbp_cache_size = 1024 * 1024;
113 progname = strrchr(argv[0], '/');
114 if (progname != NULL)
118 cfile = getcfname(0, 0, SM_GET_SENDMAIL_CF, NULL);
120 clrbitmap(DontBlameSendmail);
121 RunAsUid = RealUid = getuid();
122 RunAsGid = RealGid = getgid();
123 pw = getpwuid(RealUid);
125 (void) sm_strlcpy(rnamebuf, pw->pw_name, sizeof rnamebuf);
127 (void) sm_snprintf(rnamebuf, sizeof rnamebuf,
128 "Unknown UID %d", (int) RealUid);
129 RunAsUserName = RealUserName = rnamebuf;
130 user_info.smdbu_id = RunAsUid;
131 user_info.smdbu_group_id = RunAsGid;
132 (void) sm_strlcpy(user_info.smdbu_name, RunAsUserName,
133 SMDB_MAX_USER_NAME_LEN);
135 #define OPTIONS "C:D:Nc:deflorst:uv"
136 while ((opt = getopt(argc, argv, OPTIONS)) != -1)
149 params.smdbp_cache_size = atol(optarg);
153 params.smdbp_allow_dup = true;
164 #if _FFR_COMMENT_CHAR
168 #endif /* _FFR_COMMENT_CHAR */
171 smdb_print_available_types();
184 setbitn(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail);
185 setbitn(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail);
186 setbitn(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail);
187 setbitn(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail);
191 if (optarg == NULL || *optarg == '\0')
193 sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
194 "Invalid separator\n");
214 if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail))
216 if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail))
218 if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail))
235 /* Find TrustedUser value in sendmail.cf */
236 if ((cfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, cfile, SM_IO_RDONLY,
239 sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "makemap: %s: %s",
240 cfile, sm_errstring(errno));
243 while (sm_io_fgets(cfp, SM_TIME_DEFAULT, buf, sizeof(buf)) != NULL)
247 if ((b = strchr(buf, '\n')) != NULL)
253 case 'O': /* option */
254 if (strncasecmp(b, " TrustedUser", 12) == 0 &&
255 !(isascii(b[12]) && isalnum(b[12])))
260 while (isascii(*++b) && isspace(*b))
262 if (isascii(*b) && isdigit(*b))
263 TrustedUid = atoi(b);
269 (void) sm_io_fprintf(smioerr,
271 "TrustedUser: unknown user %s\n", b);
273 TrustedUid = pw->pw_uid;
277 if (TrustedUid > UID_MAX)
279 (void) sm_io_fprintf(smioerr,
281 "TrustedUser: uid value (%ld) > UID_MAX (%ld)",
286 # endif /* UID_MAX */
295 (void) sm_io_close(cfp, SM_TIME_DEFAULT);
296 #endif /* HASFCHOWN */
298 if (!params.smdbp_allow_dup && !allowreplace)
299 putflags = SMDBF_NO_OVERWRITE;
311 mode |= O_CREAT|O_TRUNC;
317 params.smdbp_num_elements = 4096;
319 errno = smdb_open_database(&database, mapname, mode, smode, sff,
320 typename, &user_info, ¶ms);
321 if (errno != SMDBE_OK)
325 if (errno == SMDBE_UNSUPPORTED_DB_TYPE &&
326 (hint = smdb_db_definition(typename)) != NULL)
327 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
328 "%s: Need to recompile with -D%s for %s support\n",
329 progname, hint, typename);
331 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
332 "%s: error opening type %s map %s: %s\n",
333 progname, typename, mapname,
334 sm_errstring(errno));
338 (void) database->smdb_sync(database, 0);
340 if (!unmake && geteuid() == 0 && TrustedUid != 0)
342 errno = database->smdb_set_owner(database, TrustedUid, -1);
343 if (errno != SMDBE_OK)
345 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
346 "WARNING: ownership change on %s failed %s",
347 mapname, sm_errstring(errno));
358 errno = database->smdb_cursor(database, &cursor, 0);
359 if (errno != SMDBE_OK)
362 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
363 "%s: cannot make cursor for type %s map %s\n",
364 progname, typename, mapname);
368 memset(&db_key, '\0', sizeof db_key);
369 memset(&db_val, '\0', sizeof db_val);
371 for (lineno = 0; ; lineno++)
373 errno = cursor->smdbc_get(cursor, &db_key, &db_val,
374 SMDB_CURSOR_GET_NEXT);
375 if (errno != SMDBE_OK)
378 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
381 (char *) db_key.data,
383 (char *)db_val.data);
386 (void) cursor->smdbc_close(cursor);
391 while (sm_io_fgets(smioin, SM_TIME_DEFAULT, ibuf, sizeof ibuf)
402 p = strchr(ibuf, '\n');
405 else if (!sm_io_eof(smioin))
407 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
408 "%s: %s: line %u: line too long (%ld bytes max)\n",
409 progname, mapname, lineno,
411 exitstat = EX_DATAERR;
415 if (ibuf[0] == '\0' || ibuf[0] == comment)
417 if (sep == '\0' && isascii(ibuf[0]) && isspace(ibuf[0]))
419 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
420 "%s: %s: line %u: syntax error (leading space)\n",
421 progname, mapname, lineno);
422 exitstat = EX_DATAERR;
426 memset(&db_key, '\0', sizeof db_key);
427 memset(&db_val, '\0', sizeof db_val);
430 for (p = ibuf; *p != '\0' && !(ISSEP(*p)); p++)
432 if (foldcase && isascii(*p) && isupper(*p))
435 db_key.size = p - ibuf;
441 while (*p != '\0' && ISSEP(*p))
443 if (!allowempty && *p == '\0')
445 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
446 "%s: %s: line %u: no RHS for LHS %s\n",
447 progname, mapname, lineno,
448 (char *) db_key.data);
449 exitstat = EX_DATAERR;
454 db_val.size = strlen(p);
459 ** Do the database insert.
464 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
465 "key=`%s', val=`%s'\n",
466 (char *) db_key.data,
467 (char *) db_val.data);
470 errno = database->smdb_put(database, &db_key, &db_val,
474 case SMDBE_KEY_EXIST:
489 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
490 "%s: %s: line %u: key %s: put error: %s\n",
491 progname, mapname, lineno,
492 (char *) db_key.data,
493 sm_errstring(errno));
498 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
499 "%s: %s: line %u: key %s: duplicate key\n",
502 (char *) db_key.data);
503 exitstat = EX_DATAERR;
509 ** Now close the database.
512 errno = database->smdb_close(database);
513 if (errno != SMDBE_OK)
515 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
516 "%s: close(%s): %s\n",
517 progname, mapname, sm_errstring(errno));
520 smdb_free_database(database);