patches to zdump.c and date.c for Posix-compliant tzset behavior

date.c and zdump.c currently use the trick of temporarily setting `environ' to modify "TZ", then calling tzset(), then restoring `environ', then calling `localtime' to get the effect of the temporarily modified "TZ". But this trick doesn't work if `ctime', `localtime', `mktime', and `strftime' inspect "TZ" every time they are invoked, as required by Posix 1003.1b-1993 section 8.1.1 page 192 lines 54-56. The following patch fixes date.c and zdump.c to set `environ' permanently; this should work regardless of whether tzset has the Posix-required behavior or the old tz behavior. (I've already sent a patch to fix the old tz behavior -- I can resend this to whoever's interested.) =================================================================== RCS file: RCS/date.c,v retrieving revision 1994.6.1.2 retrieving revision 1994.6.1.3 diff -c -r1994.6.1.2 -r1994.6.1.3 *** date.c 1994/05/09 09:47:28 1994.6.1.2 --- date.c 1994/12/06 17:13:55 1994.6.1.3 *************** *** 299,312 **** static void dogmt() { ! register char ** saveenv; ! static char TZ_GMT0[] = "TZ=GMT0"; ! static char * fakeenv[] = { TZ_GMT0, NULL }; ! saveenv = environ; ! environ = fakeenv; ! tzset(); ! environ = saveenv; } #ifdef OLD_TIME --- 299,320 ---- static void dogmt() { ! static char **fakeenv; ! if (!fakeenv) { ! register int i, j; ! for (i = 0; environ[i]; i++) ! continue; ! if (!(fakeenv = (char **) malloc((i + 2) * sizeof(char *)))) { ! (void) perror("Memory exhausted"); ! errensure(); ! (void) exit(retval); ! } ! fakeenv[0] = "TZ=GMT0"; ! for (i = 0, j = 1; (fakeenv[j] = environ[i]) != 0; i++) ! j += strncmp(fakeenv[j], "TZ=", 3) != 0; ! environ = fakeenv; ! } } #ifdef OLD_TIME =================================================================== RCS file: RCS/zdump.c,v retrieving revision 1994.6.1.1 retrieving revision 1994.6.1.2 diff -c -r1994.6.1.1 -r1994.6.1.2 *** zdump.c 1994/05/05 16:24:49 1994.6.1.1 --- zdump.c 1994/12/06 17:13:55 1994.6.1.2 *************** *** 41,47 **** /* localtime.c */ extern char * tzname[]; - extern void tzset P((void)); #ifndef MAX_STRING_LENGTH #define MAX_STRING_LENGTH 1024 --- 41,46 ---- *************** *** 116,121 **** --- 115,121 ---- register char * cutoff; register int cutyear; register long cuttime; + char ** fakeenv; time_t now; time_t t, newt; time_t hibit; *************** *** 154,178 **** longest = strlen(argv[i]); for (hibit = 1; (hibit << 1) != 0; hibit <<= 1) continue; for (i = optind; i < argc; ++i) { - register char ** saveenv; static char buf[MAX_STRING_LENGTH]; - char * fakeenv[2]; ! if (strlen(argv[i]) + 4 > sizeof buf) { ! (void) fflush(stdout); ! (void) fprintf(stderr, "%s: argument too long -- %s\n", ! progname, argv[i]); ! (void) exit(EXIT_FAILURE); ! } ! (void) strcpy(buf, "TZ="); ! (void) strcat(buf, argv[i]); ! fakeenv[0] = buf; ! fakeenv[1] = NULL; ! saveenv = environ; ! environ = fakeenv; ! (void) tzset(); ! environ = saveenv; show(argv[i], now, FALSE); if (!vflag) continue; --- 154,176 ---- longest = strlen(argv[i]); for (hibit = 1; (hibit << 1) != 0; hibit <<= 1) continue; + + for (i = 0; environ[i]; i++) + continue; + if (!(fakeenv = (char **) malloc((i + 2) * sizeof(char *))) + || !(fakeenv[0] = malloc(longest + 4))) { + (void) perror(progname); + (void) exit(EXIT_FAILURE); + } + (void) strcpy(fakeenv[0], "TZ="); + for (i = 0, c = 1; (fakeenv[c] = environ[i]) != 0; i++) + c += strncmp(fakeenv[c], "TZ=", 3) != 0; + environ = fakeenv; + for (i = optind; i < argc; ++i) { static char buf[MAX_STRING_LENGTH]; ! (void) strcpy(fakeenv[0] + 3, argv[i]); show(argv[i], now, FALSE); if (!vflag) continue;
participants (1)
-
eggert@twinsun.com