-/* $Cambridge: exim/src/src/exim_dbmbuild.c,v 1.2 2005/01/04 10:00:42 ph10 Exp $ */
-
/*************************************************
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2005 */
+/* Copyright (c) The Exim Maintainers 2020 - 2024 */
+/* Copyright (c) University of Cambridge 1995 - 2018 */
/* See the file NOTICE for conditions of use and distribution. */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/* A small freestanding program to build dbm databases from serial input. For
#include "exim.h"
+uschar * spool_directory = NULL; /* dummy for hintsdb.h */
+
+/******************************************************************************/
+ /* dummies needed by Solaris build */
+void
+millisleep(int msec)
+{}
+uschar *
+readconf_printtime(int t)
+{ return NULL; }
+void *
+store_get_3(int size, const void * proto_mem, const char *filename, int linenumber)
+{ return NULL; }
+void **
+store_reset_3(void **ptr, const char *filename, int linenumber)
+{ return NULL; }
+void
+store_release_above_3(void *ptr, const char *func, int linenumber)
+{ }
+gstring *
+string_catn(gstring * g, const uschar * s, int count)
+{ return NULL; }
+gstring *
+string_vformat_trc(gstring * g, const uschar * func, unsigned line,
+ unsigned size_limit, unsigned flags, const char *format, va_list ap)
+{ return NULL; }
+uschar *
+string_sprintf_trc(const char * a, const uschar * b, unsigned c, ...)
+{ return NULL; }
+BOOL
+string_format_trc(uschar * buf, int len, const uschar * func, unsigned line,
+ const char * fmt, ...)
+{ return FALSE; }
+void
+log_write(unsigned int selector, int flags, const char *format, ...)
+{ }
+
+
+struct global_flags f;
+unsigned int log_selector[1];
+uschar * queue_name;
+BOOL split_spool_directory;
+
+
+/******************************************************************************/
+
#define max_insize 20000
#define max_outsize 100000
/* This is global because it's defined in the headers and compilers grumble
if it is made static. */
-uschar *hex_digits = US"0123456789abcdef";
+const uschar *hex_digits = CUS"0123456789abcdef";
+
+
+/*******************
+* Debug output *
+*******************/
+
+unsigned int debug_selector = 0; /* set -1 for debugging */
+
+void
+debug_printf(const char * fmt, ...)
+{
+va_list ap;
+va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap);
+}
+void
+debug_printf_indent(const char * fmt, ...)
+{
+va_list ap;
+va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap);
+}
+
#ifdef STRERROR_FROM_ERRLIST
#endif /* STRERROR_FROM_ERRLIST */
-/* For Berkeley DB >= 2, we can define a function to be called in case of DB
-errors. This should help with debugging strange DB problems, e.g. getting "File
-exists" when you try to open a db file. */
-
-#if defined(USE_DB) && defined(DB_VERSION_STRING)
-void
-dbfn_bdb_error_callback(const char *pfx, char *msg)
-{
-pfx = pfx;
-printf("Berkeley DB error: %s\n", msg);
-}
-#endif
-
-
/*************************************************
* Interpret escape sequence *
*/
int
-string_interpret_escape(uschar **pp)
+string_interpret_escape(const uschar **pp)
{
int ch;
-uschar *p = *pp;
+const uschar *p = *pp;
ch = *(++p);
+if (ch == '\0') return **pp;
if (isdigit(ch) && ch != '8' && ch != '9')
{
ch -= '0';
BOOL warn = TRUE;
BOOL duperr = TRUE;
BOOL lastdup = FALSE;
-#if !defined (USE_DB) && !defined(USE_TDB) && !defined(USE_GDBM)
+#if !defined (USE_DB) && !defined(USE_TDB) && !defined(USE_GDBM) && !defined(USE_SQLITE)
int is_db = 0;
struct stat statbuf;
#endif
EXIM_DATUM key, content;
uschar *bptr;
uschar keybuffer[256];
-uschar temp_dbmname[256];
-uschar real_dbmname[256];
+uschar temp_dbmname[512];
+uschar real_dbmname[512];
+uschar dirname[512];
uschar *buffer = malloc(max_outsize);
uschar *line = malloc(max_insize);
if (argc != 3)
{
printf("usage: exim_dbmbuild [-nolc] <source file> <dbm base name>\n");
- exit(1);
+ exit(EXIT_FAILURE);
}
-if (Ustrcmp(argv[arg], "-") == 0) f = stdin; else
+if (Ustrcmp(argv[arg], "-") == 0)
+ f = stdin;
+else if (!(f = fopen(argv[arg], "rb")))
{
- f = fopen(argv[arg], "rb");
- if (f == NULL)
- {
- printf("exim_dbmbuild: unable to open %s: %s\n", argv[arg], strerror(errno));
- exit(1);
- }
+ printf("exim_dbmbuild: unable to open %s: %s\n", argv[arg], strerror(errno));
+ exit(EXIT_FAILURE);
}
/* By default Berkeley db does not put extensions on... which
can be painful! */
-#if defined(USE_DB) || defined(USE_TDB) || defined(USE_GDBM)
+#if defined(USE_DB) || defined(USE_TDB) || defined(USE_GDBM) && !defined(USE_SQLITE)
if (Ustrcmp(argv[arg], argv[arg+1]) == 0)
{
printf("exim_dbmbuild: input and output filenames are the same\n");
- exit(1);
+ exit(EXIT_FAILURE);
}
#endif
-Ustrcpy(temp_dbmname, argv[arg+1]);
-Ustrcat(temp_dbmname, ".dbmbuild_temp");
+/* Check length of filename; allow for adding .dbmbuild_temp and .db or
+.dir/.pag later. */
+
+if (strlen(argv[arg+1]) > sizeof(temp_dbmname) - 20)
+ {
+ printf("exim_dbmbuild: output filename is ridiculously long\n");
+ exit(EXIT_FAILURE);
+ }
+
+Ustrcpy(temp_dbmname, US argv[arg+1]);
+Ustrcat(temp_dbmname, US".dbmbuild_temp");
+
+Ustrcpy(dirname, temp_dbmname);
+if ((bptr = Ustrrchr(dirname, '/')))
+ *bptr = '\0';
+else
+ Ustrcpy(dirname, US".");
/* It is apparently necessary to open with O_RDWR for this to work
with gdbm-1.7.3, though no reading is actually going to be done. */
-EXIM_DBOPEN(temp_dbmname, O_RDWR|O_CREAT|O_EXCL, 0644, &d);
-
-if (d == NULL)
+if (!(d = exim_dbopen(temp_dbmname, dirname, O_RDWR|O_CREAT|O_EXCL, 0644)))
{
printf("exim_dbmbuild: unable to create %s: %s\n", temp_dbmname,
strerror(errno));
- fclose(f);
- exit(1);
+ (void)fclose(f);
+ exit(EXIT_FAILURE);
}
/* Unless using native db calls, see if we have created <name>.db; if not,
assume .dir & .pag */
-#if !defined(USE_DB) && !defined(USE_TDB) && !defined(USE_GDBM)
+#if !defined(USE_DB) && !defined(USE_TDB) && !defined(USE_GDBM) && !defined(USE_SQLITE)
sprintf(CS real_dbmname, "%s.db", temp_dbmname);
is_db = Ustat(real_dbmname, &statbuf) == 0;
#endif
if (len >= max_insize - 1 && p[-1] != '\n')
{
printf("Overlong line read: max permitted length is %d\n", max_insize - 1);
- return 1;
+ yield = 2;
+ goto TIDYUP;
}
if (line[0] == '#') continue;
{
printf("Continued set of lines is too long: max permitted length is %d\n",
max_outsize -1);
- return 1;
+ yield = 2;
+ goto TIDYUP;
}
Ustrcpy(bptr, s);
if (started)
{
- EXIM_DATUM_INIT(content);
- EXIM_DATUM_DATA(content) = CS buffer;
- EXIM_DATUM_SIZE(content) = bptr - buffer + add_zero;
+ exim_datum_init(&content);
+ exim_datum_data_set(&content, buffer);
+ exim_datum_size_set(&content, bptr - buffer + add_zero);
- switch(rc = EXIM_DBPUTB(d, key, content))
+ rc = exim_dbputb(d, &key, &content);
+ switch(rc)
{
case EXIM_DBPUTB_OK:
- count++;
- break;
+ count++;
+ break;
case EXIM_DBPUTB_DUP:
- if (warn) fprintf(stderr, "** Duplicate key \"%s\"\n",
- keybuffer);
- dupcount++;
- if(duperr) yield = 1;
- if (lastdup) EXIM_DBPUT(d, key, content);
- break;
+ if (warn) fprintf(stderr, "** Duplicate key \"%s\"\n", keybuffer);
+ dupcount++;
+ if(duperr) yield = 1;
+ if (lastdup) exim_dbput(d, &key, &content);
+ break;
default:
- fprintf(stderr, "Error %d while writing key %s: errno=%d\n", rc,
- keybuffer, errno);
- yield = 2;
- goto TIDYUP;
+ fprintf(stderr, "Error %d while writing key %s: errno=%d\n", rc,
+ keybuffer, errno);
+ yield = 2;
+ goto TIDYUP;
}
bptr = buffer;
}
- EXIM_DATUM_INIT(key);
- EXIM_DATUM_DATA(key) = CS keybuffer;
+ exim_datum_init(&key);
+ exim_datum_data_set(&key, keybuffer);
/* Deal with quoted keys. Escape sequences always make one character
out of several, so we can re-build in place. */
keystart = t;
while (*s != 0 && *s != '\"')
{
- if (*s == '\\') *t++ = string_interpret_escape(&s);
- else *t++ = *s;
+ *t++ = *s == '\\'
+ ? string_interpret_escape((const uschar **)&s)
+ : *s;
s++;
}
if (*s != 0) s++; /* Past terminating " */
- EXIM_DATUM_SIZE(key) = t - keystart + add_zero;
+ exim_datum_size_set(&key, t - keystart + add_zero);
}
else
{
keystart = s;
- while (*s != 0 && *s != ':' && !isspace(*s)) s++;
- EXIM_DATUM_SIZE(key) = s - keystart + add_zero;
+ while (*s && *s != ':' && !isspace(*s)) s++;
+ exim_datum_size_set(&key, s - keystart + add_zero);
}
- if (EXIM_DATUM_SIZE(key) > 256)
+ if (exim_datum_size_get(&key) > 256)
{
printf("Keys longer than 255 characters cannot be handled\n");
started = 0;
}
if (lowercase)
- {
- for (i = 0; i < EXIM_DATUM_SIZE(key) - add_zero; i++)
+ for (i = 0; i < exim_datum_size_get(&key) - add_zero; i++)
keybuffer[i] = tolower(keystart[i]);
- }
else
- {
- for (i = 0; i < EXIM_DATUM_SIZE(key) - add_zero; i++)
+ for (i = 0; i < exim_datum_size_get(&key) - add_zero; i++)
keybuffer[i] = keystart[i];
- }
keybuffer[i] = 0;
started = 1;
- while (isspace(*s))s++;
+ while (isspace(*s)) s++;
if (*s == ':')
{
s++;
- while (isspace(*s))s++;
+ while (isspace(*s)) s++;
}
if (*s != 0)
{
if (started)
{
int rc;
- EXIM_DATUM_INIT(content);
- EXIM_DATUM_DATA(content) = CS buffer;
- EXIM_DATUM_SIZE(content) = bptr - buffer + add_zero;
+ exim_datum_init(&content);
+ exim_datum_data_set(&content, buffer);
+ exim_datum_size_set(&content, bptr - buffer + add_zero);
- switch(rc = EXIM_DBPUTB(d, key, content))
+ rc = exim_dbputb(d, &key, &content);
+ switch(rc)
{
case EXIM_DBPUTB_OK:
count++;
if (warn) fprintf(stderr, "** Duplicate key \"%s\"\n", keybuffer);
dupcount++;
if (duperr) yield = 1;
- if (lastdup) EXIM_DBPUT(d, key, content);
+ if (lastdup) exim_dbput(d, &key, &content);
break;
default:
TIDYUP:
-EXIM_DBCLOSE(d);
-fclose(f);
+exim_dbclose(d);
+(void)fclose(f);
/* If successful, output the number of entries and rename the temporary
files. */
printf("%d duplicate key%s \n", dupcount, (dupcount > 1)? "s" : "");
}
- #if defined(USE_DB) || defined(USE_TDB) || defined(USE_GDBM)
+#if defined(USE_DB) || defined(USE_TDB) || defined(USE_GDBM) || defined(USE_SQLITE)
Ustrcpy(real_dbmname, temp_dbmname);
- Ustrcpy(buffer, argv[arg+1]);
+ Ustrcpy(buffer, US argv[arg+1]);
if (Urename(real_dbmname, buffer) != 0)
{
printf("Unable to rename %s as %s\n", real_dbmname, buffer);
return 1;
}
- #else
+#else
/* Rename a single .db file */
}
}
- #endif /* USE_DB || USE_TDB || USE_GDBM */
+#endif /* USE_DB || USE_TDB || USE_GDBM || USE_SQLITE */
}
/* Otherwise unlink the temporary files. */
else
{
printf("dbmbuild abandoned\n");
- #if defined(USE_DB) || defined(USE_TDB) || defined(USE_GDBM)
+#if defined(USE_DB) || defined(USE_TDB) || defined(USE_GDBM) || defined(USE_SQLITE)
+ /* We created it, so safe to delete despite the name coming from outside */
+ /* coverity[tainted_string] */
Uunlink(temp_dbmname);
- #else
+#else
if (is_db)
{
sprintf(CS real_dbmname, "%s.db", temp_dbmname);
sprintf(CS real_dbmname, "%s.pag", temp_dbmname);
Uunlink(real_dbmname);
}
- #endif /* USE_DB || USE_TDB */
+#endif /* USE_DB || USE_TDB || USE_GDBM || USE_SQLITE */
}
return yield;
}
/* End of exim_dbmbuild.c */
+/* se aw ai sw=2
+*/