UTC output option for exim_dumpdb, exim_fixdb
authorJeremy Harris <jgh146exb@wizmail.org>
Sun, 15 Aug 2021 09:40:02 +0000 (10:40 +0100)
committerJeremy Harris <jgh146exb@wizmail.org>
Sun, 15 Aug 2021 11:47:01 +0000 (12:47 +0100)
doc/doc-docbook/spec.xfpt
doc/doc-txt/NewStuff
src/src/exim_dbutil.c

index e766b69e2d1e193a87f4d1b0bcc09c43e7210098..3691b8ba6d2061e0af49e310f106ca23322150c5 100644 (file)
@@ -39936,8 +39936,13 @@ in a transport)
 .section "exim_dumpdb" "SECTdumpdb"
 .cindex "&'exim_dumpdb'&"
 The entire contents of a database are written to the standard output by the
 .section "exim_dumpdb" "SECTdumpdb"
 .cindex "&'exim_dumpdb'&"
 The entire contents of a database are written to the standard output by the
-&'exim_dumpdb'& program, which has no options or arguments other than the
-spool and database names. For example, to dump the retry database:
+&'exim_dumpdb'& program,
+.new
+taking as arguments the spool and database names.
+An option &'-z'& may be given to regest times in UTC;
+otherwise times are in the local timezone.
+.wen
+For example, to dump the retry database:
 .code
 exim_dumpdb /var/spool/exim retry
 .endd
 .code
 exim_dumpdb /var/spool/exim retry
 .endd
@@ -40023,7 +40028,7 @@ databases is likely to keep on increasing.
 .cindex "&'exim_fixdb'&"
 The &'exim_fixdb'& program is a utility for interactively modifying databases.
 Its main use is for testing Exim, but it might also be occasionally useful for
 .cindex "&'exim_fixdb'&"
 The &'exim_fixdb'& program is a utility for interactively modifying databases.
 Its main use is for testing Exim, but it might also be occasionally useful for
-getting round problems in a live system. It has no options, and its interface
+getting round problems in a live system. Its interface
 is somewhat crude. On entry, it prompts for input with a right angle-bracket. A
 key of a database record can then be entered, and the data for that record is
 displayed.
 is somewhat crude. On entry, it prompts for input with a right angle-bracket. A
 key of a database record can then be entered, and the data for that record is
 displayed.
@@ -40040,6 +40045,12 @@ resets the time of the next delivery attempt. Time values are given as a
 sequence of digit pairs for year, month, day, hour, and minute. Colons can be
 used as optional separators.
 
 sequence of digit pairs for year, month, day, hour, and minute. Colons can be
 used as optional separators.
 
+.new
+Both displayed and input times are in the local timezone by default.
+If an option &'-z'& is used on the command line, displayed times
+are in UTC.
+.wen
+
 
 
 
 
 
 
index 1d6190b294e512a516f05d3d1236c598d77fe9c8..99c6303243eee237a8720440a042fed9fcf98f40 100644 (file)
@@ -13,6 +13,8 @@ Version 4.96
 
  2. A variant of the "mask" expansion operator to give normalised IPv6.
 
 
  2. A variant of the "mask" expansion operator to give normalised IPv6.
 
+ 3. UTC output option for exim_dumpdb, exim_fixdb
+
 
 Version 4.95
 ------------
 
 Version 4.95
 ------------
index 45b778fc0aacc8039efa97b3ec22fcad392ff64f..697b87500ec846f938deee86adeec735092d4297 100644 (file)
@@ -17,13 +17,13 @@ maintaining Exim hints databases.
 In all cases, the first argument is the name of the spool directory. The second
 argument is the name of the database file. The available names are:
 
 In all cases, the first argument is the name of the spool directory. The second
 argument is the name of the database file. The available names are:
 
-  retry:      retry delivery information
-  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
+  callout:     callout verification cache
+  misc:                miscellaneous hints data
+  ratelimit:   record for ACL "ratelimit" condition
+  retry:       etry delivery information
+  seen:                imestamp records for ACL "seen" condition
+  tls:         TLS session resumption cache
+  wait-<t>:    message waiting information; <t> is a transport name
 
 There are a number of common subroutines, followed by three main programs,
 whose inclusion is controlled by -D on the compilation command. */
 
 There are a number of common subroutines, followed by three main programs,
 whose inclusion is controlled by -D on the compilation command. */
@@ -47,6 +47,8 @@ whose inclusion is controlled by -D on the compilation command. */
 
 uschar *spool_directory;
 
 
 uschar *spool_directory;
 
+BOOL utc = FALSE;
+
 
 /******************************************************************************/
       /* dummies needed by Solaris build */
 
 /******************************************************************************/
       /* dummies needed by Solaris build */
@@ -130,7 +132,7 @@ 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 | seen\n");
 {
 printf("Usage: exim_%s%s  <spool-directory> <database-name>\n", name, options);
 printf("  <database-name> = retry | misc | wait-<transport-name> | callout | ratelimit | tls | seen\n");
-exit(1);
+exit(EXIT_FAILURE);
 }
 
 
 }
 
 
@@ -145,21 +147,38 @@ second of them to be sure it is a known database name. */
 static int
 check_args(int argc, uschar **argv, uschar *name, uschar *options)
 {
 static int
 check_args(int argc, uschar **argv, uschar *name, uschar *options)
 {
-if (argc == 3)
+uschar * aname = argv[optind + 1];
+if (argc - optind == 2)
   {
   {
-  if (Ustrcmp(argv[2], "retry") == 0) return type_retry;
-  if (Ustrcmp(argv[2], "misc") == 0) return type_misc;
-  if (Ustrncmp(argv[2], "wait-", 5) == 0) return type_wait;
-  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;
+  if (Ustrcmp(aname, "retry") == 0)            return type_retry;
+  if (Ustrcmp(aname, "misc") == 0)             return type_misc;
+  if (Ustrncmp(aname, "wait-", 5) == 0)        return type_wait;
+  if (Ustrcmp(aname, "callout") == 0)          return type_callout;
+  if (Ustrcmp(aname, "ratelimit") == 0)        return type_ratelimit;
+  if (Ustrcmp(aname, "tls") == 0)              return type_tls;
+  if (Ustrcmp(aname, "seen") == 0)             return type_seen;
   }
 usage(name, options);
 return -1;              /* Never obeyed */
 }
 
 
   }
 usage(name, options);
 return -1;              /* Never obeyed */
 }
 
 
+static void
+options(int argc, uschar * argv[], uschar * name)
+{
+int opt;
+
+opterr = 0;
+while ((opt = getopt(argc, (char * const *)argv, "z")) != -1)
+  switch (opt)
+  {
+  case 'z':    utc = TRUE; break;
+  default:     usage(name, US" [-z]");
+  }
+}
+
+
+
 
 /*************************************************
 *         Handle attempts to write the log       *
 
 /*************************************************
 *         Handle attempts to write the log       *
@@ -200,7 +219,7 @@ static uschar time_buffer[sizeof("09-xxx-1999 hh:mm:ss  ")];
 uschar *
 print_time(time_t t)
 {
 uschar *
 print_time(time_t t)
 {
-struct tm *tmstr = localtime(&t);
+struct tm *tmstr = utc ? gmtime(&t) : localtime(&t);
 Ustrftime(time_buffer, sizeof(time_buffer), "%d-%b-%Y %H:%M:%S", tmstr);
 return time_buffer;
 }
 Ustrftime(time_buffer, sizeof(time_buffer), "%d-%b-%Y %H:%M:%S", tmstr);
 return time_buffer;
 }
@@ -214,8 +233,8 @@ return time_buffer;
 uschar *
 print_cache(int value)
 {
 uschar *
 print_cache(int value)
 {
-return (value == ccache_accept)? US"accept" :
-       (value == ccache_reject)? US"reject" :
+return value == ccache_accept ? US"accept" :
+       value == ccache_reject ? US"reject" :
        US"unknown";
 }
 
        US"unknown";
 }
 
@@ -563,12 +582,15 @@ uschar **argv = USS cargv;
 uschar keybuffer[1024];
 
 store_init();
 uschar keybuffer[1024];
 
 store_init();
+options(argc, argv, US"dumpdb");
 
 /* Check the arguments, and open the database */
 
 
 /* Check the arguments, and open the database */
 
-dbdata_type = check_args(argc, argv, US"dumpdb", US"");
-spool_directory = argv[1];
-if (!(dbm = dbfn_open(argv[2], O_RDONLY, &dbblock, FALSE, TRUE)))
+dbdata_type = check_args(argc, argv, US"dumpdb", US" [-z]");
+argc -= optind; argv += optind;
+spool_directory = argv[0];
+
+if (!(dbm = dbfn_open(argv[1], O_RDONLY, &dbblock, FALSE, TRUE)))
   exit(1);
 
 /* Scan the file, formatting the information for each entry. Note
   exit(1);
 
 /* Scan the file, formatting the information for each entry. Note
@@ -776,22 +798,29 @@ If the record name is omitted from (2) or (3), the previously used record name
 is re-used. */
 
 
 is re-used. */
 
 
-int main(int argc, char **cargv)
+int
+main(int argc, char **cargv)
 {
 int dbdata_type;
 uschar **argv = USS cargv;
 uschar buffer[256];
 uschar name[256];
 rmark reset_point;
 {
 int dbdata_type;
 uschar **argv = USS cargv;
 uschar buffer[256];
 uschar name[256];
 rmark reset_point;
+uschar * aname;
 
 store_init();
 
 store_init();
+options(argc, argv, US"fixdb");
 name[0] = 0;  /* No name set */
 
 /* Sort out the database type, verify what we are working on and then process
 user requests */
 
 name[0] = 0;  /* No name set */
 
 /* Sort out the database type, verify what we are working on and then process
 user requests */
 
-dbdata_type = check_args(argc, argv, US"fixdb", US"");
-printf("Modifying Exim hints database %s/db/%s\n", argv[1], argv[2]);
+dbdata_type = check_args(argc, argv, US"fixdb", US" [-z]");
+argc -= optind; argv += optind;
+spool_directory = argv[0];
+aname = argv[1];
+
+printf("Modifying Exim hints database %s/db/%s\n", spool_directory, aname);
 
 for(; (reset_point = store_mark()); store_reset(reset_point))
   {
 
 for(; (reset_point = store_mark()); store_reset(reset_point))
   {
@@ -838,9 +867,8 @@ for(; (reset_point = store_mark()); store_reset(reset_point))
   if (field[0] != 0)
     {
     int verify = 1;
   if (field[0] != 0)
     {
     int verify = 1;
-    spool_directory = argv[1];
 
 
-    if (!(dbm = dbfn_open(argv[2], O_RDWR, &dbblock, FALSE, TRUE)))
+    if (!(dbm = dbfn_open(aname, O_RDWR, &dbblock, FALSE, TRUE)))
       continue;
 
     if (Ustrcmp(field, "d") == 0)
       continue;
 
     if (Ustrcmp(field, "d") == 0)
@@ -1009,8 +1037,7 @@ for(; (reset_point = store_mark()); store_reset(reset_point))
 
   /* Handle a read request, or verify after an update. */
 
 
   /* Handle a read request, or verify after an update. */
 
-  spool_directory = argv[1];
-  if (!(dbm = dbfn_open(argv[2], O_RDONLY, &dbblock, FALSE, TRUE)))
+  if (!(dbm = dbfn_open(aname, O_RDONLY, &dbblock, FALSE, TRUE)))
     continue;
 
   if (!(record = dbfn_read_with_length(dbm, name, &oldlength)))
     continue;
 
   if (!(record = dbfn_read_with_length(dbm, name, &oldlength)))
@@ -1140,7 +1167,8 @@ typedef struct key_item {
 } key_item;
 
 
 } key_item;
 
 
-int main(int argc, char **cargv)
+int
+main(int argc, char **cargv)
 {
 struct stat statbuf;
 int maxkeep = 30 * 24 * 60 * 60;
 {
 struct stat statbuf;
 int maxkeep = 30 * 24 * 60 * 60;