opnsense-src/contrib/sendmail/makemap/makemap.c

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

838 lines
18 KiB
C
Raw Permalink Normal View History

/*
2023-01-15 14:15:36 -05:00
* Copyright (c) 1998-2002, 2004, 2008, 2020 Proofpoint, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1992 Eric P. Allman. All rights reserved.
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*
*/
2002-02-17 16:56:45 -05:00
#include <sm/gen.h>
SM_IDSTR(copyright,
2014-01-26 15:46:55 -05:00
"@(#) Copyright (c) 1998-2002, 2004 Proofpoint, Inc. and its suppliers.\n\
All rights reserved.\n\
Copyright (c) 1992 Eric P. Allman. All rights reserved.\n\
Copyright (c) 1992, 1993\n\
2002-02-17 16:56:45 -05:00
The Regents of the University of California. All rights reserved.\n")
2014-05-21 23:45:17 -04:00
SM_IDSTR(id, "@(#)$Id: makemap.c,v 8.183 2013-11-22 20:51:52 ca Exp $")
#include <sys/types.h>
#ifndef ISC_UNIX
# include <sys/file.h>
2020-07-14 17:40:53 -04:00
#endif
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#ifdef EX_OK
# undef EX_OK /* unistd.h may have another use for this */
2020-07-14 17:40:53 -04:00
#endif
#include <sysexits.h>
#include <sendmail/sendmail.h>
2020-07-14 17:40:53 -04:00
#include <sm/path.h>
#include <sendmail/pathnames.h>
#include <libsmdb/smdb.h>
2023-01-15 14:15:36 -05:00
#if USE_EAI
# include <sm/ixlen.h>
#endif
uid_t RealUid;
gid_t RealGid;
char *RealUserName;
uid_t RunAsUid;
2007-11-04 19:04:21 -05:00
gid_t RunAsGid;
char *RunAsUserName;
int Verbose = 2;
2002-02-17 16:56:45 -05:00
bool DontInitGroups = false;
uid_t TrustedUid = 0;
BITMAP256 DontBlameSendmail;
static bool verbose = false;
static int exitstat;
#define BUFSIZE 1024
2020-07-14 17:40:53 -04:00
#define ISASCII(c) isascii((unsigned char)(c))
#define ISSPACE(c) (ISASCII(c) && isspace(c))
2020-07-14 17:40:53 -04:00
#define ISSEP(c) (sep == '\0' ? ISASCII(c) && isspace(c) : (c) == sep)
2020-07-14 17:40:53 -04:00
static void usage __P((const char *));
static char *readcf __P((const char *, char *, bool));
static void db_put __P((SMDB_DATABASE *, SMDB_DBENT, SMDB_DBENT, int, const char *, int, const char *));
2005-02-13 21:30:00 -05:00
static void
usage(progname)
2020-07-14 17:40:53 -04:00
const char *progname;
{
2002-02-17 16:56:45 -05:00
sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
2004-07-31 21:04:57 -04:00
"Usage: %s [-C cffile] [-N] [-c cachesize] [-D commentchar]\n",
progname);
sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
" %*s [-d] [-e] [-f] [-i type] [-l] [-o] [-r] [-s] [-t delimiter]\n",
2004-07-31 21:04:57 -04:00
(int) strlen(progname), "");
2023-01-15 14:15:36 -05:00
#if _FFR_TESTS
sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
" %*s [-S n]\n",
(int) strlen(progname), "");
#endif
2004-07-31 21:04:57 -04:00
sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
" %*s [-u] [-v] type mapname\n",
(int) strlen(progname), "");
exit(EX_USAGE);
}
/*
** DB_PUT -- do the DB insert
**
** Parameters:
** database -- DB to use
** db_key -- key
** db_val -- value
** putflags -- flags for smdb_put()
** mapname -- name of map (for error reporting)
** lineno -- line number (for error reporting)
** progname -- name of program (for error reporting)
**
** Returns:
** none.
**
** Side effects:
** Sets exitstat so makemap exits with error if put fails
*/
static void
db_put(database, db_key, db_val, putflags, mapname, lineno, progname)
SMDB_DATABASE *database;
SMDB_DBENT db_key, db_val;
int putflags;
const char *mapname;
int lineno;
const char *progname;
{
int errcode;
if (verbose)
{
(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
"key=`%s', val=`%s'\n",
(char *) db_key.data,
(char *) db_val.data);
}
errcode = database->smdb_put(database, &db_key, &db_val, putflags);
if (0 == errcode)
return;
(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "%s: %s: ",
progname, mapname);
if (lineno >= 0)
(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "line %u: ",
lineno);
(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "key %s: ",
(char *) db_key.data);
if (SMDBE_KEY_EXIST == errcode)
{
(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
"duplicate key\n");
exitstat = EX_DATAERR;
}
else
{
(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
"put error: %s\n", sm_errstring(errcode));
exitstat = EX_IOERR;
}
}
2020-07-14 17:40:53 -04:00
/*
** READCF -- read some settings from configuration file.
**
** Parameters:
** cfile -- configuration file name.
** mapfile -- file name of map to look up (if not NULL/empty)
** Note: this finds the first match, so in case someone
** uses the same map file for different maps, they are
** hopefully using the same map type.
** fullpath -- compare the full paths or just the "basename"s?
** (even excluding any .ext !)
**
** Returns:
** pointer to map class name (static!)
*/
static char *
readcf(cfile, mapfile, fullpath)
const char *cfile;
char *mapfile;
bool fullpath;
{
SM_FILE_T *cfp;
char buf[MAXLINE];
static char classbuf[MAXLINE];
char *classname, *mapname;
2020-07-14 17:40:53 -04:00
char *p;
if ((cfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, cfile,
SM_IO_RDONLY, NULL)) == NULL)
{
sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
"makemap: %s: %s\n",
cfile, sm_errstring(errno));
exit(EX_NOINPUT);
}
classname = NULL;
classbuf[0] = '\0';
mapname = mapfile;
2020-07-14 17:40:53 -04:00
if (!fullpath && mapfile != NULL)
{
p = strrchr(mapfile, '/');
if (p != NULL)
mapfile = ++p;
mapname = strdup(mapfile);
if (NULL == mapname)
{
sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
"makemap: strdup(%s) failed: %s\n",
mapfile, sm_errstring(errno));
exit(EX_OSERR);
}
if ((p = strchr(mapname, '.')) != NULL)
2020-07-14 17:40:53 -04:00
*p = '\0';
}
while (sm_io_fgets(cfp, SM_TIME_DEFAULT, buf, sizeof(buf)) >= 0)
{
char *b;
if ((b = strchr(buf, '\n')) != NULL)
*b = '\0';
b = buf;
switch (*b++)
{
case 'O': /* option */
#if HASFCHOWN
if (strncasecmp(b, " TrustedUser", 12) == 0 &&
!(ISASCII(b[12]) && isalnum(b[12])))
{
b = strchr(b, '=');
if (b == NULL)
continue;
while (ISASCII(*++b) && isspace(*b))
continue;
if (ISASCII(*b) && isdigit(*b))
TrustedUid = atoi(b);
else
{
struct passwd *pw;
TrustedUid = 0;
pw = getpwnam(b);
if (pw == NULL)
(void) sm_io_fprintf(smioerr,
SM_TIME_DEFAULT,
"TrustedUser: unknown user %s\n", b);
else
TrustedUid = pw->pw_uid;
}
# ifdef UID_MAX
if (TrustedUid > UID_MAX)
{
(void) sm_io_fprintf(smioerr,
SM_TIME_DEFAULT,
"TrustedUser: uid value (%ld) > UID_MAX (%ld)",
(long) TrustedUid,
(long) UID_MAX);
TrustedUid = 0;
}
# endif /* UID_MAX */
}
#endif /* HASFCHOWN */
break;
case 'K': /* Keyfile (map) */
if (classname != NULL) /* found it already */
continue;
if (mapname == NULL || *mapname == '\0')
2020-07-14 17:40:53 -04:00
continue;
/* cut off trailing spaces */
for (p = buf + strlen(buf) - 1;
ISASCII(*p) && isspace(*p) && p > buf; p--)
2020-07-14 17:40:53 -04:00
*p = '\0';
/* find the last argument */
p = strrchr(buf, ' ');
if (p == NULL)
continue;
b = strstr(p, mapname);
2020-07-14 17:40:53 -04:00
if (b == NULL)
continue;
if (b <= buf)
continue;
if (!fullpath)
{
p = strrchr(b, '.');
if (p != NULL)
*p = '\0';
}
/* allow trailing white space? */
if (strcmp(mapname, b) != 0)
2020-07-14 17:40:53 -04:00
continue;
/* SM_ASSERT(b > buf); */
--b;
if (!ISASCII(*b))
continue;
if (!isspace(*b) && fullpath)
continue;
if (!fullpath && !(SM_IS_DIR_DELIM(*b) || isspace(*b)))
continue;
/* basically from readcf.c */
for (b = buf + 1; ISASCII(*b) && isspace(*b); b++)
;
if (!(ISASCII(*b) && isalnum(*b)))
{
/* syserr("readcf: config K line: no map name"); */
return NULL;
}
while ((ISASCII(*++b) && isalnum(*b)) || *b == '_' || *b == '.')
;
if (*b != '\0')
*b++ = '\0';
while (ISASCII(*b) && isspace(*b))
b++;
if (!(ISASCII(*b) && isalnum(*b)))
{
/* syserr("readcf: config K line, map %s: no map class", b); */
return NULL;
}
classname = b;
while (ISASCII(*++b) && isalnum(*b))
;
if (*b != '\0')
*b++ = '\0';
(void) sm_strlcpy(classbuf, classname, sizeof classbuf);
break;
default:
continue;
}
}
(void) sm_io_close(cfp, SM_TIME_DEFAULT);
/* not really needed because it is just a "one time leak" */
if (mapname != mapfile && mapname != NULL)
{
free(mapname);
mapname = NULL;
}
2020-07-14 17:40:53 -04:00
return classbuf;
}
int
main(argc, argv)
int argc;
char **argv;
{
char *progname;
char *cfile;
2002-02-17 16:56:45 -05:00
bool inclnull = false;
bool notrunc = false;
bool allowreplace = false;
bool allowempty = false;
bool foldcase = true;
bool unmake = false;
#if _FFR_MM_ALIASES
/*
** NOTE: this does not work properly:
** sendmail does address rewriting which is not done here.
*/
bool aliases = false;
#endif
2020-07-14 17:40:53 -04:00
bool didreadcf = false;
char sep = '\0';
2002-02-17 16:56:45 -05:00
char comment = '#';
int opt;
char *typename = NULL;
2020-07-14 17:40:53 -04:00
char *fallback = NULL;
char *mapname = NULL;
2002-02-17 16:56:45 -05:00
unsigned int lineno;
int mode;
int smode;
int putflags = 0;
long sff = SFF_ROOTOK|SFF_REGONLY;
struct passwd *pw;
SMDB_DATABASE *database;
SMDB_CURSOR *cursor;
SMDB_DBENT db_key, db_val;
SMDB_DBPARAMS params;
SMDB_USER_INFO user_info;
char ibuf[BUFSIZE];
static char rnamebuf[MAXNAME]; /* holds RealUserName */
extern char *optarg;
extern int optind;
2023-01-15 14:15:36 -05:00
#if USE_EAI
bool ascii = true;
#endif
#if _FFR_TESTS
int slp = 0;
#endif
memset(&params, '\0', sizeof params);
params.smdbp_cache_size = 1024 * 1024;
progname = strrchr(argv[0], '/');
if (progname != NULL)
progname++;
else
progname = argv[0];
2002-02-17 16:56:45 -05:00
cfile = getcfname(0, 0, SM_GET_SENDMAIL_CF, NULL);
clrbitmap(DontBlameSendmail);
RunAsUid = RealUid = getuid();
RunAsGid = RealGid = getgid();
pw = getpwuid(RealUid);
if (pw != NULL)
2002-02-17 16:56:45 -05:00
(void) sm_strlcpy(rnamebuf, pw->pw_name, sizeof rnamebuf);
else
2002-02-17 16:56:45 -05:00
(void) sm_snprintf(rnamebuf, sizeof rnamebuf,
"Unknown UID %d", (int) RealUid);
RunAsUserName = RealUserName = rnamebuf;
user_info.smdbu_id = RunAsUid;
user_info.smdbu_group_id = RunAsGid;
2002-02-17 16:56:45 -05:00
(void) sm_strlcpy(user_info.smdbu_name, RunAsUserName,
SMDB_MAX_USER_NAME_LEN);
2020-07-14 17:40:53 -04:00
#define OPTIONS "C:D:Nc:defi:Llorst:uvx"
#if _FFR_MM_ALIASES
# define A_OPTIONS "a"
#else
# define A_OPTIONS
#endif
2023-01-15 14:15:36 -05:00
#if _FFR_TESTS
# define X_OPTIONS "S:"
#else
# define X_OPTIONS
#endif
while ((opt = getopt(argc, argv, A_OPTIONS OPTIONS X_OPTIONS)) != -1)
{
switch (opt)
{
case 'C':
cfile = optarg;
break;
case 'N':
2002-02-17 16:56:45 -05:00
inclnull = true;
break;
#if _FFR_MM_ALIASES
case 'a':
/* Note: this doesn't verify e-mail addresses */
sep = ':';
aliases = true;
break;
#endif
case 'c':
params.smdbp_cache_size = atol(optarg);
break;
case 'd':
2002-02-17 16:56:45 -05:00
params.smdbp_allow_dup = true;
break;
case 'e':
2002-02-17 16:56:45 -05:00
allowempty = true;
break;
case 'f':
2002-02-17 16:56:45 -05:00
foldcase = false;
break;
2020-07-14 17:40:53 -04:00
case 'i':
fallback =optarg;
break;
2002-02-17 16:56:45 -05:00
case 'D':
comment = *optarg;
break;
2020-07-14 17:40:53 -04:00
case 'L':
smdb_print_available_types(false);
sm_io_fprintf(smioout, SM_TIME_DEFAULT,
"cf\nCF\n");
exit(EX_OK);
break;
case 'l':
2020-07-14 17:40:53 -04:00
smdb_print_available_types(false);
exit(EX_OK);
break;
case 'o':
2002-02-17 16:56:45 -05:00
notrunc = true;
break;
case 'r':
2002-02-17 16:56:45 -05:00
allowreplace = true;
break;
2023-01-15 14:15:36 -05:00
#if _FFR_TESTS
case 'S':
slp = atoi(optarg);
break;
#endif
case 's':
setbitn(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail);
setbitn(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail);
setbitn(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail);
setbitn(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail);
break;
case 't':
if (optarg == NULL || *optarg == '\0')
{
2002-02-17 16:56:45 -05:00
sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
"Invalid separator\n");
break;
}
sep = *optarg;
break;
case 'u':
2002-02-17 16:56:45 -05:00
unmake = true;
break;
case 'v':
2002-02-17 16:56:45 -05:00
verbose = true;
break;
2023-01-15 14:15:36 -05:00
2020-07-14 17:40:53 -04:00
case 'x':
smdb_print_available_types(true);
exit(EX_OK);
break;
default:
usage(progname);
/* NOTREACHED */
}
}
if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail))
sff |= SFF_NOSLINK;
if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail))
sff |= SFF_NOHLINK;
if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail))
sff |= SFF_NOWLINK;
argc -= optind;
argv += optind;
if (argc != 2)
{
usage(progname);
/* NOTREACHED */
}
else
{
typename = argv[0];
mapname = argv[1];
}
2020-07-14 17:40:53 -04:00
#define TYPEFROMCF (strcasecmp(typename, "cf") == 0)
#define FULLPATHFROMCF (strcmp(typename, "cf") == 0)
#if HASFCHOWN
2020-07-14 17:40:53 -04:00
if (geteuid() == 0)
2015-07-06 00:29:34 -04:00
{
2020-07-14 17:40:53 -04:00
if (TYPEFROMCF)
typename = readcf(cfile, mapname, FULLPATHFROMCF);
else
(void) readcf(cfile, NULL, false);
didreadcf = true;
}
#endif /* HASFCHOWN */
if (!params.smdbp_allow_dup && !allowreplace)
putflags = SMDBF_NO_OVERWRITE;
if (unmake)
{
mode = O_RDONLY;
smode = S_IRUSR;
}
else
{
mode = O_RDWR;
if (!notrunc)
{
mode |= O_CREAT|O_TRUNC;
sff |= SFF_CREAT;
}
smode = S_IWUSR;
}
params.smdbp_num_elements = 4096;
2020-07-14 17:40:53 -04:00
if (!didreadcf && TYPEFROMCF)
{
typename = readcf(cfile, mapname, FULLPATHFROMCF);
didreadcf = true;
}
if (didreadcf && (typename == NULL || *typename == '\0'))
{
if (fallback != NULL && *fallback != '\0')
{
typename = fallback;
if (verbose)
(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
"%s: mapfile %s: not found in %s, using fallback %s\n",
progname, mapname, cfile, fallback);
}
else
{
(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
"%s: mapfile %s: not found in %s\n",
progname, mapname, cfile);
exit(EX_DATAERR);
}
}
/*
** Note: if "implicit" is selected it does not work like
** sendmail: it will just use the first available DB type,
** it won't try several (for -u) to find one that "works".
*/
errno = smdb_open_database(&database, mapname, mode, smode, sff,
typename, &user_info, &params);
if (errno != SMDBE_OK)
{
char *hint;
if (errno == SMDBE_UNSUPPORTED_DB_TYPE &&
(hint = smdb_db_definition(typename)) != NULL)
2002-02-17 16:56:45 -05:00
(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
"%s: Need to recompile with -D%s for %s support\n",
progname, hint, typename);
else
2002-02-17 16:56:45 -05:00
(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
"%s: error opening type %s map %s: %s\n",
progname, typename, mapname,
sm_errstring(errno));
exit(EX_CANTCREAT);
}
(void) database->smdb_sync(database, 0);
if (!unmake && geteuid() == 0 && TrustedUid != 0)
{
errno = database->smdb_set_owner(database, TrustedUid, -1);
if (errno != SMDBE_OK)
{
2002-02-17 16:56:45 -05:00
(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
"WARNING: ownership change on %s failed %s",
mapname, sm_errstring(errno));
}
}
/*
** Copy the data
*/
exitstat = EX_OK;
if (unmake)
{
errno = database->smdb_cursor(database, &cursor, 0);
if (errno != SMDBE_OK)
{
2002-02-17 16:56:45 -05:00
(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
"%s: cannot make cursor for type %s map %s\n",
progname, typename, mapname);
exit(EX_SOFTWARE);
}
memset(&db_key, '\0', sizeof db_key);
memset(&db_val, '\0', sizeof db_val);
2001-01-21 17:17:06 -05:00
for (lineno = 0; ; lineno++)
{
errno = cursor->smdbc_get(cursor, &db_key, &db_val,
SMDB_CURSOR_GET_NEXT);
if (errno != SMDBE_OK)
2001-01-21 17:17:06 -05:00
break;
2002-02-17 16:56:45 -05:00
(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
"%.*s%c%.*s\n",
2002-02-17 16:56:45 -05:00
(int) db_key.size,
(char *) db_key.data,
(sep != '\0') ? sep : '\t',
2002-02-17 16:56:45 -05:00
(int) db_val.size,
(char *)db_val.data);
}
(void) cursor->smdbc_close(cursor);
}
else
{
lineno = 0;
2002-02-17 16:56:45 -05:00
while (sm_io_fgets(smioin, SM_TIME_DEFAULT, ibuf, sizeof ibuf)
2013-04-21 12:35:04 -04:00
>= 0)
{
register char *p;
lineno++;
/*
** Parse the line.
*/
p = strchr(ibuf, '\n');
if (p != NULL)
*p = '\0';
2002-02-17 16:56:45 -05:00
else if (!sm_io_eof(smioin))
{
2002-02-17 16:56:45 -05:00
(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
"%s: %s: line %u: line too long (%ld bytes max)\n",
progname, mapname, lineno,
(long) sizeof ibuf);
exitstat = EX_DATAERR;
continue;
}
2002-02-17 16:56:45 -05:00
if (ibuf[0] == '\0' || ibuf[0] == comment)
continue;
2020-07-14 17:40:53 -04:00
if (sep == '\0' && ISASCII(ibuf[0]) && isspace(ibuf[0]))
{
2002-02-17 16:56:45 -05:00
(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
"%s: %s: line %u: syntax error (leading space)\n",
progname, mapname, lineno);
exitstat = EX_DATAERR;
continue;
}
memset(&db_key, '\0', sizeof db_key);
memset(&db_val, '\0', sizeof db_val);
2001-01-21 17:17:06 -05:00
db_key.data = ibuf;
2023-01-15 14:15:36 -05:00
#if USE_EAI
db_key.size = 0;
if (foldcase)
{
for (p = ibuf; *p != '\0' && !ISSEP(*p); p++)
{
if (!ISASCII(*p))
ascii = false;
}
if (!ascii)
{
char sep;
char *lkey;
sep = *p;
*p = '\0';
lkey = sm_lowercase(ibuf);
db_key.data = lkey;
db_key.size = strlen(lkey);
*p = sep;
}
}
if (ascii)
#endif /* USE_EAI */
/* NOTE: see if () above! */
for (p = ibuf; *p != '\0' && !ISSEP(*p); p++)
{
2020-07-14 17:40:53 -04:00
if (foldcase && ISASCII(*p) && isupper(*p))
*p = tolower(*p);
}
2023-01-15 14:15:36 -05:00
#if USE_EAI
if (0 == db_key.size)
#endif
db_key.size = p - ibuf;
if (inclnull)
2001-01-21 17:17:06 -05:00
db_key.size++;
if (*p != '\0')
*p++ = '\0';
2002-02-17 16:56:45 -05:00
while (*p != '\0' && ISSEP(*p))
p++;
#if _FFR_MM_ALIASES
while (aliases && *p != '\0' && ISSPACE(*p))
p++;
#endif
if (!allowempty && *p == '\0')
{
2002-02-17 16:56:45 -05:00
(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
"%s: %s: line %u: no RHS for LHS %s\n",
progname, mapname, lineno,
(char *) db_key.data);
exitstat = EX_DATAERR;
continue;
}
2001-01-21 17:17:06 -05:00
db_val.data = p;
db_val.size = strlen(p);
if (inclnull)
2001-01-21 17:17:06 -05:00
db_val.size++;
/*
** Do the database insert.
*/
db_put(database, db_key, db_val, putflags, mapname,
lineno, progname);
}
#if _FFR_MM_ALIASES
if (aliases)
{
char magic[2] = "@";
db_key.data = magic;
db_val.data = magic;
db_key.size = 1;
db_val.size = 1;
db_put(database, db_key, db_val, putflags, mapname, -1,
progname);
}
#endif /* _FFR_MM_ALIASES */
}
2023-01-15 14:15:36 -05:00
#if _FFR_TESTS
if (slp > 0)
sleep(slp);
#endif
/*
** Now close the database.
*/
errno = database->smdb_close(database);
if (errno != SMDBE_OK)
{
2002-02-17 16:56:45 -05:00
(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
"%s: close(%s): %s\n",
progname, mapname, sm_errstring(errno));
exitstat = EX_IOERR;
}
smdb_free_database(database);
exit(exitstat);
2002-02-17 16:56:45 -05:00
/* NOTREACHED */
return exitstat;
}