summaryrefslogtreecommitdiff
path: root/src/memline.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/memline.c')
-rw-r--r--src/memline.c50
1 files changed, 43 insertions, 7 deletions
diff --git a/src/memline.c b/src/memline.c
index e7ae6dfb5..0e3bdb8b6 100644
--- a/src/memline.c
+++ b/src/memline.c
@@ -2082,6 +2082,48 @@ get_b0_dict(char_u *fname, dict_T *d)
#endif
/*
+ * Cache of the current timezone name as retrieved from TZ, or an empty string
+ * where unset, up to 64 octets long including trailing null byte.
+ */
+#if defined(HAVE_LOCALTIME_R) && defined(HAVE_TZSET)
+static char tz_cache[64];
+#endif
+
+/*
+ * Call either localtime(3) or localtime_r(3) from POSIX libc time.h, with the
+ * latter version preferred for reentrancy.
+ *
+ * If we use localtime_r(3) and we have tzset(3) available, check to see if the
+ * environment variable TZ has changed since the last run, and call tzset(3) to
+ * update the global timezone variables if it has. This is because the POSIX
+ * standard doesn't require localtime_r(3) implementations to do that as it
+ * does with localtime(3), and we don't want to call tzset(3) every time.
+ */
+ struct tm *
+vim_localtime(
+ const time_t *timep, // timestamp for local representation
+ struct tm *result) // pointer to caller return buffer
+{
+#ifdef HAVE_LOCALTIME_R
+# ifdef HAVE_TZSET
+ char *tz; // pointer for TZ environment var
+
+ tz = (char *)mch_getenv((char_u *)"TZ");
+ if (tz == NULL)
+ tz = "";
+ if (STRNCMP(tz_cache, tz, sizeof(tz_cache) - 1) != 0)
+ {
+ tzset();
+ vim_strncpy((char_u *)tz_cache, (char_u *)tz, sizeof(tz_cache) - 1);
+ }
+# endif // HAVE_TZSET
+ return localtime_r(timep, result);
+#else
+ return localtime(timep);
+#endif // HAVE_LOCALTIME_R
+}
+
+/*
* Replacement for ctime(), which is not safe to use.
* Requires strftime(), otherwise returns "(unknown)".
* If "thetime" is invalid returns "(invalid)". Never returns NULL.
@@ -2093,16 +2135,10 @@ get_ctime(time_t thetime, int add_newline)
{
static char buf[50];
#ifdef HAVE_STRFTIME
-# ifdef HAVE_LOCALTIME_R
struct tm tmval;
-# endif
struct tm *curtime;
-# ifdef HAVE_LOCALTIME_R
- curtime = localtime_r(&thetime, &tmval);
-# else
- curtime = localtime(&thetime);
-# endif
+ curtime = vim_localtime(&thetime, &tmval);
/* MSVC returns NULL for an invalid value of seconds. */
if (curtime == NULL)
vim_strncpy((char_u *)buf, (char_u *)_("(Invalid)"), sizeof(buf) - 1);