*************************************************/
/* Copyright (c) University of Cambridge 1995 - 2018 */
+/* Copyright (c) The Exim Maintainers 2020 */
/* See the file NOTICE for conditions of use and distribution. */
misc: miscellaneous hints data
wait-<t>: message waiting information; <t> is a transport name
callout: callout verification cache
+ ratelimit: ACL 'ratelimit' condition
tls: TLS session resumption cache
+ seen: ACL 'seen' condition
There are a number of common subroutines, followed by three main programs,
whose inclusion is controlled by -D on the compilation command. */
#define type_callout 4
#define type_ratelimit 5
#define type_tls 6
+#define type_seen 7
/* This is used by our cut-down dbfn_open(). */
uschar *
string_sprintf_trc(const char * fmt, const uschar * func, unsigned line, ...)
{ return NULL; }
+BOOL
+string_format_trc(uschar * buf, int len, const uschar * func, unsigned line,
+ const char * fmt, ...)
+{ return FALSE; }
struct global_flags f;
unsigned int log_selector[1];
uschar * queue_name;
BOOL split_spool_directory;
+
+
+/* These introduced by the taintwarn handling */
+#ifdef ALLOW_INSECURE_TAINTED_DATA
+BOOL allow_insecure_tainted_data;
+#endif
+
/******************************************************************************/
void
sigalrm_handler(int sig)
{
-sig = sig; /* Keep picky compilers happy */
sigalrm_seen = 1;
}
usage(uschar *name, uschar *options)
{
printf("Usage: exim_%s%s <spool-directory> <database-name>\n", name, options);
-printf(" <database-name> = retry | misc | wait-<transport-name> | callout | ratelimit | tls\n");
+printf(" <database-name> = retry | misc | wait-<transport-name> | callout | ratelimit | tls | seen\n");
exit(1);
}
if (Ustrcmp(argv[2], "callout") == 0) return type_callout;
if (Ustrcmp(argv[2], "ratelimit") == 0) return type_ratelimit;
if (Ustrcmp(argv[2], "tls") == 0) return type_tls;
+ if (Ustrcmp(argv[2], "seen") == 0) return type_seen;
}
usage(name, options);
return -1; /* Never obeyed */
vfprintf(stderr, format, ap);
fprintf(stderr, "\n");
va_end(ap);
-selector = selector; /* Keep picky compilers happy */
-flags = flags;
}
#else
filename = string_sprintf("%s/%s", dirname, name);
#endif
-EXIM_DBOPEN(filename, dirname, flags, 0, &(dbblock->dbptr));
+EXIM_DBOPEN(filename, dirname, flags, 0, &dbblock->dbptr);
if (!dbblock->dbptr)
{
Arguments:
dbblock a pointer to an open database block
key the key of the record to be read
- length where to put the length (or NULL if length not wanted)
+ length where to put the length (or NULL if length not wanted). Includes overhead.
Returns: a pointer to the retrieved record, or
NULL if the record is not found
yield = store_get(EXIM_DATUM_SIZE(result_datum), TRUE);
memcpy(yield, EXIM_DATUM_DATA(result_datum), EXIM_DATUM_SIZE(result_datum));
-if (length != NULL) *length = EXIM_DATUM_SIZE(result_datum);
+if (length) *length = EXIM_DATUM_SIZE(result_datum);
EXIM_DATUM_FREE(result_datum); /* Some DBM libs require freeing */
return yield;
{
EXIM_DATUM key_datum, value_datum;
uschar *yield;
-value_datum = value_datum; /* dummy; not all db libraries use this */
/* Some dbm require an initialization */
uschar **argv = USS cargv;
uschar keybuffer[1024];
+store_init();
+
/* Check the arguments, and open the database */
dbdata_type = check_args(argc, argv, US"dumpdb", US"");
dbdata_ratelimit *ratelimit;
dbdata_ratelimit_unique *rate_unique;
dbdata_tls_session *session;
+ dbdata_seen *seen;
int count_bad = 0;
int length;
uschar *t;
t = wait->text;
name[MESSAGE_ID_LENGTH] = 0;
+ /* Leave corrupt records alone */
if (wait->count > WAIT_NAME_MAX)
{
fprintf(stderr,
session = (dbdata_tls_session *)value;
printf(" %s %.*s\n", keybuffer, length, session->session);
break;
+
+ case type_seen:
+ seen = (dbdata_seen *)value;
+ printf("%s\t%s\n", keybuffer, print_time(seen->time_stamp));
+ break;
}
}
store_reset(reset_point);
uschar name[256];
rmark reset_point;
+store_init();
name[0] = 0; /* No name set */
/* Sort out the database type, verify what we are working on and then process
uschar buffer[256];
uschar *key;
+store_init();
+
/* Scan the options */
for (i = 1; i < argc; i++)
/* A continuation record may have been deleted or renamed already, so
non-existence is not serious. */
- if (value == NULL) continue;
+ if (!value) continue;
/* Delete if too old */
/* Leave corrupt records alone */
+ if (wait->time_stamp > time(NULL))
+ {
+ printf("**** Data for '%s' corrupted\n time in future: %s\n",
+ key, print_time(((dbdata_generic *)value)->time_stamp));
+ continue;
+ }
if (wait->count > WAIT_NAME_MAX)
{
- printf("**** Data for %s corrupted\n count=%d=0x%x max=%d\n",
+ printf("**** Data for '%s' corrupted\n count=%d=0x%x max=%d\n",
key, wait->count, wait->count, WAIT_NAME_MAX);
continue;
}
+ if (wait->sequence > WAIT_CONT_MAX)
+ {
+ printf("**** Data for '%s' corrupted\n sequence=%d=0x%x max=%d\n",
+ key, wait->sequence, wait->sequence, WAIT_CONT_MAX);
+ continue;
+ }
+
+ /* Record over 1 year old; just remove it */
+
+ if (wait->time_stamp < time(NULL) - 365*24*60*60)
+ {
+ dbfn_delete(dbm, key);
+ printf("deleted %s (too old)\n", key);
+ continue;
+ }
/* Loop for renamed continuation records. For each message id,
check to see if the message exists, and if not, remove its entry