X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/571b27158aa468eda77b1a20ed80bed1f342e15d..a85c067ba6c6940512cf57ec213277a370d87e70:/src/src/tod.c diff --git a/src/src/tod.c b/src/src/tod.c index dac8b27f3..ac4ed35b9 100644 --- a/src/src/tod.c +++ b/src/src/tod.c @@ -2,8 +2,10 @@ * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2014 */ +/* Copyright (c) University of Cambridge 1995 - 2018 */ +/* Copyright (c) The Exim Maintainers 2020 */ /* See the file NOTICE for conditions of use and distribution. */ +/* SPDX-License-Identifier: GPL-2.0-only */ /* A function for returning the time of day in various formats */ @@ -54,7 +56,6 @@ tod_stamp(int type) { struct timeval now; struct tm * t; -int off = 0; gettimeofday(&now, NULL); @@ -63,19 +64,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 +86,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,19 +111,22 @@ 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: - off = sprintf(CS timebuf, "%04d%02d", - 1900 + t->tm_year, 1 + t->tm_mon); +#ifndef COMPILE_UTILITY + snprintf(CS timebuf, sizeof(timebuf), "%04u%02u", + 1900 + (uint)t->tm_year, 1 + (uint)t->tm_mon); +#endif break; #endif @@ -137,21 +150,31 @@ switch(type) { int diff_hour, diff_min; struct tm local; - memcpy(&local, t, sizeof(struct tm)); + struct tm * lp = &local; + memcpy(lp, t, sizeof(struct tm)); - if (timestamps_utc) + 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); + if (local.tm_sec == gmt->tm_sec) /* usual case */ + { + 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); + } + else /* subminute offset, eg. TAI */ + { + lp = gmt; /* pretend we're in UTC */ + diff_min = diff_hour = 0; + } } switch(type) @@ -159,62 +182,58 @@ 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, now.tv_usec/1000, + (void) snprintf(CS timebuf, sizeof(timebuf), + "%04u-%02u-%02u %02u:%02u:%02u.%03u %+03d%02d", + 1900 + (uint)lp->tm_year, 1 + (uint)lp->tm_mon, (uint)lp->tm_mday, + (uint)lp->tm_hour, (uint)lp->tm_min, (uint)lp->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)lp->tm_year, 1 + (uint)lp->tm_mon, (uint)lp->tm_mday, + (uint)lp->tm_hour, (uint)lp->tm_min, (uint)lp->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 */ - #ifdef SUPPORT_MBX +#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); - } + { + int len = snprintf(CS timebuf, sizeof(timebuf), + "%02u-", (uint)lp->tm_mday); + len += Ustrftime(timebuf + len, sizeof(timebuf) - len, + "%b-%Y %H:%M:%S", lp); + (void) snprintf(CS timebuf + len, sizeof(timebuf)-len, + " %+03d%02d", diff_hour, diff_min); + } break; - #endif +#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); - } + { + int len = Ustrftime(timebuf, sizeof(timebuf), "%a, ", lp); + len += snprintf(CS timebuf + len, sizeof(timebuf)-len, + "%02u ", (uint)lp->tm_mday); + len += Ustrftime(timebuf + len, sizeof(timebuf) - len, + "%b %Y %H:%M:%S", lp); + (void) snprintf(CS timebuf + len, sizeof(timebuf)-len, + " %+03d%02d", diff_hour, diff_min); + } break; } } break; } -#ifndef COMPILE_UTILITY -if (LOGGING(millisec) && off > 0) - (void) sprintf(CS timebuf + off, ".%03d", now.tv_usec/1000); -#endif - return timebuf; }