X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/f57879265211e8eee3f8e231287c71b66167afee..d85cdeb5e554b59bf4c43c54461409c15c6ee9c5:/src/src/tod.c diff --git a/src/src/tod.c b/src/src/tod.c index 9aa845c82..9088fc604 100644 --- a/src/src/tod.c +++ b/src/src/tod.c @@ -2,7 +2,7 @@ * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2009 */ +/* 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 */ @@ -13,7 +13,7 @@ /* #define TESTING_LOG_DATESTAMP */ -static uschar timebuf[sizeof("www, dd-mmm-yyyy hh:mm:ss +zzzz")]; +static uschar timebuf[sizeof("www, dd-mmm-yyyy hh:mm:ss.ddd +zzzz")]; /************************************************* @@ -52,156 +52,173 @@ Returns: pointer to fixed buffer containing the timestamp uschar * tod_stamp(int type) { -time_t now; -struct tm *t; +struct timeval now; +struct tm * t; -if (type == tod_epoch_l) - { - struct timeval tv; - gettimeofday(&tv, NULL); - (void) sprintf(CS timebuf, "%ld%06ld", tv.tv_sec, tv.tv_usec ); /* Unix epoch/usec format */ - return timebuf; - } - -now = time(NULL); - -/* Vary log type according to timezone requirement */ - -if (type == tod_log) type = log_timezone? tod_log_zone : tod_log_bare; +gettimeofday(&now, NULL); /* Styles that don't need local time */ -else if (type == tod_epoch) +switch(type) { - (void) sprintf(CS timebuf, "%d", (int)now); /* Unix epoch format */ - return timebuf; + case tod_epoch: + (void) sprintf(CS 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 ); + return timebuf; + + case tod_zulu: + t = gmtime(&now.tv_sec); + (void) sprintf(CS 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; } -else if (type == tod_zulu) - { - t = gmtime(&now); - (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); - return timebuf; - } +/* Vary log type according to timezone requirement */ + +if (type == tod_log) type = log_timezone ? tod_log_zone : tod_log_bare; /* Convert to local time or UTC */ -t = timestamps_utc? gmtime(&now) : localtime(&now); +t = f.timestamps_utc ? gmtime(&now.tv_sec) : localtime(&now.tv_sec); switch(type) { case tod_log_bare: /* Format used in logging without timezone */ - (void) 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); - break; +#ifndef COMPILE_UTILITY + if (LOGGING(millisec)) + sprintf(CS 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 + sprintf(CS 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); - /* Format used as suffix of log file name when 'log_datestamp' is active. For - testing purposes, it changes the file every second. */ + break; - #ifdef TESTING_LOG_DATESTAMP + /* Format used as suffix of log file name when 'log_datestamp' is active. For + testing purposes, it changes the file every second. */ + +#ifdef TESTING_LOG_DATESTAMP case tod_log_datestamp_daily: case tod_log_datestamp_monthly: - (void) 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); - break; + sprintf(CS 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 +#else case tod_log_datestamp_daily: - (void) sprintf(CS timebuf, "%04d%02d%02d", - 1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday); - break; + sprintf(CS timebuf, "%04u%02u%02u", + 1900 + (uint)t->tm_year, 1 + (uint)t->tm_mon, (uint)t->tm_mday); + break; case tod_log_datestamp_monthly: - (void) sprintf(CS timebuf, "%04d%02d", - 1900 + t->tm_year, 1 + t->tm_mon); - break; - #endif - - /* Format used in BSD inbox separator lines. Sort-of documented in RFC 976 - ("UUCP Mail Interchange Format Standard") but only by example, not by - explicit definition. The examples show no timezone offsets, and some MUAs - appear to be sensitive to this, so Exim has been changed to remove the - timezone offsets that originally appeared. */ +#ifndef COMPILE_UTILITY + sprintf(CS timebuf, "%04u%02u", + 1900 + (uint)t->tm_year, 1 + (uint)t->tm_mon); +#endif + break; +#endif + + /* Format used in BSD inbox separator lines. Sort-of documented in RFC 976 + ("UUCP Mail Interchange Format Standard") but only by example, not by + explicit definition. The examples show no timezone offsets, and some MUAs + appear to be sensitive to this, so Exim has been changed to remove the + timezone offsets that originally appeared. */ case tod_bsdin: - { - int len = Ustrftime(timebuf, sizeof(timebuf), "%a %b %d %H:%M:%S", t); - Ustrftime(timebuf + len, sizeof(timebuf) - len, " %Y", t); - } - break; - - /* Other types require the GMT offset to be calculated, or just set up in the - case of UTC timestamping. We need to take a copy of the local time first. */ - - default: - { - int diff_hour, diff_min; - struct tm local; - memcpy(&local, t, sizeof(struct tm)); - - if (timestamps_utc) { - diff_hour = diff_min = 0; - } - else - { - struct tm *gmt = gmtime(&now); - diff_min = 60*(local.tm_hour - gmt->tm_hour) + local.tm_min - gmt->tm_min; - if (local.tm_year != gmt->tm_year) - diff_min += (local.tm_year > gmt->tm_year)? 1440 : -1440; - else if (local.tm_yday != gmt->tm_yday) - diff_min += (local.tm_yday > gmt->tm_yday)? 1440 : -1440; - diff_hour = diff_min/60; - diff_min = abs(diff_min - diff_hour*60); + int len = Ustrftime(timebuf, sizeof(timebuf), "%a %b %d %H:%M:%S", t); + Ustrftime(timebuf + len, sizeof(timebuf) - len, " %Y", t); } + break; - switch(type) + /* Other types require the GMT offset to be calculated, or just set up in the + case of UTC timestamping. We need to take a copy of the local time first. */ + + default: { - case tod_log_zone: /* Format used in logging with timezone */ - (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, - diff_hour, diff_min); - break; - - case tod_zone: /* Just the timezone offset */ - (void) sprintf(CS timebuf, "%+03d%02d", diff_hour, diff_min); - break; - - /* tod_mbx: format used in MBX mailboxes - subtly different to tod_full */ - - #ifdef SUPPORT_MBX - case tod_mbx: - { - int len; - (void) sprintf(CS timebuf, "%02d-", 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); - } - break; - #endif - - /* tod_full: format used in Received: headers (use as default just in case - called with a junk type value) */ - - default: - { - int len = Ustrftime(timebuf, sizeof(timebuf), "%a, ", &local); - (void) sprintf(CS timebuf + len, "%02d ", 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); - } - break; + int diff_hour, diff_min; + struct tm local; + memcpy(&local, t, sizeof(struct tm)); + + if (f.timestamps_utc) + diff_hour = diff_min = 0; + else + { + struct tm * gmt = gmtime(&now.tv_sec); + + diff_min = 60*(local.tm_hour - gmt->tm_hour) + local.tm_min - gmt->tm_min; + if (local.tm_year != gmt->tm_year) + diff_min += (local.tm_year > gmt->tm_year)? 1440 : -1440; + else if (local.tm_yday != gmt->tm_yday) + diff_min += (local.tm_yday > gmt->tm_yday)? 1440 : -1440; + diff_hour = diff_min/60; + diff_min = abs(diff_min - diff_hour*60); + } + + switch(type) + { + case tod_log_zone: /* Format used in logging with timezone */ +#ifndef COMPILE_UTILITY + if (LOGGING(millisec)) + (void) sprintf(CS 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, + "%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); + break; + + /* tod_mbx: format used in MBX mailboxes - subtly different to tod_full */ + + #ifdef SUPPORT_MBX + case tod_mbx: + { + int len; + (void) sprintf(CS 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); + } + break; + #endif + + /* tod_full: format used in Received: headers (use as default just in case + called with a junk type value) */ + + default: + { + int len = Ustrftime(timebuf, sizeof(timebuf), "%a, ", &local); + (void) sprintf(CS 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); + } + break; + } } - } - break; + break; } return timebuf;