diff --git a/configure.ac b/configure.ac index 211078983..8384aa040 100644 --- a/configure.ac +++ b/configure.ac @@ -304,6 +304,54 @@ AC_CHECK_FUNCS([sigsuspend], gl_WINSIZE_IN_PTEM +AC_MSG_CHECKING([whether localtime caches TZ]) +AC_CACHE_VAL([utils_cv_localtime_cache], +[if test x$ac_cv_func_tzset = xyes; then +AC_RUN_IFELSE([AC_LANG_SOURCE([[#include +#if STDC_HEADERS +# include +#endif +extern char **environ; +void unset_TZ (void) +{ + char **from, **to; + for (to = from = environ; (*to = *from); from++) + if (! (to[0][0] == 'T' && to[0][1] == 'Z' && to[0][2] == '=')) + to++; +} +int +main () +{ + time_t now = time ((time_t *) 0); + int hour_GMT0, hour_unset; + if (putenv ("TZ=GMT0") != 0) + return 1; + hour_GMT0 = localtime (&now)->tm_hour; + unset_TZ (); + hour_unset = localtime (&now)->tm_hour; + if (putenv ("TZ=PST8") != 0) + return 1; + if (localtime (&now)->tm_hour == hour_GMT0) + return 1; + unset_TZ (); + if (localtime (&now)->tm_hour != hour_unset) + return 1; + return 0; +}]])], +[utils_cv_localtime_cache=no], +[utils_cv_localtime_cache=yes], +[# If we have tzset, assume the worst when cross-compiling. +utils_cv_localtime_cache=yes]) +else + # If we lack tzset, report that localtime does not cache TZ, + # since we can't invalidate the cache if we don't have tzset. + utils_cv_localtime_cache=no +fi])dnl +AC_MSG_RESULT([$utils_cv_localtime_cache]) +if test $utils_cv_localtime_cache = yes; then + AC_DEFINE([LOCALTIME_CACHE], [1], [FIXME]) +fi + # Should 'sort' link libcrypto dynamically? AS_CASE([$LIB_CRYPTO], [-lcrypto], diff --git a/src/date.c b/src/date.c index 88ea1279a..ebd23fe16 100644 --- a/src/date.c +++ b/src/date.c @@ -107,6 +107,12 @@ static struct option const long_options[] = /* flags for parse_datetime2 */ static unsigned int parse_datetime_flags; +#if LOCALTIME_CACHE +# define TZSET tzset () +#else +# define TZSET /* empty */ +#endif + #ifdef _DATE_FMT # define DATE_FMT_LANGINFO() nl_langinfo (_DATE_FMT) #else @@ -570,7 +576,7 @@ main (int argc, char **argv) char *reference = NULL; bool discarded_datestr = false; bool discarded_set_datestr = false; - char const *tzstring = NULL; + bool utc = false; initialize_main (&argc, &argv); set_program_name (argv[0]); @@ -647,7 +653,7 @@ main (int argc, char **argv) set_date = true; break; case 'u': - tzstring = "UTC0"; + utc = true; break; case_GETOPT_HELP_CHAR; case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); @@ -656,6 +662,15 @@ main (int argc, char **argv) } } + if (utc) + { + /* POSIX says that 'date -u' is equivalent to setting the TZ + environment variable, so this option should do nothing other + than setting TZ. */ + xsetenv ("TZ", "UTC0", 1); + TZSET; + } + int option_specified_date = (!!datestr + !!batch_file + !!reference + get_resolution); @@ -726,8 +741,7 @@ main (int argc, char **argv) char *format_copy = adjust_resolution (format); char const *format_res = format_copy ? format_copy : format; - if (!tzstring) - tzstring = getenv ("TZ"); + char const *tzstring = getenv ("TZ"); timezone_t tz = tzalloc (tzstring); bool ok = true;