| 218 | # define tzfree zdump_tzfree |
| 219 | |
| 220 | static timezone_t |
| 221 | tzalloc(char const *val) |
| 222 | { |
| 223 | # if HAVE_SETENV |
| 224 | if (setenv("TZ", val, 1) != 0) { |
| 225 | char const *e = strerror(errno); |
| 226 | fprintf(stderr, _("%s: setenv: %s\n"), progname, e); |
| 227 | exit(EXIT_FAILURE); |
| 228 | } |
| 229 | tzset(); |
| 230 | return &optarg; /* Any valid non-null char ** will do. */ |
| 231 | # else |
| 232 | enum { TZeqlen = 3 }; |
| 233 | static char const TZeq[TZeqlen] = "TZ="; |
| 234 | static char **fakeenv; |
| 235 | static ptrdiff_t fakeenv0size; |
| 236 | void *freeable = NULL; |
| 237 | char **env = fakeenv, **initial_environ; |
| 238 | ptrdiff_t valsize = strlen(val) + 1; |
| 239 | if (fakeenv0size < valsize) { |
| 240 | char **e = environ, **to; |
| 241 | ptrdiff_t initial_nenvptrs = 1; /* Counting the trailing NULL pointer. */ |
| 242 | |
| 243 | while (*e++) { |
| 244 | # ifdef ckd_add |
| 245 | if (ckd_add(&initial_nenvptrs, initial_nenvptrs, 1) |
| 246 | || INDEX_MAX < initial_nenvptrs) |
| 247 | size_overflow(); |
| 248 | # else |
| 249 | if (initial_nenvptrs == INDEX_MAX / sizeof *environ) |
| 250 | size_overflow(); |
| 251 | initial_nenvptrs++; |
| 252 | # endif |
| 253 | } |
| 254 | fakeenv0size = sumsize(valsize, valsize); |
| 255 | fakeenv0size = max(fakeenv0size, 64); |
| 256 | freeable = env; |
| 257 | fakeenv = env = |
| 258 | xmalloc(sumsize(sumsize(sizeof *environ, |
| 259 | initial_nenvptrs * sizeof *environ), |
| 260 | sumsize(TZeqlen, fakeenv0size))); |
| 261 | to = env + 1; |
| 262 | for (e = environ; (*to = *e); e++) |
| 263 | to += strncmp(*e, TZeq, TZeqlen) != 0; |
| 264 | env[0] = memcpy(to + 1, TZeq, TZeqlen); |
| 265 | } |
| 266 | memcpy(env[0] + TZeqlen, val, valsize); |
| 267 | initial_environ = environ; |
| 268 | environ = env; |
| 269 | tzset(); |
| 270 | free(freeable); |
| 271 | return initial_environ; |
| 272 | # endif |
| 273 | } |
| 274 | |
| 275 | static void |
| 276 | tzfree(ATTRIBUTE_MAYBE_UNUSED timezone_t initial_environ) |