summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog23
-rw-r--r--PROJECTS24
-rw-r--r--inet/netinet/in.h6
-rw-r--r--stdlib/stdlib.h3
-rw-r--r--sysdeps/generic/putenv.c11
-rw-r--r--sysdeps/generic/setenv.c153
-rw-r--r--time/tzfile.c51
-rw-r--r--time/tzset.c12
-rw-r--r--timezone/Makefile2
-rw-r--r--timezone/asia11
-rw-r--r--timezone/australasia4
-rw-r--r--timezone/europe2
-rw-r--r--timezone/tst-timezone.c104
13 files changed, 324 insertions, 82 deletions
diff --git a/ChangeLog b/ChangeLog
index 0aee3ac595..0d22b9f6b3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+1998-05-14 13:25 Ulrich Drepper <drepper@cygnus.com>
+
+ * inet/netinet/in.h: Add defines for multicast.
+ Reported by Jeremy Hall <jhall@UU.NET>.
+
+ * stdlib/stdlib.h: Add prototypes for __setenv and __unsetenv.
+ * sysdeps/generic/putenv.c: Use __setenv and __unsetenv, not setenv
+ and unsetenv. Optimize _LIBC case.
+ * sysdeps/generic/setenv.c: Prevent unnecessary memory leaks.
+ Define functions with leading __.
+
+ * time/tzfile.c: Correct handling of global variables daylight,
+ timezone, and tzname.
+ * time/tzset.c: Likewise.
+ * timezone/Makefile (tests): Add tst-timezone.
+ * timezone/tst-timezone.c: New file.
+
+1998-05-14 10:35 Ulrich Drepper <drepper@cygnus.com>
+
+ * timezone/asia: Update from tzdata1998d.
+ * timezone/australasia: Likewise.
+ * timezone/europe: Likewise.
+
1998-05-13 Ulrich Drepper <drepper@cygnus.com>
* string/string.h: Don't use the optimized versions for the string
diff --git a/PROJECTS b/PROJECTS
index f1488d3e62..06242c70e0 100644
--- a/PROJECTS
+++ b/PROJECTS
@@ -1,6 +1,6 @@
Open jobs for finishing GNU libc:
---------------------------------
-Status: April 1998
+Status: May 1998
If you have time and talent to take over any of the jobs below please
contact <bug-glibc@gnu.org>.
@@ -112,3 +112,25 @@ contact <bug-glibc@gnu.org>.
correct form so it would be possible to enlarge it always according
to the page size and install the correct length only for fclose() and
fflush() calls.
+
+[17] The sprof program to analyze the profiling data generated by ld.so
+ must be finished. It should have the same functionality as gprof
+ (as far as this is possible).
+
+[18] Based on the sprof program we need tools to analyze the output. The
+ result should be a link map which specifies in which order the .o
+ files are placed in the shared object. This should help to improve
+ code locality and result in a smaller foorprint (in code and data
+ memory) since less pages are only used in small parts.
+
+[19] A user-level STREAMS implementation should be available if the
+ kernel does not provide the support.
+
+[20] More conversion modules for iconv(3). Existing modules should be
+ extended to do things like transliteration if this is wanted.
+ For often used conversion a direct conversion function should be
+ available.
+
+[21] The nscd program and the stubs in the libc should be changed so
+ that each program uses only one socket connect. Take a look at
+ http://www.cygnus.com/~drepper/nscd.html
diff --git a/inet/netinet/in.h b/inet/netinet/in.h
index c6985ffa0a..ddc09753e2 100644
--- a/inet/netinet/in.h
+++ b/inet/netinet/in.h
@@ -143,6 +143,12 @@ struct in_addr
# define INADDR_LOOPBACK ((uint32_t) 0x7f000001) /* Inet 127.0.0.1. */
#endif
+/* Defines for Multicast INADDR. */
+#define INADDR_UNSPEC_GROUP ((uint32_t) 0xe0000000) /* 224.0.0.0 */
+#define INADDR_ALLHOSTS_GROUP ((uint32_t) 0xe0000001) /* 224.0.0.1 */
+#define INADDR_ALLRTRS_GROUP ((uint32_t) 0xe0000002) /* 224.0.0.2 */
+#define INADDR_MAX_LOCAL_GROUP ((uint32_t) 0xe00000ff) /* 224.0.0.255 */
+
/* IPv6 address */
struct in6_addr
diff --git a/stdlib/stdlib.h b/stdlib/stdlib.h
index 757c252e87..b0703333d1 100644
--- a/stdlib/stdlib.h
+++ b/stdlib/stdlib.h
@@ -533,10 +533,13 @@ extern int putenv __P ((__const char *__string));
#ifdef __USE_BSD
/* Set NAME to VALUE in the environment.
If REPLACE is nonzero, overwrite an existing value. */
+extern int __setenv __P ((__const char *__name, __const char *__value,
+ int __replace));
extern int setenv __P ((__const char *__name, __const char *__value,
int __replace));
/* Remove the variable NAME from the environment. */
+extern void __unsetenv __P ((__const char *__name));
extern void unsetenv __P ((__const char *__name));
#endif
diff --git a/sysdeps/generic/putenv.c b/sysdeps/generic/putenv.c
index 296f2847cf..d059c2f78c 100644
--- a/sysdeps/generic/putenv.c
+++ b/sysdeps/generic/putenv.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 94, 95, 96, 97, 98 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -16,7 +16,7 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#if defined (_AIX) && !defined (__GNUC__)
+#if defined _AIX && !defined __GNUC__
#pragma alloca
#endif
@@ -45,6 +45,9 @@
extern char *alloca ();
# endif /* __GNUC__ */
# endif /* HAVE_ALLOCA_H */
+
+# define setenv __setenv
+# define unsetenv __unsetenv
#endif /* _LIBC */
@@ -57,10 +60,10 @@ putenv (string)
if (name_end != NULL)
{
- char *name = alloca (name_end - string + 1);
#ifdef _LIBC
- *((char *) __mempcpy (name, string, name_end - string)) = '\0';
+ char *name = strndupa (string, name_end - string);
#else
+ char *name = alloca (name_end - string + 1);
memcpy (name, string, name_end - string);
name[name_end - string] = '\0';
#endif
diff --git a/sysdeps/generic/setenv.c b/sysdeps/generic/setenv.c
index d4c5c87b15..69bd992832 100644
--- a/sysdeps/generic/setenv.c
+++ b/sysdeps/generic/setenv.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992, 1995, 1996, 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1992, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -22,7 +22,7 @@
#include <errno.h>
#if !_LIBC
-# if !defined(errno) && !defined(HAVE_ERRNO_DECL)
+# if !defined errno && !defined HAVE_ERRNO_DECL
extern int errno;
# endif
# define __set_errno(ev) ((errno) = (ev))
@@ -58,9 +58,34 @@ __libc_lock_define_initialized (static, envlock)
/* In the GNU C library we must keep the namespace clean. */
#ifdef _LIBC
+# define setenv __setenv
+# define unsetenv __unsetenv
# define clearenv __clearenv
#endif
+/* In the GNU C library implementation we try to be more clever and
+ allow arbitrary many changes of the environment given that the used
+ values are from a small set. Outside glibc this will eat up all
+ memory after a while. */
+#if defined _LIBC || (defined HAVE_SEARCH_H && defined HAVE_TSEARCH)
+# define USE_TSEARCH 1
+# include <search.h>
+
+/* This is a pointer to the root of the search tree with the known
+ values. */
+static void *known_values;
+
+# define KNOWN_VALUE(Str) tfind (Str, &known_values, (__compar_fn_t) strcmp)
+# define STORE_VALUE(Str) tsearch (Str, &known_values, (__compar_fn_t) strcmp)
+
+#else
+# undef USE_TSEARCH
+
+# define KNOWN_VALUE(Str) NULL
+# define STORE_VALUE(Str) do { } while (0)
+
+#endif
+
/* If this variable is not a null pointer we allocated the current
environment. */
@@ -91,45 +116,56 @@ setenv (name, value, replace)
if (__environ == NULL || *ep == NULL)
{
char **new_environ;
+#ifdef USE_TSEARCH
+ char *new_value;
+#endif
- if (__environ == last_environ && __environ != NULL)
- /* We allocated this space; we can extend it. */
- new_environ = (char **) realloc (last_environ,
- (size + 2) * sizeof (char *));
- else
- new_environ = (char **) malloc ((size + 2) * sizeof (char *));
-
+ /* We allocated this space; we can extend it. */
+ new_environ = (char **) realloc (last_environ,
+ (size + 2) * sizeof (char *));
if (new_environ == NULL)
{
UNLOCK;
return -1;
}
- new_environ[size] = malloc (namelen + 1 + vallen);
+ /* See whether the value is already known. */
+#ifdef USE_TSEARCH
+ new_value = alloca (namelen + 1 + vallen);
+# ifdef _LIBC
+ __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1),
+ value, vallen);
+# else
+ memcpy (new_value, name, namelen);
+ new_value[namelen] = '=';
+ memcpy (&new_value[namelen + 1], value, vallen);
+# endif
+
+ new_environ[size] = KNOWN_VALUE (new_value);
if (new_environ[size] == NULL)
+#endif
{
- free ((char *) new_environ);
- __set_errno (ENOMEM);
- UNLOCK;
- return -1;
+ new_environ[size] = malloc (namelen + 1 + vallen);
+ if (new_environ[size] == NULL)
+ {
+ __set_errno (ENOMEM);
+ UNLOCK;
+ return -1;
+ }
+
+#ifdef USE_TSEARCH
+ memcpy (new_environ[size], new_value, namelen + 1 + vallen);
+#else
+ memcpy (new_environ[size], name, namelen);
+ new_environ[size][namelen] = '=';
+ memcpy (&new_environ[size][namelen + 1], value, vallen);
+#endif
}
if (__environ != last_environ)
memcpy ((char *) new_environ, (char *) __environ,
size * sizeof (char *));
-#ifdef _LIBC
- {
- char *tmp = __mempcpy (new_environ[size], name, namelen);
- *tmp++ = '=';
- __mempcpy (tmp, value, vallen);
- }
-#else
- memcpy (new_environ[size], name, namelen);
- new_environ[size][namelen] = '=';
- memcpy (&new_environ[size][namelen + 1], value, vallen);
-#endif
-
new_environ[size + 1] = NULL;
last_environ = __environ = new_environ;
@@ -139,22 +175,48 @@ setenv (name, value, replace)
size_t len = strlen (*ep);
if (len + 1 < namelen + 1 + vallen)
{
+ char *new_value;
+ char *np;
+
/* The existing string is too short; malloc a new one. */
- char *new = malloc (namelen + 1 + vallen);
- if (new == NULL)
+#ifdef USE_TSEARCH
+ new_value = alloca (namelen + 1 + vallen);
+# ifdef _LIBC
+ __mempcpy (__mempcpy (__mempcpy (new_value, name, namelen), "=", 1),
+ value, vallen);
+# else
+ memcpy (new_value, name, namelen);
+ new_value[namelen] = '=';
+ memcpy (&new_value[namelen + 1], value, vallen);
+# endif
+
+ np = KNOWN_VALUE (new_value);
+ if (np == NULL)
+#endif
{
- UNLOCK;
- return -1;
- }
- *ep = new;
-#ifdef _LIBC
- *((char *) __mempcpy (*ep, name, namelen)) = '=';
+ np = malloc (namelen + 1 + vallen);
+ if (np == NULL)
+ {
+ UNLOCK;
+ return -1;
+ }
+
+#ifdef USE_TSEARCH
+ memcpy (np, new_value, namelen + 1 + vallen);
#else
- memcpy (*ep, name, namelen);
- (*ep)[namelen] = '=';
+ memcpy (np, name, namelen);
+ np[namelen] = '=';
+ memcpy (&np[namelen + 1], value, vallen);
#endif
+ }
+
+ /* Keep the old value around. */
+ STORE_VALUE (*ep);
+ *ep = np;
}
- memcpy (&(*ep)[namelen + 1], value, vallen);
+ else
+ /* Overwrite the value part of the old value. */
+ memcpy (&(*ep)[namelen + 1], value, vallen);
}
UNLOCK;
@@ -171,11 +233,15 @@ unsetenv (name)
LOCK;
- for (ep = __environ; *ep; ++ep)
+ for (ep = __environ; *ep != NULL; ++ep)
if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
{
/* Found it. Remove this pointer by moving later ones back. */
char **dp = ep;
+
+ /* Store the value so that we can reuse it later. */
+ STORE_VALUE (ep);
+
do
dp[0] = dp[1];
while (*dp++);
@@ -195,7 +261,12 @@ clearenv ()
if (__environ == last_environ && __environ != NULL)
{
- /* We allocated this environment so we can free it. */
+ /* We allocated this environment so we can free it. Store all the
+ strings. */
+ char **ep = __environ;
+ while (*ep != NULL)
+ STORE_VALUE (*ep++);
+
free (__environ);
last_environ = NULL;
}
@@ -208,6 +279,10 @@ clearenv ()
return 0;
}
#ifdef _LIBC
+# undef setenv
+# undef unsetenv
# undef clearenv
+weak_alias (__setenv, setenv)
+weak_alias (__unsetenv, unsetenv)
weak_alias (__clearenv, clearenv)
#endif
diff --git a/time/tzfile.c b/time/tzfile.c
index 7dcf88dbe9..c9becf3238 100644
--- a/time/tzfile.c
+++ b/time/tzfile.c
@@ -54,6 +54,8 @@ static unsigned char *type_idxs = NULL;
static size_t num_types;
static struct ttinfo *types = NULL;
static char *zone_names = NULL;
+static long int rule_stdoff;
+static long int rule_dstoff;
static size_t num_leaps;
static struct leap *leaps = NULL;
@@ -266,15 +268,32 @@ __tzfile_read (const char *file)
fclose (f);
- info = find_transition (0);
+ /* Find the standard and daylight time offsets used by the rule file.
+ We choose the offsets in the types of each flavor that are
+ transitioned to earliest in time. */
+ __tzname[1] = NULL;
for (i = 0; i < num_types && i < sizeof (__tzname) / sizeof (__tzname[0]);
++i)
__tzname[types[i].isdst] = __tzstring (&zone_names[types[i].idx]);
- if (info->isdst < sizeof (__tzname) / sizeof (__tzname[0]))
- __tzname[info->isdst] = __tzstring (&zone_names[info->idx]);
+ if (__tzname[1] == NULL)
+ __tzname[1] = __tzname[0];
compute_tzname_max (chars);
+ rule_stdoff = rule_dstoff = 0;
+ for (i = 0; i < num_transitions; ++i)
+ {
+ if (!rule_stdoff && !types[type_idxs[i]].isdst)
+ rule_stdoff = types[type_idxs[i]].offset;
+ if (!rule_dstoff && types[type_idxs[i]].isdst)
+ rule_dstoff = types[type_idxs[i]].offset;
+ if (rule_stdoff && rule_dstoff)
+ break;
+ }
+
+ __daylight = rule_stdoff != rule_dstoff;
+ __timezone = -rule_stdoff;
+
__use_tzfile = 1;
return;
@@ -291,7 +310,6 @@ __tzfile_default (const char *std, const char *dst,
long int stdoff, long int dstoff)
{
size_t stdlen, dstlen, i;
- long int rule_offset, rule_stdoff, rule_dstoff;
int isdst;
__tzfile_read (TZDEFRULES);
@@ -318,24 +336,9 @@ __tzfile_default (const char *std, const char *dst,
}
__mempcpy (__mempcpy (zone_names, std, stdlen), dst, dstlen);
- /* Find the standard and daylight time offsets used by the rule file.
- We choose the offsets in the types of each flavor that are
- transitioned to earliest in time. */
- rule_stdoff = rule_dstoff = 0;
- for (i = 0; i < num_transitions; ++i)
- {
- if (!rule_stdoff && !types[type_idxs[i]].isdst)
- rule_stdoff = types[type_idxs[i]].offset;
- if (!rule_dstoff && types[type_idxs[i]].isdst)
- rule_dstoff = types[type_idxs[i]].offset;
- if (rule_stdoff && rule_dstoff)
- break;
- }
-
/* Now correct the transition times for the user-specified standard and
daylight offsets from GMT. */
isdst = 0;
- rule_offset = rule_offset;
for (i = 0; i < num_transitions; ++i)
{
struct ttinfo *trans_type = &types[type_idxs[i]];
@@ -419,14 +422,16 @@ __tzfile_compute (time_t timer, int use_localtime,
if (use_localtime)
{
struct ttinfo *info = find_transition (timer);
- __daylight = info->isdst;
- __timezone = -info->offset;
+ __daylight = rule_stdoff != rule_dstoff;
+ __timezone = -rule_stdoff;
+ __tzname[1] = NULL;
for (i = 0;
i < num_types && i < sizeof (__tzname) / sizeof (__tzname[0]);
++i)
__tzname[types[i].isdst] = &zone_names[types[i].idx];
- if (info->isdst < sizeof (__tzname) / sizeof (__tzname[0]))
- __tzname[info->isdst] = &zone_names[info->idx];
+ if (__tzname[1] == NULL)
+ /* There is no daylight saving time. */
+ __tzname[1] = __tzname[0];
}
*leap_correct = 0L;
diff --git a/time/tzset.c b/time/tzset.c
index e766796513..e42be39db8 100644
--- a/time/tzset.c
+++ b/time/tzset.c
@@ -333,6 +333,7 @@ tzset_internal (always)
{
/* There is no DST. */
tz_rules[1].name = tz_rules[0].name;
+ tz_rules[1].offset = tz_rules[0].offset;
free (tzbuf);
return;
}
@@ -547,8 +548,8 @@ tz_compute (timer, tm)
! compute_change (&tz_rules[1], 1900 + tm->tm_year))
return 0;
- __daylight = timer >= tz_rules[0].change && timer < tz_rules[1].change;
- __timezone = -tz_rules[__daylight].offset;
+ __daylight = tz_rules[0].offset != tz_rules[1].offset;
+ __timezone = -tz_rules[0].offset;
__tzname[0] = (char *) tz_rules[0].name;
__tzname[1] = (char *) tz_rules[1].name;
@@ -626,9 +627,10 @@ __tz_convert (const time_t *timer, int use_localtime, struct tm *tp)
{
if (use_localtime)
{
- tp->tm_isdst = __daylight;
- tp->tm_zone = __tzname[__daylight];
- tp->tm_gmtoff = -__timezone;
+ tp->tm_isdst = (*timer >= tz_rules[0].change
+ && *timer < tz_rules[1].change);
+ tp->tm_zone = __tzname[tp->tm_isdst];
+ tp->tm_gmtoff = tz_rules[tp->tm_isdst].offset;
}
else
{
diff --git a/timezone/Makefile b/timezone/Makefile
index 9b436e17ff..1b26d1ab4d 100644
--- a/timezone/Makefile
+++ b/timezone/Makefile
@@ -28,7 +28,7 @@ distribute := tzfile.h private.h scheck.c ialloc.c yearistype \
extra-objs := scheck.o ialloc.o
others := zdump zic
-tests := test-tz
+tests := test-tz tst-timezone
tzbases := africa antarctica asia australasia europe northamerica \
southamerica etcetera factory systemv \
diff --git a/timezone/asia b/timezone/asia
index de1a379846..8d667cc99e 100644
--- a/timezone/asia
+++ b/timezone/asia
@@ -1,4 +1,4 @@
-# @(#)asia 7.36
+# @(#)asia 7.38
# This data is by no means authoritative; if you think you know better,
# go ahead and edit the file (and please send any changes to
@@ -507,7 +507,7 @@ Rule Zion 1988 only - Apr 9 0:00 1:00 D
Rule Zion 1988 only - Sep 3 0:00 0 S
# From Ephraim Silverberg <ephraim@cs.huji.ac.il>
-# (1997-03-04 and 1997-12-31):
+# (1997-03-04 and 1998-03-16):
# According to the Office of the Secretary General of the Ministry of
# Interior, there is NO set rule for Daylight-Savings/Standard time changes.
@@ -557,9 +557,9 @@ Rule Zion 1995 only - Sep 3 0:00 0 S
#
# ftp://ftp.huji.ac.il/pub/tz/announcements/1997.ps.gz
#
-# According to the Office of the Spokeswoman for the Ministry of Interior,
-# the dates for 1998 are tentative and are still subject to final approval
-# (probably in late February/early March of 1998).
+# The official announcement for the year 1998 can be viewed at:
+#
+# ftp://ftp.huji.ac.il/pub/tz/announcements/1998.ps.gz
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Zion 1996 only - Mar 15 0:00 1:00 D
@@ -780,7 +780,6 @@ Zone Indian/Maldives 4:54:00 - LMT 1880 # Male
# Mongolia
# Shanks says that Mongolia has three time zones, but usno1995 and the CIA map
-# <a href="http://www.odci.gov/cia/publications/nsolo/rmap-pdf/802483.pdf">
# Standard Time Zones of the World (1997-01)
# </a>
# both say that it has just one.
diff --git a/timezone/australasia b/timezone/australasia
index 2bb3a0a771..810c10d618 100644
--- a/timezone/australasia
+++ b/timezone/australasia
@@ -1,4 +1,4 @@
-# @(#)australasia 7.40
+# @(#)australasia 7.41
# This file also includes Pacific islands.
# Notes are at the end of this file
@@ -804,7 +804,7 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901
# # YANCOWINNA.. [ Confirmation courtesy of Broken Hill Postmaster ]
# # [ Dec 1990 ]
# ...
-# # Yancowinna uses Central Standard Time, despite it's location on the
+# # Yancowinna uses Central Standard Time, despite [its] location on the
# # New South Wales side of the S.A. border. Most business and social dealings
# # are with CST zones, therefore CST is legislated by local government
# # although the switch to Summer Time occurs in line with N.S.W. There have
diff --git a/timezone/europe b/timezone/europe
index 0df00f3a69..0f2398f677 100644
--- a/timezone/europe
+++ b/timezone/europe
@@ -1,4 +1,4 @@
-# @(#)europe 7.53
+# %W%
# This data is by no means authoritative; if you think you know better,
# go ahead and edit the file (and please send any changes to
diff --git a/timezone/tst-timezone.c b/timezone/tst-timezone.c
new file mode 100644
index 0000000000..49b3621128
--- /dev/null
+++ b/timezone/tst-timezone.c
@@ -0,0 +1,104 @@
+/* Copyright (C) 1998 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Andreas Jaeger <aj@arthur.rhein-neckar.de>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+int failed = 0;
+
+struct test_times
+{
+ const char *name;
+ int daylight;
+ int timezone;
+};
+
+static const struct test_times tests[] =
+{
+ { "Europe/Berlin", 1, -3600 },
+ { "Universal", 0, 0 },
+ { "Australia/Melbourne", 1, -36000 },
+ { "America/Sao_Paulo", 1, 10800 },
+ { NULL, 0, 0 }
+};
+
+
+void
+print_tzvars (void)
+{
+ printf ("tzname[0]: %s\n", tzname[0]);
+ printf ("tzname[1]: %s\n", tzname[1]);
+ printf ("daylight: %d\n", daylight);
+ printf ("timezone: %ld\n", timezone);
+}
+
+
+void
+check_tzvars (const char *name, int dayl, int timez)
+{
+ if (daylight != dayl)
+ {
+ printf ("Timezone: %s, daylight is: %d but should be: %d\n",
+ name, daylight, dayl);
+ ++failed;
+ }
+ if (timezone != timez)
+ {
+ printf ("Timezone: %s, timezone is: %ld but should be: %d\n",
+ name, timezone, timez);
+ ++failed;
+ }
+}
+
+
+int
+main (int argc, char ** argv)
+{
+ time_t t;
+ const struct test_times *pt;
+ char buf[BUFSIZ];
+
+ /* This should be: Thu May 14 18:02:16 1998. */
+ t = 895194136;
+ printf ("We use this date: %s\n", ctime (&t));
+
+ for (pt = tests; pt->name != NULL; ++pt)
+ {
+ /* Start with a known state */
+ printf ("Checking timezone %s\n", pt->name);
+ sprintf (buf, "TZ=%s", pt->name);
+ if (putenv (buf))
+ {
+ puts ("putenv failed.");
+ failed = 1;
+ }
+ tzset ();
+ print_tzvars ();
+ check_tzvars (pt->name, pt->daylight, pt->timezone);
+
+ /* calling localtime shouldn't make a difference */
+ localtime (&t);
+ print_tzvars ();
+ check_tzvars (pt->name, pt->daylight, pt->timezone);
+ }
+
+ return failed ? EXIT_FAILURE : EXIT_SUCCESS;
+}