Use a monotonic clock, if available, for ID generation
[exim.git] / src / src / tod.c
index 76b6d2da993bc94268482bc13c0c863011e9e4ef..e7123f9eb90d89a22ec07fee07b01dc1f1079045 100644 (file)
@@ -2,7 +2,7 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2014 */
+/* Copyright (c) University of Cambridge 1995 - 2018 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* A function for returning the time of day in various formats */
@@ -54,7 +54,6 @@ tod_stamp(int type)
 {
 struct timeval now;
 struct tm * t;
-int off = 0;
 
 gettimeofday(&now, NULL);
 
@@ -63,19 +62,19 @@ gettimeofday(&now, NULL);
 switch(type)
   {
   case tod_epoch:
-    (void) sprintf(CS timebuf, TIME_T_FMT, now.tv_sec);  /* Unix epoch format */
+    (void) snprintf(CS timebuf, sizeof(timebuf), TIME_T_FMT, now.tv_sec);  /* Unix epoch format */
     return timebuf;    /* NB the above will be wrong if time_t is FP */
 
   case tod_epoch_l:
     /* Unix epoch/usec format */
-    (void) sprintf(CS timebuf, TIME_T_FMT "%06ld", now.tv_sec, (long) now.tv_usec );
+    (void) snprintf(CS timebuf, sizeof(timebuf), TIME_T_FMT "%06ld", now.tv_sec, (long) now.tv_usec );
     return timebuf;
 
   case tod_zulu:
     t = gmtime(&now.tv_sec);
-    (void) sprintf(CS timebuf, "%04d%02d%02d%02d%02d%02dZ",
-      1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min,
-      t->tm_sec);
+    (void) snprintf(CS timebuf, sizeof(timebuf), "%04u%02u%02u%02u%02u%02uZ",
+      1900 + (uint)t->tm_year, 1 + (uint)t->tm_mon, (uint)t->tm_mday, (uint)t->tm_hour, (uint)t->tm_min,
+      (uint)t->tm_sec);
     return timebuf;
   }
 
@@ -85,14 +84,23 @@ if (type == tod_log) type = log_timezone ? tod_log_zone : tod_log_bare;
 
 /* Convert to local time or UTC */
 
-t = timestamps_utc ? gmtime(&now.tv_sec) : localtime(&now.tv_sec);
+t = f.timestamps_utc ? gmtime(&now.tv_sec) : localtime(&now.tv_sec);
 
 switch(type)
   {
   case tod_log_bare:          /* Format used in logging without timezone */
-    off = sprintf(CS timebuf, "%04d-%02d-%02d %02d:%02d:%02d",
-      1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday,
-      t->tm_hour, t->tm_min, t->tm_sec);
+#ifndef COMPILE_UTILITY
+    if (LOGGING(millisec))
+      snprintf(CS timebuf, sizeof(timebuf), "%04u-%02u-%02u %02u:%02u:%02u.%03u",
+       1900 + (uint)t->tm_year, 1 + (uint)t->tm_mon, (uint)t->tm_mday,
+       (uint)t->tm_hour, (uint)t->tm_min, (uint)t->tm_sec,
+       (uint)(now.tv_usec/1000));
+    else
+#endif
+      snprintf(CS timebuf, sizeof(timebuf), "%04u-%02u-%02u %02u:%02u:%02u",
+       1900 + (uint)t->tm_year, 1 + (uint)t->tm_mon, (uint)t->tm_mday,
+       (uint)t->tm_hour, (uint)t->tm_min, (uint)t->tm_sec);
+
     break;
 
     /* Format used as suffix of log file name when 'log_datestamp' is active. For
@@ -101,20 +109,21 @@ switch(type)
 #ifdef TESTING_LOG_DATESTAMP
   case tod_log_datestamp_daily:
   case tod_log_datestamp_monthly:
-    off = sprintf(CS timebuf, "%04d%02d%02d%02d%02d",
-      1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min);
+    snprintf(CS timebuf, sizeof(timebuf), "%04u%02u%02u%02u%02u",
+      1900 + (uint)t->tm_year, 1 + (uint)t->tm_mon, (uint)t->tm_mday,
+      (uint)t->tm_hour, (uint)t->tm_min);
     break;
 
 #else
   case tod_log_datestamp_daily:
-    off = sprintf(CS timebuf, "%04d%02d%02d",
-      1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday);
+    snprintf(CS timebuf, sizeof(timebuf), "%04u%02u%02u",
+      1900 + (uint)t->tm_year, 1 + (uint)t->tm_mon, (uint)t->tm_mday);
     break;
 
   case tod_log_datestamp_monthly:
 #ifndef COMPILE_UTILITY
-    off = sprintf(CS timebuf, "%04d%02d",
-      1900 + t->tm_year, 1 + t->tm_mon);
+    snprintf(CS timebuf, sizeof(timebuf), "%04u%02u",
+      1900 + (uint)t->tm_year, 1 + (uint)t->tm_mon);
 #endif
     break;
 #endif
@@ -141,7 +150,7 @@ switch(type)
       struct tm local;
       memcpy(&local, t, sizeof(struct tm));
 
-      if (timestamps_utc)
+      if (f.timestamps_utc)
        diff_hour = diff_min = 0;
       else
        {
@@ -161,22 +170,22 @@ switch(type)
        case tod_log_zone:          /* Format used in logging with timezone */
 #ifndef COMPILE_UTILITY
          if (LOGGING(millisec))
-           (void) sprintf(CS timebuf,
-             "%04d-%02d-%02d %02d:%02d:%02d.%03d %+03d%02d",
-             1900 + local.tm_year, 1 + local.tm_mon, local.tm_mday,
-             local.tm_hour, local.tm_min, local.tm_sec, (int)(now.tv_usec/1000),
+           (void) snprintf(CS timebuf, sizeof(timebuf),
+             "%04u-%02u-%02u %02u:%02u:%02u.%03u %+03d%02d",
+             1900 + (uint)local.tm_year, 1 + (uint)local.tm_mon, (uint)local.tm_mday,
+             (uint)local.tm_hour, (uint)local.tm_min, (uint)local.tm_sec, (uint)(now.tv_usec/1000),
              diff_hour, diff_min);
          else
 #endif
-           (void) sprintf(CS timebuf,
-             "%04d-%02d-%02d %02d:%02d:%02d %+03d%02d",
-             1900 + local.tm_year, 1 + local.tm_mon, local.tm_mday,
-             local.tm_hour, local.tm_min, local.tm_sec,
+           (void) snprintf(CS timebuf, sizeof(timebuf),
+             "%04u-%02u-%02u %02u:%02u:%02u %+03d%02d",
+             1900 + (uint)local.tm_year, 1 + (uint)local.tm_mon, (uint)local.tm_mday,
+             (uint)local.tm_hour, (uint)local.tm_min, (uint)local.tm_sec,
              diff_hour, diff_min);
          break;
 
        case tod_zone:              /* Just the timezone offset */
-         (void) sprintf(CS timebuf, "%+03d%02d", diff_hour, diff_min);
+         (void) snprintf(CS timebuf, sizeof(timebuf), "%+03d%02d", diff_hour, diff_min);
          break;
 
        /* tod_mbx: format used in MBX mailboxes - subtly different to tod_full */
@@ -185,11 +194,11 @@ switch(type)
        case tod_mbx:
            {
            int len;
-           (void) sprintf(CS timebuf, "%02d-", local.tm_mday);
+           (void) snprintf(CS timebuf, sizeof(timebuf), "%02u-", (uint)local.tm_mday);
            len = Ustrlen(timebuf);
            len += Ustrftime(timebuf + len, sizeof(timebuf) - len, "%b-%Y %H:%M:%S",
              &local);
-           (void) sprintf(CS timebuf + len, " %+03d%02d", diff_hour, diff_min);
+           (void) snprintf(CS timebuf + len, sizeof(timebuf)-len, " %+03d%02d", diff_hour, diff_min);
            }
          break;
          #endif
@@ -200,11 +209,11 @@ switch(type)
        default:
            {
            int len = Ustrftime(timebuf, sizeof(timebuf), "%a, ", &local);
-           (void) sprintf(CS timebuf + len, "%02d ", local.tm_mday);
+           (void) snprintf(CS timebuf + len, sizeof(timebuf)-len, "%02u ", (uint)local.tm_mday);
            len += Ustrlen(timebuf + len);
            len += Ustrftime(timebuf + len, sizeof(timebuf) - len, "%b %Y %H:%M:%S",
              &local);
-           (void) sprintf(CS timebuf + len, " %+03d%02d", diff_hour, diff_min);
+           (void) snprintf(CS timebuf + len, sizeof(timebuf)-len, " %+03d%02d", diff_hour, diff_min);
            }
          break;
        }
@@ -212,13 +221,6 @@ switch(type)
     break;
   }
 
-#ifndef COMPILE_UTILITY
-if (LOGGING(millisec) && off > 0)
-  (void) sprintf(CS timebuf + off, ".%03d", (int)(now.tv_usec/1000));
-#else
-off = off;     /* Compiler quietening */
-#endif
-
 return timebuf;
 }