summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog52
-rw-r--r--FAQ11
-rw-r--r--FAQ.in9
-rw-r--r--elf/Makefile13
-rw-r--r--extra-lib.mk26
-rw-r--r--libio/genops.c94
-rw-r--r--libio/iofgets.c5
-rw-r--r--libio/iofgets_u.c5
-rw-r--r--libio/libio.h3
-rw-r--r--manual/top-menu.texi10
-rw-r--r--sysdeps/generic/isastream.c15
-rw-r--r--sysdeps/unix/sysv/linux/net/if_packet.h17
-rw-r--r--time/mktime.c40
-rw-r--r--time/strftime.c44
14 files changed, 204 insertions, 140 deletions
diff --git a/ChangeLog b/ChangeLog
index 39072c7285..4ad93ce0e6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,55 @@
+1998-11-05 1998  H.J. Lu  <hjl@gnu.org> 
+ 
+	* libio/iofgets.c (_IO_fgets): Don't report error 
+	if something was read in and errno is set to 
+	EAGAIN. 
+	* libio/iofgets_u.c (fgets_unlocked): Likewise. 
+ 
+1998-11-05  Philip Blundell  <philb@gnu.org> 
+ 
+	* sysdeps/unix/sysv/linux/net/if_packet.h: Don't include kernel 
+	header; it defines too much.  Provide a local definition of struct 
+	sockaddr_pkt and a comment advising against its use. 
+ 
+1998-11-06 1998  Andreas Schwab  <schwab@issan.cs.uni-dortmund.de> 
+ 
+	* extra-lib.mk: Avoid empty include list. 
+ 
+1998-11-04  Andreas Schwab  <schwab@issan.cs.uni-dortmund.de> 
+ 
+	* extra-lib.mk: Add support for $(lib)-shared-only-routines. 
+ 
+	* elf/Makefile (libdl-routines): Add dlopenold only if doing 
+	versioning. 
+	(libdl-shared-only-routines): New variable. 
+ 
+1998-11-06  Paul Eggert  <eggert@twinsun.com> 
+ 
+	Don't invoke localtime_r or gmtime_r unless it's the GNU C 
+	library's localtime_r and gmtime_r; there are too many buggy 
+	implementations of localtime_r and gmtime_r out there, and 
+	it's not worth keeping track of all the different bugs. 
+
+	* time/mktime.c (__EXTENSIONS__): Remove. 
+	(<unistd.h>): No need to include. 
+	* time/strftime.c: Likewise.
+
+	* time/mktime.c (_POSIX_THREAD_SAFE_FUNCTIONS, HAVE_LOCALTIME_R):
+	Remove. 
+	(my_mktime_localtime_r): Renamed from localtime_r; all uses changed. 
+	Base it on localtime unless _LIBC. 
+
+	* time/strftime.c (my_strftime_gmtime_r): Renamed from gmtime_r; 
+	all uses changed. 
+	(my_strftime_localtime_r): Renamed from localtime_r; all uses changed. 
+	Base them on localtime/gmtime if not _LIBC. 
+
+1998-11-07  Ulrich Drepper  <drepper@cygnus.com>
+
+	* sysdeps/generic/isastream.c: Always return 0 unless it is an invalid
+	file descriptor.  This makes this function actually usable.
+	Proposed by Mark Kettenis <kettenis@phys.uva.nl>.
+
 1998-11-05  Ulrich Drepper  <drepper@cygnus.com>
 
 	* math/math.h: Unconditionally include bits/mathdef.h.  Declare
diff --git a/FAQ b/FAQ
index 42a05d4860..73385871e8 100644
--- a/FAQ
+++ b/FAQ
@@ -122,6 +122,7 @@ please let me know.
 	happen with db-1, gdbm, or ndbm.
 3.14.	The pow() inline function I get when including <math.h> is broken.
 	I get segmentation faults when I run the program.
+3.15.	The sys/sem.h file lacks the definition of `union semun'.
 
 4. Miscellaneous
 
@@ -751,7 +752,7 @@ ypbind.  ypbind 3.3 and older versions don't always remove these files, so
 glibc will continue to use them.  Other BSD versions seem to work correctly.
 Until ypbind 3.4 is released, you can find a patch at
 
-    ftp://ftp.kernel.org/pub/linux/utils/net/NIS/ypbind-3.3-glibc3.diff.gz
+    ftp://ftp.kernel.org/pub/linux/utils/net/NIS/ypbind-3.3-glibc4.diff.gz
 
 
 2.13.	Under Linux/Alpha, I always get "do_ypcall: clnt_call:
@@ -1237,6 +1238,14 @@ If you have to use this compiler you must define __NO_MATH_INLINES before
 including <math.h> to prevent the inline functions from being used.  egcs 1.1
 fixes the problem.  I don't know about gcc 2.8 and 2.8.1.
 
+
+3.15.	The sys/sem.h file lacks the definition of `union semun'.
+
+{UD} Nope.  This union has to be provided by the user program.  Former glibc
+versions defined this but it was an error since it does not make much sense
+when thinking about it.  The standards describing the System V IPC functions
+define it this way and therefore programs must be adopted.
+
 
 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
 
diff --git a/FAQ.in b/FAQ.in
index f25e42125d..624b219bf1 100644
--- a/FAQ.in
+++ b/FAQ.in
@@ -599,7 +599,7 @@ ypbind.  ypbind 3.3 and older versions don't always remove these files, so
 glibc will continue to use them.  Other BSD versions seem to work correctly.
 Until ypbind 3.4 is released, you can find a patch at
 
-    ftp://ftp.kernel.org/pub/linux/utils/net/NIS/ypbind-3.3-glibc3.diff.gz
+    ftp://ftp.kernel.org/pub/linux/utils/net/NIS/ypbind-3.3-glibc4.diff.gz
 
 ??	Under Linux/Alpha, I always get "do_ypcall: clnt_call:
 	RPC: Unable to receive; errno = Connection refused" when using NIS.
@@ -1063,6 +1063,13 @@ If you have to use this compiler you must define __NO_MATH_INLINES before
 including <math.h> to prevent the inline functions from being used.  egcs 1.1
 fixes the problem.  I don't know about gcc 2.8 and 2.8.1.
 
+??	The sys/sem.h file lacks the definition of `union semun'.
+
+{UD} Nope.  This union has to be provided by the user program.  Former glibc
+versions defined this but it was an error since it does not make much sense
+when thinking about it.  The standards describing the System V IPC functions
+define it this way and therefore programs must be adopted.
+
 
 ? Miscellaneous
 
diff --git a/elf/Makefile b/elf/Makefile
index 763908e7c5..b563e93899 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -40,17 +40,18 @@ distribute	= $(rtld-routines:=.c) dynamic-link.h do-rel.h dl-machine.h \
 		  genrtldtbl.awk atomicity.h dl-procinfo.h ldsodefs.h \
 		  dl-librecon.h interp.c sln.c dl-origin.h
 
+include ../Makeconfig
+
 extra-libs	 = libdl
 extra-libs-others = $(extra-libs)
-libdl-routines	:= dlopen dlclose dlsym dlvsym dlerror dladdr dlopenold
+libdl-routines	:= dlopen dlclose dlsym dlvsym dlerror dladdr
+ifeq ($(versioning),yes)
+libdl-routines	+= dlopenold
+libdl-shared-only-routines := dlopenold
+endif
 
 before-compile = $(objpfx)trusted-dirs.h
 
-
-all: # Make this the default target; it will be defined in Rules.
-
-include ../Makeconfig
-
 ifeq ($(versioning),yes)
 ld-map		= $(common-objpfx)libc.map
 endif
diff --git a/extra-lib.mk b/extra-lib.mk
index 87d4fa3863..e33f958ad7 100644
--- a/extra-lib.mk
+++ b/extra-lib.mk
@@ -19,8 +19,13 @@ extra-objs := $(extra-objs)
 
 # Add each flavor of library to the lists of things to build and install.
 install-lib += $(foreach o,$(object-suffixes-$(lib)),$(lib:lib%=$(libtype$o)))
-extra-objs += $(foreach o,$(object-suffixes-$(lib)),\
-			$(patsubst %,%$o,$($(lib)-routines)))
+extra-objs += $(foreach o,$(object-suffixes-$(lib):.os=),\
+			$(patsubst %,%$o,$(filter-out \
+					   $($(lib)-shared-only-routines),\
+					   $($(lib)-routines))))
+ifneq (,$(filter .os,$(object-suffixes-$(lib))))
+extra-objs += $($(lib)-routines:=.os)
+endif
 alltypes-$(lib) := $(foreach o,$(object-suffixes-$(lib)),\
 			     $(objpfx)$(patsubst %,$(libtype$o),\
 			     $(lib:lib%=%)))
@@ -42,12 +47,23 @@ endif
 
 
 # Use o-iterator.mk to generate a rule for each flavor of library.
+ifneq (,$(filter-out .os,$(object-suffices-$(lib))))
 define o-iterator-doit
 $(objpfx)$(patsubst %,$(libtype$o),$(lib:lib%=%)): \
-  $($(lib)-routines:%=$(objpfx)%$o); $$(build-extra-lib)
+  $(patsubst %,$(objpfx)%$o,\
+	     $(filter-out $($(lib)-shared-only-routines),\
+			  $($(lib)-routines))); \
+	$$(build-extra-lib)
 endef
-object-suffixes-left = $(object-suffixes-$(lib))
-include $(patsubst %,$(..)o-iterator.mk,$(object-suffixes-$(lib)))
+object-suffixes-left = $(object-suffixes-$(lib):.os=)
+include $(patsubst %,$(..)o-iterator.mk,$(object-suffixes-$(lib):.os=))
+endif
+
+ifneq (,$(filter .os,$(object-suffixes-$(lib))))
+$(objpfx)$(patsubst %,$(libtype.os),$(lib:lib%=%)): \
+  $($(lib)-routines:%=$(objpfx)%.os)
+	$(build-extra-lib)
+endif
 
 ifeq ($(versioning),yes)
 # Add the version script to the dependencies of the shared library.
diff --git a/libio/genops.c b/libio/genops.c
index b1ccb289b3..6f560dec53 100644
--- a/libio/genops.c
+++ b/libio/genops.c
@@ -64,13 +64,14 @@ _IO_link_in (fp)
 
 /* Return minimum _pos markers
    Assumes the current get area is the main get area. */
-static _IO_size_t _IO_least_marker __P ((_IO_FILE *fp));
+static _IO_ssize_t _IO_least_marker __P ((_IO_FILE *fp, char *end_p));
 
-static _IO_size_t
-_IO_least_marker (fp)
+static _IO_ssize_t
+_IO_least_marker (fp, end_p)
      _IO_FILE *fp;
+     char *end_p;
 {
-  _IO_ssize_t least_so_far = fp->_IO_read_end - fp->_IO_read_base;
+  _IO_ssize_t least_so_far = end_p - fp->_IO_read_base;
   struct _IO_marker *mark;
   for (mark = fp->_markers; mark != NULL; mark = mark->_next)
     if (mark->_pos < least_so_far)
@@ -94,10 +95,8 @@ _IO_switch_to_main_get_area (fp)
   tmp = fp->_IO_read_base;
   fp->_IO_read_base = fp->_IO_save_base;
   fp->_IO_save_base = tmp;
-  /* Swap _IO_read_ptr and _IO_save_ptr. */
-  tmp = fp->_IO_read_ptr;
-  fp->_IO_read_ptr = fp->_IO_save_ptr;
-  fp->_IO_save_ptr = tmp;
+  /* Set _IO_read_ptr. */
+  fp->_IO_read_ptr = fp->_IO_read_base;
 }
 
 /* Switch current get area from main get area to (end of) backup area. */
@@ -112,12 +111,11 @@ _IO_switch_to_backup_area (fp)
   tmp = fp->_IO_read_end;
   fp->_IO_read_end = fp->_IO_save_end;
   fp->_IO_save_end = tmp;
-  /* Swap _gbase and _IO_save_base. */
+  /* Swap _IO_read_base and _IO_save_base. */
   tmp = fp->_IO_read_base;
   fp->_IO_read_base = fp->_IO_save_base;
   fp->_IO_save_base = tmp;
-  /* read _IO_read_ptr.  */
-  fp->_IO_save_ptr = fp->_IO_read_ptr;
+  /* Set _IO_read_ptr.  */
   fp->_IO_read_ptr = fp->_IO_read_end;
 }
 
@@ -183,26 +181,28 @@ __overflow (f, ch)
   return _IO_OVERFLOW (f, ch);
 }
 
-static int save_for_backup __P ((_IO_FILE *fp))
+static int save_for_backup __P ((_IO_FILE *fp, char *end_p))
 #ifdef _LIBC
      internal_function
 #endif
      ;
 
-     static int
+static int
 #ifdef _LIBC
-     internal_function
+internal_function
 #endif
-save_for_backup (fp)
+save_for_backup (fp, end_p)
      _IO_FILE *fp;
+     char *end_p;
 {
-  /* Append [_IO_read_base.._IO_read_end] to backup area. */
-  int least_mark = _IO_least_marker (fp);
+  /* Append [_IO_read_base..end_p] to backup area. */
+  _IO_ssize_t least_mark = _IO_least_marker (fp, end_p);
   /* needed_size is how much space we need in the backup area. */
-  int needed_size = (fp->_IO_read_end - fp->_IO_read_base) - least_mark;
-  int current_Bsize = fp->_IO_save_end - fp->_IO_save_base;
-  int avail; /* Extra space available for future expansion. */
-  int delta;
+  _IO_size_t needed_size = (end_p - fp->_IO_read_base) - least_mark;
+  /* FIXME: Dubious arithmetic if pointers are NULL */
+  _IO_size_t current_Bsize = fp->_IO_save_end - fp->_IO_save_base;
+  _IO_size_t avail; /* Extra space available for future expansion. */
+  _IO_ssize_t delta;
   struct _IO_marker *mark;
   if (needed_size > current_Bsize)
     {
@@ -218,14 +218,14 @@ save_for_backup (fp)
 				fp->_IO_save_end + least_mark,
 				-least_mark),
 		     fp->_IO_read_base,
-		     fp->_IO_read_end - fp->_IO_read_base);
+		     end_p - fp->_IO_read_base);
 #else
 	  memcpy (new_buffer + avail,
 		  fp->_IO_save_end + least_mark,
 		  -least_mark);
 	  memcpy (new_buffer + avail - least_mark,
 		  fp->_IO_read_base,
-		  fp->_IO_read_end - fp->_IO_read_base);
+		  end_p - fp->_IO_read_base);
 #endif
 	}
       else
@@ -247,17 +247,16 @@ save_for_backup (fp)
 		   -least_mark);
 	  memcpy (fp->_IO_save_base + avail - least_mark,
 		  fp->_IO_read_base,
-		  fp->_IO_read_end - fp->_IO_read_base);
+		  end_p - fp->_IO_read_base);
 	}
       else if (needed_size > 0)
 	memcpy (fp->_IO_save_base + avail,
 		fp->_IO_read_base + least_mark,
 		needed_size);
     }
-  /* FIXME: Dubious arithmetic if pointers are NULL */
   fp->_IO_backup_base = fp->_IO_save_base + avail;
   /* Adjust all the streammarkers. */
-  delta = fp->_IO_read_end - fp->_IO_read_base;
+  delta = end_p - fp->_IO_read_base;
   for (mark = fp->_markers; mark != NULL; mark = mark->_next)
     mark->_pos -= delta;
   return 0;
@@ -280,7 +279,7 @@ __underflow (fp)
     }
   if (_IO_have_markers (fp))
     {
-      if (save_for_backup (fp))
+      if (save_for_backup (fp, fp->_IO_read_end))
 	return EOF;
     }
   else if (_IO_have_backup (fp))
@@ -305,7 +304,7 @@ __uflow (fp)
     }
   if (_IO_have_markers (fp))
     {
-      if (save_for_backup (fp))
+      if (save_for_backup (fp, fp->_IO_read_end))
 	return EOF;
     }
   else if (_IO_have_backup (fp))
@@ -817,10 +816,7 @@ _IO_seekmark (fp, mark, delta)
   else
     {
       if (!_IO_in_backup (fp))
-	{
-	  fp->_IO_read_ptr = fp->_IO_read_base;
-	  _IO_switch_to_backup_area (fp);
-	}
+	_IO_switch_to_backup_area (fp);
       fp->_IO_read_ptr = fp->_IO_read_end + mark->_pos;
     }
   return 0;
@@ -880,20 +876,28 @@ _IO_default_pbackfail (fp, c)
   else
     {
       /* Need to handle a filebuf in write mode (switch to read mode). FIXME!*/
-      if (_IO_have_backup (fp) && !_IO_in_backup (fp))
-	_IO_switch_to_backup_area (fp);
-
-      if (!_IO_have_backup (fp))
+      if (!_IO_in_backup (fp))
 	{
-	  /* No backup buffer: allocate one. */
-	  /* Use nshort buffer, if unused? (probably not)  FIXME */
-	  int backup_size = 128;
-	  char *bbuf = (char *) malloc (backup_size);
-	  if (bbuf == NULL)
-	    return EOF;
-	  fp->_IO_save_base = bbuf;
-	  fp->_IO_save_end = fp->_IO_save_base + backup_size;
-	  fp->_IO_backup_base = fp->_IO_save_end;
+	  /* We need to keep the invariant that the main get area
+	     logically follows the backup area.  */
+	  if (fp->_IO_read_ptr > fp->_IO_read_base && _IO_have_backup (fp))
+	    {
+	      if (save_for_backup (fp, fp->_IO_read_ptr))
+		return EOF;
+	    }
+	  else if (!_IO_have_backup (fp))
+	    {
+	      /* No backup buffer: allocate one. */
+	      /* Use nshort buffer, if unused? (probably not)  FIXME */
+	      int backup_size = 128;
+	      char *bbuf = (char *) malloc (backup_size);
+	      if (bbuf == NULL)
+		return EOF;
+	      fp->_IO_save_base = bbuf;
+	      fp->_IO_save_end = fp->_IO_save_base + backup_size;
+	      fp->_IO_backup_base = fp->_IO_save_end;
+	    }
+	  fp->_IO_read_base = fp->_IO_read_ptr;
 	  _IO_switch_to_backup_area (fp);
 	}
       else if (fp->_IO_read_ptr <= fp->_IO_read_base)
diff --git a/libio/iofgets.c b/libio/iofgets.c
index d61fb81481..98e82782ce 100644
--- a/libio/iofgets.c
+++ b/libio/iofgets.c
@@ -46,7 +46,10 @@ _IO_fgets (buf, n, fp)
   old_error = fp->_IO_file_flags & _IO_ERR_SEEN;
   fp->_IO_file_flags &= ~_IO_ERR_SEEN;
   count = _IO_getline (fp, buf, n - 1, '\n', 1);
-  if (count == 0 || (fp->_IO_file_flags & _IO_ERR_SEEN))
+  /* If we read in some bytes and errno is EAGAIN, that error will
+     be reported for next read. */
+  if (count == 0 || ((fp->_IO_file_flags & _IO_ERR_SEEN)
+		     && errno != EAGAIN))
     result = NULL;
   else
     {
diff --git a/libio/iofgets_u.c b/libio/iofgets_u.c
index 1eb98bd542..df6fa9afe3 100644
--- a/libio/iofgets_u.c
+++ b/libio/iofgets_u.c
@@ -44,7 +44,10 @@ fgets_unlocked (buf, n, fp)
   old_error = fp->_IO_file_flags & _IO_ERR_SEEN;
   fp->_IO_file_flags &= ~_IO_ERR_SEEN;
   count = _IO_getline (fp, buf, n - 1, '\n', 1);
-  if (count == 0 || (fp->_IO_file_flags & _IO_ERR_SEEN))
+  /* If we read in some bytes and errno is EAGAIN, that error will
+     be reported for next read. */
+  if (count == 0 || ((fp->_IO_file_flags & _IO_ERR_SEEN)
+  		     && errno != EAGAIN))
     result = NULL;
   else
     {
diff --git a/libio/libio.h b/libio/libio.h
index b257f13915..fcb8ae6eaa 100644
--- a/libio/libio.h
+++ b/libio/libio.h
@@ -231,9 +231,8 @@ struct _IO_FILE_complete
 #endif
 #if defined _G_IO_IO_FILE_VERSION && _G_IO_IO_FILE_VERSION == 0x20001
   _IO_off64_t _offset;
-  char *_IO_save_ptr;
   /* Make sure we don't get into trouble again.  */
-  char _unused2[16 * sizeof (int) - sizeof (char *)];
+  int _unused2[16];
 #endif
 };
 
diff --git a/manual/top-menu.texi b/manual/top-menu.texi
index ce5919886e..b08ab50d3a 100644
--- a/manual/top-menu.texi
+++ b/manual/top-menu.texi
@@ -1149,12 +1149,10 @@ Floating Type Macros
 
 Installation
 
-* Tools for Installation::      We recommend using these tools to build.
-* Supported Configurations::    What systems the GNU C library runs on.
-* Tips for Installation::       Useful hints for the installation.
-* Reporting Bugs::              How to report bugs (if you want to
-                                get them fixed) and other troubles
-                                you may have with the GNU C library.
+* Configuring and compiling::   How to compile and test GNU libc.
+* Tools for Compilation::       You'll need these first.
+* Supported Configurations::    What it runs on, what it doesn't.
+* Reporting Bugs::              So they'll get fixed.
 
 Maintenance
 
diff --git a/sysdeps/generic/isastream.c b/sysdeps/generic/isastream.c
index 4e595808ea..00a4760aab 100644
--- a/sysdeps/generic/isastream.c
+++ b/sysdeps/generic/isastream.c
@@ -17,16 +17,19 @@
    Boston, MA 02111-1307, USA.  */
 
 #include <errno.h>
+#include <fcntl.h>
 #include <stropts.h>
 
 int
 isastream (fildes)
      int fildes;
 {
-  __set_errno (ENOSYS);
-  return -1;
-}
-
+  /* In general we do not have a STREAMS implementation and therefore
+     return 0.  But for invalid file descriptors we have to return an
+     error.  */
+  if (__fcntl (fildes, F_GETFD) < 0)
+    return -1;
 
-stub_warning (isastream)
-#include <stub-tag.h>
+  /* No STREAM.  */
+  return 0;
+}
diff --git a/sysdeps/unix/sysv/linux/net/if_packet.h b/sysdeps/unix/sysv/linux/net/if_packet.h
index 60155eeac3..441cad1758 100644
--- a/sysdeps/unix/sysv/linux/net/if_packet.h
+++ b/sysdeps/unix/sysv/linux/net/if_packet.h
@@ -1,5 +1,5 @@
 /* Definitions for use with Linux SOCK_PACKET sockets.
-   Copyright (C) 1997 Free Software Foundation, Inc.
+   Copyright (C) 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
@@ -20,7 +20,18 @@
 #ifndef __IF_PACKET_H
 #define __IF_PACKET_H
 
-/* For now we can just use the kernel definitions.  */
-#include <linux/if_packet.h>
+#include <features.h>
+#include <bits/sockaddr.h>
+
+/* This is the SOCK_PACKET address structure as used in Linux 2.0.
+   From Linux 2.1 the AF_PACKET interface is preferred and you should
+   consider using it in place of this one.  */
+
+struct sockaddr_pkt
+  {
+    __SOCKADDR_COMMON (spkt_);
+    unsigned char spkt_device[14];
+    unsigned short spkt_protocol;
+  };
 
 #endif
diff --git a/time/mktime.c b/time/mktime.c
index 673bb48266..88ac72366a 100644
--- a/time/mktime.c
+++ b/time/mktime.c
@@ -25,18 +25,8 @@
 # include <config.h>
 #endif
 
-/* Some systems require that one of these symbols be defined in
-   order to declare localtime_r properly.  */
-#ifndef __EXTENSIONS__
-# define __EXTENSIONS__ 1
-#endif
-#ifndef _POSIX_THREAD_SAFE_FUNCTIONS
-# define _POSIX_THREAD_SAFE_FUNCTIONS 1
-#endif
-
 #ifdef _LIBC
 # define HAVE_LIMITS_H 1
-# define HAVE_LOCALTIME_R 1
 # define STDC_HEADERS 1
 #endif
 
@@ -47,12 +37,6 @@
 # define LEAP_SECONDS_POSSIBLE 1
 #endif
 
-/* Some systems require <unistd.h> to be included before <time.h>
-   for localtime_r to be declared properly.  */
-#if HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
 #include <sys/types.h>		/* Some systems define `time_t' here.  */
 #include <time.h>
 
@@ -132,35 +116,23 @@ time_t __mktime_internal __P ((struct tm *,
 
 
 #ifdef _LIBC
-# define localtime_r __localtime_r
+# define my_mktime_localtime_r __localtime_r
 #else
-# if HAVE_LOCALTIME_R == defined localtime_r
-/* Provide our own substitute for a missing or possibly broken localtime_r.  */
+/* If we're a mktime substitute in a GNU program, then prefer
+   localtime to localtime_r, since many localtime_r implementations
+   are buggy.  */
 static struct tm *my_mktime_localtime_r __P ((const time_t *, struct tm *));
 static struct tm *
 my_mktime_localtime_r (t, tp)
      const time_t *t;
      struct tm *tp;
 {
-#  ifdef localtime_r
-  /* Digital Unix 4.0A and 4.0D have a macro localtime_r with the
-     standard meaning, along with an unwanted, nonstandard function
-     localtime_r.  The placeholder function my_mktime_localtime_r
-     invokes the macro; use that instead of the system's bogus
-     localtime_r.  */
-  return localtime_r (t, tp);
-#   undef localtime_r
-#  else /* ! defined (localtime_r) */
-  /* Approximate localtime_r as best we can in its absence.  */
   struct tm *l = localtime (t);
   if (! l)
     return 0;
   *tp = *l;
   return tp;
-#  endif /* ! defined localtime_r */
 }
-#  define localtime_r my_mktime_localtime_r
-# endif /* HAVE_LOCALTIME_R == defined localtime_r */
 #endif /* ! _LIBC */
 
 
@@ -215,7 +187,7 @@ mktime (tp)
   __tzset ();
 #endif
 
-  return __mktime_internal (tp, localtime_r, &localtime_offset);
+  return __mktime_internal (tp, my_mktime_localtime_r, &localtime_offset);
 }
 
 /* Use CONVERT to convert *T to a broken down time in *TP.
@@ -565,6 +537,6 @@ main (argc, argv)
 
 /*
 Local Variables:
-compile-command: "gcc -DDEBUG -D__EXTENSIONS__ -DHAVE_LIMITS_H -DHAVE_LOCALTIME_R -DSTDC_HEADERS -Wall -W -O -g mktime.c -o mktime"
+compile-command: "gcc -DDEBUG -DHAVE_LIMITS_H -DSTDC_HEADERS -Wall -W -O -g mktime.c -o mktime"
 End:
 */
diff --git a/time/strftime.c b/time/strftime.c
index 69babade36..3e81d2189b 100644
--- a/time/strftime.c
+++ b/time/strftime.c
@@ -20,11 +20,6 @@
 # include <config.h>
 #endif
 
-/* Some hosts need this in order to declare localtime_r properly.  */
-#ifndef __EXTENSIONS__
-# define __EXTENSIONS__ 1
-#endif
-
 #ifdef _LIBC
 # define HAVE_LIMITS_H 1
 # define HAVE_MBLEN 1
@@ -46,12 +41,6 @@
 #include <ctype.h>
 #include <sys/types.h>		/* Some systems define `time_t' here.  */
 
-/* Some systems require <unistd.h> to be included before <time.h>
-   for localtime_r to be declared properly.  */
-#if HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
 #ifdef TIME_WITH_SYS_TIME
 # include <sys/time.h>
 # include <time.h>
@@ -153,19 +142,20 @@ extern char *tzname[];
 
 
 #ifdef _LIBC
-# define gmtime_r __gmtime_r
-# define localtime_r __localtime_r
+# define my_strftime_gmtime_r __gmtime_r
+# define my_strftime_localtime_r __localtime_r
 # define tzname __tzname
 # define tzset __tzset
 #else
-# if ! HAVE_LOCALTIME_R
-#  if ! HAVE_TM_GMTOFF
-/* Approximate gmtime_r as best we can in its absence.  */
-#   undef gmtime_r
-#   define gmtime_r my_gmtime_r
-static struct tm *gmtime_r __P ((const time_t *, struct tm *));
+
+/* If we're a strftime substitute in a GNU program, then prefer gmtime
+   to gmtime_r, since many gmtime_r implementations are buggy.
+   Similarly for localtime_r.  */
+
+# if ! HAVE_TM_GMTOFF
+static struct tm *my_strftime_gmtime_r __P ((const time_t *, struct tm *));
 static struct tm *
-gmtime_r (t, tp)
+my_strftime_gmtime_r (t, tp)
      const time_t *t;
      struct tm *tp;
 {
@@ -175,14 +165,11 @@ gmtime_r (t, tp)
   *tp = *l;
   return tp;
 }
-#  endif /* ! HAVE_TM_GMTOFF */
+# endif /* ! HAVE_TM_GMTOFF */
 
-/* Approximate localtime_r as best we can in its absence.  */
-#  undef localtime_r
-#  define localtime_r my_ftime_localtime_r
-static struct tm *localtime_r __P ((const time_t *, struct tm *));
+static struct tm *my_strftime_localtime_r __P ((const time_t *, struct tm *));
 static struct tm *
-localtime_r (t, tp)
+my_strftime_localtime_r (t, tp)
      const time_t *t;
      struct tm *tp;
 {
@@ -192,7 +179,6 @@ localtime_r (t, tp)
   *tp = *l;
   return tp;
 }
-# endif /* ! HAVE_LOCALTIME_R */
 #endif /* ! defined _LIBC */
 
 
@@ -1203,7 +1189,7 @@ my_strftime (s, maxsize, format, tp ut_argument)
 		       occurred.  */
 		    struct tm tm;
 
-		    if (! localtime_r (&lt, &tm)
+		    if (! my_strftime_localtime_r (&lt, &tm)
 			|| ((ltm.tm_sec ^ tm.tm_sec)
 			    | (ltm.tm_min ^ tm.tm_min)
 			    | (ltm.tm_hour ^ tm.tm_hour)
@@ -1213,7 +1199,7 @@ my_strftime (s, maxsize, format, tp ut_argument)
 		      break;
 		  }
 
-		if (! gmtime_r (&lt, &gtm))
+		if (! my_strftime_gmtime_r (&lt, &gtm))
 		  break;
 
 		diff = tm_diff (&ltm, &gtm);