* lib/ctime.c: Include <wchar.h>.
(rpl_ctime): Modify _environ and _wenviron without using _putenv.
* lib/localtime.c: Include <wchar.h>.
(rpl_localtime): Modify _environ and _wenviron without using _putenv.
* lib/tzset.c: Include <wchar.h>.
(rpl_tzset): Modify _environ and _wenviron without using _putenv.
* lib/wcsftime.c (rpl_wcsftime): Likewise.
+2024-02-09 Bruno Haible <bruno@clisp.org>
+
+ ctime, localtime, tzset, wcsftime: Make multithread-safe.
+ * lib/ctime.c: Include <wchar.h>.
+ (rpl_ctime): Modify _environ and _wenviron without using _putenv.
+ * lib/localtime.c: Include <wchar.h>.
+ (rpl_localtime): Modify _environ and _wenviron without using _putenv.
+ * lib/tzset.c: Include <wchar.h>.
+ (rpl_tzset): Modify _environ and _wenviron without using _putenv.
+ * lib/wcsftime.c (rpl_wcsftime): Likewise.
+
2024-02-09 Bruno Haible <bruno@clisp.org>
strftime: Remove module, deprecated in 2017.
#include <stdlib.h>
#include <string.h>
+#if defined _WIN32 && ! defined __CYGWIN__
+# include <wchar.h>
+#endif
#undef ctime
responsibility. */
const char *tz = getenv ("TZ");
if (tz != NULL && strchr (tz, '/') != NULL)
- _putenv ("TZ=");
+ {
+ /* Neutralize it, in a way that is multithread-safe.
+ (If we were to use _putenv ("TZ="), it would free the memory allocated
+ for the environment variable "TZ", and thus other threads that are
+ using the previously fetched value of getenv ("TZ") could crash.) */
+ char **env = _environ;
+ wchar_t **wenv = _wenviron;
+ if (env != NULL)
+ for (char *s = env; *s != NULL; s++)
+ if (s[0] == 'T' && s[1] == 'Z' && s[2] == '=')
+ s[0] = '$';
+ if (wenv != NULL)
+ for (wchar_t *ws = wenv; *ws != NULL; ws++)
+ if (ws[0] == L'T' && ws[1] == L'Z' && ws[2] == L'=')
+ ws[0] = L'$';
+ }
#endif
return ctime (tp);
#include <stdlib.h>
#include <string.h>
+#if defined _WIN32 && ! defined __CYGWIN__
+# include <wchar.h>
+#endif
#undef localtime
responsibility. */
const char *tz = getenv ("TZ");
if (tz != NULL && strchr (tz, '/') != NULL)
- _putenv ("TZ=");
+ {
+ /* Neutralize it, in a way that is multithread-safe.
+ (If we were to use _putenv ("TZ="), it would free the memory allocated
+ for the environment variable "TZ", and thus other threads that are
+ using the previously fetched value of getenv ("TZ") could crash.) */
+ char **env = _environ;
+ wchar_t **wenv = _wenviron;
+ if (env != NULL)
+ for (char *s = env; *s != NULL; s++)
+ if (s[0] == 'T' && s[1] == 'Z' && s[2] == '=')
+ s[0] = '$';
+ if (wenv != NULL)
+ for (wchar_t *ws = wenv; *ws != NULL; ws++)
+ if (ws[0] == L'T' && ws[1] == L'Z' && ws[2] == L'=')
+ ws[0] = L'$';
+ }
#endif
return localtime (tp);
#include <stdlib.h>
#include <string.h>
+#if defined _WIN32 && ! defined __CYGWIN__
+# include <wchar.h>
+#endif
void
rpl_tzset (void)
responsibility. */
const char *tz = getenv ("TZ");
if (tz != NULL && strchr (tz, '/') != NULL)
- _putenv ("TZ=");
+ {
+ /* Neutralize it, in a way that is multithread-safe.
+ (If we were to use _putenv ("TZ="), it would free the memory allocated
+ for the environment variable "TZ", and thus other threads that are
+ using the previously fetched value of getenv ("TZ") could crash.) */
+ char **env = _environ;
+ wchar_t **wenv = _wenviron;
+ if (env != NULL)
+ for (char *s = env; *s != NULL; s++)
+ if (s[0] == 'T' && s[1] == 'Z' && s[2] == '=')
+ s[0] = '$';
+ if (wenv != NULL)
+ for (wchar_t *ws = wenv; *ws != NULL; ws++)
+ if (ws[0] == L'T' && ws[1] == L'Z' && ws[2] == L'=')
+ ws[0] = L'$';
+ }
/* On native Windows, tzset() is deprecated. Use _tzset() instead. See
<https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/posix-tzset>
responsibility. */
const char *tz = getenv ("TZ");
if (tz != NULL && strchr (tz, '/') != NULL)
- _putenv ("TZ=");
+ {
+ /* Neutralize it, in a way that is multithread-safe.
+ (If we were to use _putenv ("TZ="), it would free the memory allocated
+ for the environment variable "TZ", and thus other threads that are
+ using the previously fetched value of getenv ("TZ") could crash.) */
+ char **env = _environ;
+ wchar_t **wenv = _wenviron;
+ if (env != NULL)
+ for (char *s = env; *s != NULL; s++)
+ if (s[0] == 'T' && s[1] == 'Z' && s[2] == '=')
+ s[0] = '$';
+ if (wenv != NULL)
+ for (wchar_t *ws = wenv; *ws != NULL; ws++)
+ if (ws[0] == L'T' && ws[1] == L'Z' && ws[2] == L'=')
+ ws[0] = L'$';
+ }
#endif
return wcsftime (buf, bufsize, format, tp);