time functions: removed support for Solaris

diff --git a/skeletons/GeneralizedTime.c b/skeletons/GeneralizedTime.c
index 015fc6a..6236d2a 100644
--- a/skeletons/GeneralizedTime.c
+++ b/skeletons/GeneralizedTime.c
@@ -16,7 +16,7 @@
 #pragma message( "  ")
 #pragma message( "  You must fix the code by inserting appropriate locking")
 #pragma message( "  if you want to use asn_GT2time() or asn_UT2time().")
-#pragma message( "PLEASE STOP AND READ! ")
+#pragma message( "PLEASE STOP AND READ!")
 
 static struct tm *localtime_r(const time_t *tloc, struct tm *result) {
 	struct tm *tm;
@@ -38,7 +38,7 @@
 
 #endif	/* WIN32 */
 
-#if	defined(sun)
+#if	defined(sun) || defined(_sun_) || defined(__solaris__)
 #define	_EMULATE_TIMEGM
 #endif
 
@@ -62,6 +62,15 @@
 #define	GMTOFF(tm)	(-timezone)
 #endif	/* HAVE_TM_GMTOFF */
 
+#if	(defined(_EMULATE_TIMEGM) || !defined(HAVE_TM_GMTOFF))
+#warning "PLEASE STOP AND READ!"
+#warning "  timegm() is implemented via getenv(\"TZ\")/setenv(\"TZ\"), which may be not thread-safe."
+#warning "  "
+#warning "  You must fix the code by inserting appropriate locking"
+#warning "  if you want to use asn_GT2time() or asn_UT2time()."
+#warning "PLEASE STOP AND READ!"
+#endif	/* _EMULATE_TIMEGM */
+
 /*
  * Override our GMTOFF decision for other known platforms.
  */
@@ -84,25 +93,40 @@
 
 #endif	/* __CYGWIN__ */
 
+#define	ATZVARS do {							\
+	char tzoldbuf[64];						\
+	char *tzold
+#define	ATZSAVETZ do {							\
+	tzold = getenv("TZ");						\
+	if(tzold) {							\
+		size_t tzlen = strlen(tzold);				\
+		if(tzlen < sizeof(tzoldbuf))				\
+			tzold = memcpy(tzoldbuf, tzold, tzlen + 1);	\
+		else							\
+			tzold = strdup(tzold);	/* Ignore error */	\
+		setenv("TZ", "UTC", 1);					\
+	}								\
+	tzset();							\
+} while(0)
+#define	ATZOLDTZ do {							\
+	if (tzold) {							\
+		setenv("TZ", tzold, 1);					\
+		*tzoldbuf = 0;						\
+		if(tzold != tzoldbuf)					\
+			free(tzold);					\
+	} else {							\
+		unsetenv("TZ");						\
+	}								\
+	tzset();							\
+} while(0); } while(0);
+
 #ifdef	_EMULATE_TIMEGM
 static time_t timegm(struct tm *tm) {
 	time_t tloc;
-	char *tz;
-	char *buf;
-
-	tz = getenv("TZ");
-	putenv("TZ=UTC");
-	tzset();
+	ATZVARS;
+	ATZSAVETZ;
 	tloc = mktime(tm);
-	if (tz) {
-		int bufsize = strlen(tz) + 4;
-		buf = alloca(bufsize);
-		snprintf(buf, bufsize, "TZ=%s", tz);
-	} else {
-		buf = "TZ=";
-	}
-	putenv(buf);
-	tzset();
+	ATZOLDTZ;
 	return tloc;
 }
 #endif	/* _EMULATE_TIMEGM */
@@ -567,8 +591,8 @@
 		tm = &tm_s;
 #ifdef	HAVE_TM_GMTOFF
 		assert(!GMTOFF(tm_s));	/* Will fix itself */
-#else
-		gmtoff = 0;		/* Intervention required */
+#else	/* !HAVE_TM_GMTOFF */
+		gmtoff = 0;
 #endif
 	}
 
diff --git a/skeletons/tests/check-GeneralizedTime.c b/skeletons/tests/check-GeneralizedTime.c
index 9eabb69..b56fa0b 100644
--- a/skeletons/tests/check-GeneralizedTime.c
+++ b/skeletons/tests/check-GeneralizedTime.c
@@ -59,13 +59,15 @@
 	}
 }
 
+#define	RECODE(foo, bar)	recode(__LINE__, foo, bar)
 
 static void
-recode(char *time_str, const char *expect) {
+recode(int lineno, char *time_str, const char *expect) {
 	int frac_value, frac_digits;
 	GeneralizedTime_t gt;
 	struct tm tm;
 	time_t tloc;
+	char *tz;
 
 	gt.buf = (uint8_t *)time_str;
 	gt.size = strlen(time_str);
@@ -77,8 +79,11 @@
 	asn_time2GT_frac(&gt, &tm, frac_value, frac_digits, 1);
 	assert(gt.buf);
 
-	printf("[%s] => [%s] == [%s] (%d, %d)\n",
-		time_str, gt.buf, expect, frac_value, frac_digits);
+	tz = getenv("TZ");
+	printf("%d: [%s] (%ld) => [%s] == [%s] (%d, %d) (TZ=%s)\n",
+		lineno, time_str, (long)tloc, gt.buf,
+		expect, frac_value, frac_digits,
+		tz ? tz : "");
 
 	assert(strcmp((char *)gt.buf, expect) == 0);
 	FREEMEM(gt.buf);
@@ -182,9 +187,12 @@
 
 int
 main(int ac, char **av) {
+	char *tz = getenv("TZ");
 
 	(void)av;
 
+	printf("TZ = [%s]\n", tz ? tz : "");
+
 	check_fractions();
 
 	recognize("200401250", -1, 0);
@@ -222,32 +230,36 @@
 		recognize("20040125093000,1234", 1075051800, 0);
 
 		encode(1075023007, "20040125013007-0800", 0);
-		recode("20050702123312", "20050702193312Z");
+		RECODE("20050702123312", "20050702193312Z");
 	}
 
-	recode("20050702123312Z", "20050702123312Z");
-	recode("20050702123312+01", "20050702113312Z");
-	recode("20050702123312,0+01", "20050702113312Z");
-	recode("20050702123312,1+01", "20050702113312.1Z");
-	recode("20050702123312.01+01", "20050702113312.01Z");
-	recode("20050702123312.00+01", "20050702113312Z");
-	recode("20050702123312.30+01", "20050702113312.3Z");
-	recode("20050702123312,30000+01", "20050702113312.3Z");
-	recode("20050702123312,300000000+01", "20050702113312.3Z");
-	recode("20050702123312.123456+01", "20050702113312.123456Z");
-	recode("20050702123312.1234567+01", "20050702113312.123456Z");
-	recode("20050702123312.12345678+01", "20050702113312.123456Z");
-	recode("20050702123312.123456789+01", "20050702113312.123456Z");
-	recode("20050702123312.2000000000+01", "20050702113312.2Z");
-	recode("20050702123312.3000000000+01", "20050702113312.3Z");
-	recode("20050702123312.4000000000+01", "20050702113312.4Z");
-	recode("20050702123312.5000000000+01", "20050702113312.5Z");
-	recode("20050702123312.5000000001+01", "20050702113312.5Z");
-	recode("20050702123312.5000010001+01", "20050702113312.500001Z");
-	recode("20050702123312.5000001001+01", "20050702113312.5Z");
-	recode("20050702123312.000001+01", "20050702113312.000001Z");
-	recode("20050702123312.0000001Z", "20050702123312Z");
-	recode("20050702123312.0080010+1056", "20050702013712.008001Z");
+#if defined(sun) || defined(__sun) || defined(_sun_) || defined(__solaris__)
+	printf("Solaris does not have a decent timegm() function.\n");
+#else	/* !solaris */
+	RECODE("20050702123312Z", "20050702123312Z");
+	RECODE("20050702123312+01", "20050702113312Z");
+	RECODE("20050702123312,0+01", "20050702113312Z");
+	RECODE("20050702123312,1+01", "20050702113312.1Z");
+	RECODE("20050702123312.01+01", "20050702113312.01Z");
+	RECODE("20050702123312.00+01", "20050702113312Z");
+	RECODE("20050702123312.30+01", "20050702113312.3Z");
+	RECODE("20050702123312,30000+01", "20050702113312.3Z");
+	RECODE("20050702123312,300000000+01", "20050702113312.3Z");
+	RECODE("20050702123312.123456+01", "20050702113312.123456Z");
+	RECODE("20050702123312.1234567+01", "20050702113312.123456Z");
+	RECODE("20050702123312.12345678+01", "20050702113312.123456Z");
+	RECODE("20050702123312.123456789+01", "20050702113312.123456Z");
+	RECODE("20050702123312.2000000000+01", "20050702113312.2Z");
+	RECODE("20050702123312.3000000000+01", "20050702113312.3Z");
+	RECODE("20050702123312.4000000000+01", "20050702113312.4Z");
+	RECODE("20050702123312.5000000000+01", "20050702113312.5Z");
+	RECODE("20050702123312.5000000001+01", "20050702113312.5Z");
+	RECODE("20050702123312.5000010001+01", "20050702113312.500001Z");
+	RECODE("20050702123312.5000001001+01", "20050702113312.5Z");
+	RECODE("20050702123312.000001+01", "20050702113312.000001Z");
+	RECODE("20050702123312.0000001Z", "20050702123312Z");
+	RECODE("20050702123312.0080010+1056", "20050702013712.008001Z");
+#endif
 
 	return 0;
 }