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

Paul Eggert eggert at twinsun.com
Tue Dec 6 17:49:50 UTC 1994


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;



More information about the tz mailing list