about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>1996-05-09 00:37:21 +0000
committerRoland McGrath <roland@gnu.org>1996-05-09 00:37:21 +0000
commit7c713e287e50dc338779ed1a6c6ac701720a3a41 (patch)
tree00dc9bb790eef870a0624a5813120cc3971b16ff
parentf0523145cc30a32daa64dd0bd5661b0b204f00da (diff)
downloadglibc-7c713e287e50dc338779ed1a6c6ac701720a3a41.tar.gz
glibc-7c713e287e50dc338779ed1a6c6ac701720a3a41.tar.xz
glibc-7c713e287e50dc338779ed1a6c6ac701720a3a41.zip
Wed May 8 20:04:29 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
	* Rules (subdir_install): Depend on $(common-objpfx)sor-$(subdir).
	[! libc.so-version]: Clear static-only-routines.
	($(common-objpfx)sor-$(subdir)): New target.
	[static-only-routines]: New static pattern rule for these .so's.
	* Makerules [libc.so-version] ($(slibdir)/libc.so): Target removed.
	[libc.so-version] ($(libdir)/libc.so, $(common-objpfx)libc-syms.so):
	New targets replace it.
	(install) [libc.so-version]: Depend on $(libdir)/libc.so instead of
	$(slibdir)/libc.so.
	* io/Makefile (static-only-routines): New variable.
	* configure.in: Check for tools objdump and objcopy, and for awk.
	* config.make.in (OBJDUMP, OBJCOPY, AWK): New variables.

Thu May  9 01:24:00 1996  Ulrich Drepper  <drepper@cygnus.com>

	* locale/programs/config.h: Remove definition of wint_t.

	* locale/programs/ld-collate.c: Include <wchar.h> instead of
	<wcstr.h>.

	* manual/time.texi: Add some more description for %U and %W
	format of strftime.  Describe new format %V of strftime.

	* resolv/gethnamaddr.c: Prevent warning by preventing variable
	definition.
	* stdio-common/_itoa.c: Ditto.

Tue May  7 23:43:07 1996  Ulrich Drepper  <drepper@cygnus.com>

	* libio/clearerr.c, libio/feof.c, libio/ferror.c, libio/fgetc.c,
	libio/fileno.c, libio/fputc.c, libio/freopen.c, libio/fseek.c,
	libio/genops.c, libio/getc.c, libio/getchar.c, libio/iofclose.c,
	libio/iofflush.c, libio/iofgetpos.c, libio/iofgets.c,
	libio/iofputs.c, libio/iofread.c, libio/iofsetpos.c,
	libio/ioftell.c, libio/iofwrite.c, libio/iogetdelim.c,
	libio/iogets.c, libio/ioputs.c, libio/iosetbuffer.c,
	libio/iosetvbuf.c, libio/ioungetc.c, libio/iovsprintf.c,
	libio/libio.h, libio/putc.c, libio/putchar.c, libio/rewind.c,
	libio/stdio.h, stdio-common/printf_fp.c, stdio-common/vfprintf.c,
	stdio-common/vfscanf.c: Prepare for reentrent libio.

	* libio/clearerr_u.c, libio/feof_u.c, libio/ferror_u.c,
	libio/fputc_u.c, libio/getc_u.c, libio/getchar_u.c,
	libio/iofflush_u.c, libio/putc_u.c, libio/putchar_u.c: New files.
	Used in reentrent libio.

	* misc/getusershell.c: Prevent warnings.
-rw-r--r--ChangeLog50
-rw-r--r--Makerules22
-rw-r--r--Rules28
-rw-r--r--config.make.in3
-rw-r--r--configure.in5
-rw-r--r--io/Makefile5
-rw-r--r--libio/clearerr.c32
-rw-r--r--libio/clearerr_u.c30
-rw-r--r--libio/feof.c21
-rw-r--r--libio/feof_u.c33
-rw-r--r--libio/ferror.c14
-rw-r--r--libio/ferror_u.c33
-rw-r--r--libio/fgetc.c6
-rw-r--r--libio/fileno.c11
-rw-r--r--libio/fputc.c8
-rw-r--r--libio/fputc_u.c39
-rw-r--r--libio/freopen.c8
-rw-r--r--libio/fseek.c6
-rw-r--r--libio/genops.c7
-rw-r--r--libio/getc.c19
-rw-r--r--libio/getc_u.c38
-rw-r--r--libio/getchar.c14
-rw-r--r--libio/getchar_u.c36
-rw-r--r--libio/iofclose.c2
-rw-r--r--libio/iofflush.c10
-rw-r--r--libio/iofflush_u.c41
-rw-r--r--libio/iofgetpos.c2
-rw-r--r--libio/iofgets.c13
-rw-r--r--libio/iofputs.c13
-rw-r--r--libio/iofread.c2
-rw-r--r--libio/iofsetpos.c9
-rw-r--r--libio/ioftell.c2
-rw-r--r--libio/iofwrite.c2
-rw-r--r--libio/iogetdelim.c30
-rw-r--r--libio/iogets.c6
-rw-r--r--libio/ioputs.c16
-rw-r--r--libio/iosetbuffer.c6
-rw-r--r--libio/iosetvbuf.c23
-rw-r--r--libio/ioungetc.c8
-rw-r--r--libio/iovsprintf.c2
-rw-r--r--libio/libio.h38
-rw-r--r--libio/putc.c19
-rw-r--r--libio/putc_u.c31
-rw-r--r--libio/putchar.c14
-rw-r--r--libio/putchar_u.c30
-rw-r--r--libio/rewind.c2
-rw-r--r--libio/stdio.h47
-rw-r--r--locale/programs/config.h3
-rw-r--r--locale/programs/ld-collate.c4
-rw-r--r--manual/time.texi13
-rw-r--r--misc/getusershell.c20
-rw-r--r--resolv/gethnamaddr.c5
-rw-r--r--stdio-common/_itoa.c6
-rw-r--r--stdio-common/printf_fp.c2
-rw-r--r--stdio-common/vfprintf.c38
-rw-r--r--stdio-common/vfscanf.c85
56 files changed, 866 insertions, 146 deletions
diff --git a/ChangeLog b/ChangeLog
index 2e42e869e6..1609c71eed 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,53 @@
+Wed May  8 20:04:29 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
+
+	* Rules (subdir_install): Depend on $(common-objpfx)sor-$(subdir).
+	[! libc.so-version]: Clear static-only-routines.
+	($(common-objpfx)sor-$(subdir)): New target.
+	[static-only-routines]: New static pattern rule for these .so's.
+	* Makerules [libc.so-version] ($(slibdir)/libc.so): Target removed.
+	[libc.so-version] ($(libdir)/libc.so, $(common-objpfx)libc-syms.so):
+	New targets replace it.
+	(install) [libc.so-version]: Depend on $(libdir)/libc.so instead of
+	$(slibdir)/libc.so.
+	* io/Makefile (static-only-routines): New variable.
+	* configure.in: Check for tools objdump and objcopy, and for awk.
+	* config.make.in (OBJDUMP, OBJCOPY, AWK): New variables.
+
+Thu May  9 01:24:00 1996  Ulrich Drepper  <drepper@cygnus.com>
+
+	* locale/programs/config.h: Remove definition of wint_t.
+
+	* locale/programs/ld-collate.c: Include <wchar.h> instead of
+	<wcstr.h>.
+
+	* manual/time.texi: Add some more description for %U and %W
+	format of strftime.  Describe new format %V of strftime.
+
+	* resolv/gethnamaddr.c: Prevent warning by preventing variable
+	definition.
+	* stdio-common/_itoa.c: Ditto.
+
+Tue May  7 23:43:07 1996  Ulrich Drepper  <drepper@cygnus.com>
+
+	* libio/clearerr.c, libio/feof.c, libio/ferror.c, libio/fgetc.c,
+	libio/fileno.c, libio/fputc.c, libio/freopen.c, libio/fseek.c,
+	libio/genops.c, libio/getc.c, libio/getchar.c, libio/iofclose.c,
+	libio/iofflush.c, libio/iofgetpos.c, libio/iofgets.c,
+	libio/iofputs.c, libio/iofread.c, libio/iofsetpos.c,
+	libio/ioftell.c, libio/iofwrite.c, libio/iogetdelim.c,
+	libio/iogets.c, libio/ioputs.c, libio/iosetbuffer.c,
+	libio/iosetvbuf.c, libio/ioungetc.c, libio/iovsprintf.c,
+	libio/libio.h, libio/putc.c, libio/putchar.c, libio/rewind.c,
+	libio/stdio.h, stdio-common/printf_fp.c, stdio-common/vfprintf.c,
+	stdio-common/vfscanf.c: Prepare for reentrent libio.
+
+	* libio/clearerr_u.c, libio/feof_u.c, libio/ferror_u.c,
+	libio/fputc_u.c, libio/getc_u.c, libio/getchar_u.c,
+	libio/iofflush_u.c, libio/putc_u.c, libio/putchar_u.c: New files.
+	Used in reentrent libio.
+
+	* misc/getusershell.c: Prevent warnings.
+
 Wed May  8 12:08:35 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
 
 	* Makerules (install-lib.so rules): Undouble $s in target and dep
diff --git a/Makerules b/Makerules
index d206a6edca..6305ad753b 100644
--- a/Makerules
+++ b/Makerules
@@ -550,7 +550,6 @@ install-lib := $(filter-out %.so %_pic.a,$(install-lib))
 ifeq (yes,$(build-shared))
 
 install-lib-nosubdir: $(install-lib.so:%=$(libdir)/%)
-install: $(slibdir)/libc.so
 
 # Find which .so's have versions.
 versioned := $(foreach so,$(install-lib.so),\
@@ -567,12 +566,29 @@ ifdef libc.so-version
 # libc.so	->	libc.so.N	(e.g. libc.so.6)
 # libc.so.6	->	libc-VERSION.so	(e.g. libc-1.10.so)
 
-$(slibdir)/libc.so: $(slibdir)/libc.so$(libc.so-version)
-	$(make-link)
 $(slibdir)/libc.so$(libc.so-version): $(slibdir)/libc-$(version).so
 	$(make-link)
 $(slibdir)/libc-$(version).so: $(common-objpfx)libc.so; $(do-install-program)
+
+# What we install as libc.so for programs to link against is in fact an
+# archive.  It contains the various $(static-only-routines) objects, and
+# the special object libc-syms.so that contains just the dynamic symbol
+# table of the shared libc object.
+install: $(libdir)/libc.so
+$(libdir)/libc.so: $(common-objpfx)libc-syms.so subdir_install
+	$(AR) crvs $@ $< `cat $(addprefix $(common-objpfx)sor-,$(subdirs))`
+
+# Extract from the shared object file just the dynamic symbol table
+# needed to link against the shared library.
+$(common-objpfx)libc-syms.so: $(common-objpfx)libc.so
+	AWK='$(AWK)' OBJCOPY='$(OBJCOPY)' OBJDUMP='$(OBJDUMP)' \
+	./extract-dynsym $< $@
+ifndef subdir
+generated += libc-syms.so
+endif
+
 else
+install: $(slibdir)/libc.so
 $(slibdir)/libc.so: $(common-objpfx)libc.so; $(do-install-program)
 endif
 
diff --git a/Rules b/Rules
index 8d9d0a4695..9a7a505a30 100644
--- a/Rules
+++ b/Rules
@@ -122,7 +122,33 @@ subdir_echo-distinfo:
 # our portions of the library because the parent make will install it later
 # (likewise the stubs file).
 .PHONY: subdir_install
-subdir_install: install-no-libc.a lib-noranlib stubs
+subdir_install: install-no-libc.a lib-noranlib stubs \
+		$(common-objpfx)sor-$(subdir)
+
+ifdef objpfx
+sor-objpfx = $(objpfx:../%=%)
+else
+sor-objpfx = $(subdir)
+endif
+
+ifndef libc.so-version
+# Undefine this because it can't work when we libc.so is unversioned.
+static-only-routines =
+endif
+
+# This communicates to the parent during install the set of routines that
+# need to be put into the special libc.so archive.
+$(common-objpfx)sor-$(subdir): Makefile
+	echo $(static-only-routines:%=$(sor-objpfx)%.o) > $@T
+	mv -f $@T $@
+
+ifdef static-only-routines
+# These routines are to be omitted from the shared library object,
+# so we replace the PIC objects for them with the dummy object file.
+$(static-only-routines:%=$(objpfx)%.so): %.so: $(common-objpfx) dummy.so
+	rm -f $@
+	ln $< $@
+endif
 
 .PHONY: subdir_TAGS subdir_dist
 subdir_TAGS: TAGS
diff --git a/config.make.in b/config.make.in
index 644e5edde5..a443050902 100644
--- a/config.make.in
+++ b/config.make.in
@@ -33,6 +33,9 @@ CC = @CC@
 AR = @AR@
 RANLIB = @RANLIB@
 AS = $(CC) -c
+OBJDUMP = @OBJDUMP@
+OBJCOPY = @OBJCOPY@
+AWK = @AWK@
 
 # Installation tools.
 INSTALL = @INSTALL@
diff --git a/configure.in b/configure.in
index ed288db410..d37e4d1c5b 100644
--- a/configure.in
+++ b/configure.in
@@ -301,9 +301,12 @@ AC_PROG_LN_S
 AC_CHECK_PROGS(MSGFMT, msgfmt gmsgfmt, :)
 
 AC_CHECK_TOOL(CC, gcc)
+AC_PROG_CPP
 AC_CHECK_TOOL(AR, ar)
 AC_CHECK_TOOL(RANLIB, ranlib, :)
-AC_PROG_CPP
+AC_CHECK_TOOL(OBJDUMP, objdump)
+AC_CHECK_TOOL(OBJCOPY, objcopy)
+AC_PROG_AWK
 
 AC_CACHE_CHECK(for signed size_t type, libc_cv_signed_size_t, [dnl
 echo '#include <stddef.h>
diff --git a/io/Makefile b/io/Makefile
index 691ac03041..ce8708c7ba 100644
--- a/io/Makefile
+++ b/io/Makefile
@@ -45,6 +45,11 @@ routines :=							      \
 	unlink rmdir						      \
 	ftw fts poll
 
+# These routines will be omitted from the libc shared object.
+# Instead the static object files will be included in a special archive
+# linked against when the shared library will be used.
+static-only-routines = stat fstat lstat mknod
+
 others		:= pwd
 tests		:= test-utime
 
diff --git a/libio/clearerr.c b/libio/clearerr.c
index ee9780bdaf..669a9b0d74 100644
--- a/libio/clearerr.c
+++ b/libio/clearerr.c
@@ -1,10 +1,34 @@
+/* Copyright (C) 1995, 1996 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
+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 "libioP.h"
 #include "stdio.h"
 
 void
-clearerr(fp)
-     FILE* fp;
+clearerr (fp)
+     FILE *fp;
 {
-  CHECK_FILE(fp, /*nothing*/);
-  _IO_clearerr(fp);
+  CHECK_FILE (fp, /*nothing*/);
+  flockfile (fp);
+  _IO_clearerr (fp);
+  funlockfile (fp);
 }
+
+#ifdef _IO_MTSAFE_IO
+weak_alias (clearerr, clearerr_locked)
+#endif
diff --git a/libio/clearerr_u.c b/libio/clearerr_u.c
new file mode 100644
index 0000000000..83ed65d8b1
--- /dev/null
+++ b/libio/clearerr_u.c
@@ -0,0 +1,30 @@
+/* Copyright (C) 1995, 1996 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
+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 "libioP.h"
+#include "stdio.h"
+
+void
+__clearerr_unlocked (fp)
+     FILE *fp;
+{
+  CHECK_FILE (fp, /*nothing*/);
+  _IO_clearerr (fp);
+}
+
+weak_alias (clearerr_unlocked, __clearerr_unlocked)
diff --git a/libio/feof.c b/libio/feof.c
index bd30c175f3..9fb0008afb 100644
--- a/libio/feof.c
+++ b/libio/feof.c
@@ -1,5 +1,4 @@
-/* 
-Copyright (C) 1993 Free Software Foundation
+/* Copyright (C) 1993, 1996 Free Software Foundation, Inc.
 
 This file is part of the GNU IO Library.  This library is free
 software; you can redistribute it and/or modify it under the
@@ -26,9 +25,21 @@ the executable file might be covered by the GNU General Public License. */
 #include "stdio.h"
 
 int
-feof(fp)
+feof (fp)
      _IO_FILE* fp;
 {
-  CHECK_FILE(fp, EOF);
-  return _IO_feof(fp);
+  int result;
+  CHECK_FILE (fp, EOF);
+  _IO_flockfile (fp);
+  result = _IO_feof_unlocked (fp);
+  _IO_funlockfile (fp);
+  return result;
 }
+
+#ifdef _IO_MTSAFE_IO
+/* The feof implementation for libio does not require locking because
+   it only accesses once a single variable and this is already atomic
+   (at least at thread level).  */
+
+weak_alias (feof, feof_locked)
+#endif
diff --git a/libio/feof_u.c b/libio/feof_u.c
new file mode 100644
index 0000000000..5ce5583613
--- /dev/null
+++ b/libio/feof_u.c
@@ -0,0 +1,33 @@
+/* Copyright (C) 1993, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU IO Library.  This library is free
+software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this library; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+As a special exception, if you link this library with files
+compiled with a GNU compiler to produce an executable, this does not cause
+the resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why
+the executable file might be covered by the GNU General Public License. */
+
+#include "libioP.h"
+#include "stdio.h"
+
+int
+feof_unlocked (fp)
+     _IO_FILE* fp;
+{
+  CHECK_FILE (fp, EOF);
+  return _IO_feof_unlocked (fp);
+}
diff --git a/libio/ferror.c b/libio/ferror.c
index d0159818e8..32fd6d0dd9 100644
--- a/libio/ferror.c
+++ b/libio/ferror.c
@@ -1,5 +1,4 @@
-/*
-Copyright (C) 1993, 1995 Free Software Foundation
+/* Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
 
 This file is part of the GNU IO Library.  This library is free
 software; you can redistribute it and/or modify it under the
@@ -29,6 +28,15 @@ int
 ferror (fp)
      _IO_FILE* fp;
 {
+  int result;
   CHECK_FILE (fp, EOF);
-  return _IO_ferror (fp);
+  _IO_flockfile (fp);
+  result = _IO_ferror_unlocked (fp);
+  _IO_funlockfile (fp);
+  return result;
 }
+
+#ifdef _IO_MTSAFE_IO
+
+weak_alias (ferror, ferror_locked)
+#endif
diff --git a/libio/ferror_u.c b/libio/ferror_u.c
new file mode 100644
index 0000000000..bee668d6d9
--- /dev/null
+++ b/libio/ferror_u.c
@@ -0,0 +1,33 @@
+/* Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU IO Library.  This library is free
+software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this library; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+As a special exception, if you link this library with files
+compiled with a GNU compiler to produce an executable, this does not cause
+the resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why
+the executable file might be covered by the GNU General Public License. */
+
+#include "libioP.h"
+#include "stdio.h"
+
+int
+ferror_unlocked (fp)
+     _IO_FILE* fp;
+{
+  CHECK_FILE (fp, EOF);
+  return _IO_ferror_unlocked (fp);
+}
diff --git a/libio/fgetc.c b/libio/fgetc.c
index 19c0a589d9..2aaea05cfe 100644
--- a/libio/fgetc.c
+++ b/libio/fgetc.c
@@ -29,6 +29,10 @@ int
 fgetc (fp)
      FILE *fp;
 {
+  int result;
   CHECK_FILE (fp, EOF);
-  return _IO_getc (fp);
+  flockfile (fp);
+  result = _IO_getc_unlocked (fp);
+  funlockfile (fp);
+  return result;
 }
diff --git a/libio/fileno.c b/libio/fileno.c
index fbea4d4995..2dc67149c8 100644
--- a/libio/fileno.c
+++ b/libio/fileno.c
@@ -1,5 +1,5 @@
 /*
-Copyright (C) 1993, 1995 Free Software Foundation
+Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
 
 This file is part of the GNU IO Library.  This library is free
 software; you can redistribute it and/or modify it under the
@@ -36,3 +36,12 @@ fileno (fp)
 
   return _IO_fileno (fp);
 }
+
+#ifdef _IO_MTSAFE_IO
+/* The fileno implementation for libio does not require locking because
+   it only accesses once a single variable and this is already atomic
+   (at least at thread level).  */
+
+weak_alias (fileno_unlocked, fileno)
+weak_alias (fileno_locked, fileno)
+#endif
diff --git a/libio/fputc.c b/libio/fputc.c
index 2339139f72..339861119f 100644
--- a/libio/fputc.c
+++ b/libio/fputc.c
@@ -1,5 +1,5 @@
 /*
-Copyright (C) 1993 Free Software Foundation
+Copyright (C) 1993, 1996 Free Software Foundation, Inc.
 
 This file is part of the GNU IO Library.  This library is free
 software; you can redistribute it and/or modify it under the
@@ -30,6 +30,10 @@ fputc (c, fp)
      int c;
      _IO_FILE *fp;
 {
+  int result;
   CHECK_FILE (fp, EOF);
-  return _IO_putc (c, fp);
+  _IO_flockfile (fp);
+  result = _IO_putc_unlocked (c, fp);
+  _IO_funlockfile (fp);
+  return result;
 }
diff --git a/libio/fputc_u.c b/libio/fputc_u.c
new file mode 100644
index 0000000000..211e206605
--- /dev/null
+++ b/libio/fputc_u.c
@@ -0,0 +1,39 @@
+/*
+Copyright (C) 1993, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU IO Library.  This library is free
+software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this library; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+As a special exception, if you link this library with files
+compiled with a GNU compiler to produce an executable, this does not cause
+the resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why
+the executable file might be covered by the GNU General Public License. */
+
+#include "libioP.h"
+#include "stdio.h"
+
+#undef fputc_unlocked
+
+int
+__fputc_unlocked (c, fp)
+     int c;
+     _IO_FILE *fp;
+{
+  CHECK_FILE (fp, EOF);
+  return _IO_putc_unlocked (c, fp);
+}
+
+weak_alias (fputc_unlocked, __fputc_unlocked)
diff --git a/libio/freopen.c b/libio/freopen.c
index 22fa13a697..829af31dc1 100644
--- a/libio/freopen.c
+++ b/libio/freopen.c
@@ -1,5 +1,5 @@
 /*
-Copyright (C) 1993, 1995 Free Software Foundation
+Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
 
 This file is part of the GNU IO Library.  This library is free
 software; you can redistribute it and/or modify it under the
@@ -31,8 +31,12 @@ freopen (filename, mode, fp)
      const char* mode;
      FILE* fp;
 {
+  FILE *result;
   CHECK_FILE (fp, NULL);
   if (!(fp->_flags & _IO_IS_FILEBUF))
     return NULL;
-  return _IO_freopen (filename, mode, fp);
+  flockfile (fp);
+  result = _IO_freopen (filename, mode, fp);
+  funlockfile (fp);
+  return result;
 }
diff --git a/libio/fseek.c b/libio/fseek.c
index 3afc4283e6..5255e9defe 100644
--- a/libio/fseek.c
+++ b/libio/fseek.c
@@ -31,6 +31,10 @@ fseek (fp, offset, whence)
      long int offset;
      int whence;
 {
+  int result;
   CHECK_FILE (fp, -1);
-  return _IO_fseek (fp, offset, whence);
+  flockfile (fp);
+  result = _IO_fseek (fp, offset, whence);
+  funlockfile (fp);
+  return result;
 }
diff --git a/libio/genops.c b/libio/genops.c
index 23a6fdeaea..e5bff7afed 100644
--- a/libio/genops.c
+++ b/libio/genops.c
@@ -465,6 +465,9 @@ DEFUN(_IO_init, (fp, flags),
   fp->_IO_save_end = NULL;
   fp->_markers = NULL;
   fp->_cur_column = 0;
+#ifdef _IO_MTSAFE_IO
+  _IO_mutex_init (fp->_lock);
+#endif
 }
 
 int
@@ -497,6 +500,10 @@ DEFUN(_IO_default_finish, (fp),
       fp->_IO_save_base = NULL;
     }
 
+#ifdef _IO_MTSAFE_IO
+  _IO_mutex_destroy (fp->_lock);
+#endif
+  
   _IO_un_link(fp);
 }
 
diff --git a/libio/getc.c b/libio/getc.c
index 844bca4750..89abc0dac0 100644
--- a/libio/getc.c
+++ b/libio/getc.c
@@ -1,5 +1,5 @@
 /*
-Copyright (C) 1993, 1995 Free Software Foundation
+Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
 
 This file is part of the GNU IO Library.  This library is free
 software; you can redistribute it and/or modify it under the
@@ -28,8 +28,19 @@ the executable file might be covered by the GNU General Public License. */
 #undef getc
 
 int
-getc (stream)
-     FILE *stream;
+getc (fp)
+     FILE *fp;
 {
-  return _IO_getc (stream);
+  int result;
+  CHECK_FILE (fp, EOF);
+  _IO_flockfile (fp);
+  result = _IO_getc_unlocked (fp);
+  _IO_funlockfile (fp);
+  return result;
 }
+
+#ifdef _IO_MTSAFE_IO
+# undef getc_locked
+
+weak_alias (getc_locked, getc)
+#endif
diff --git a/libio/getc_u.c b/libio/getc_u.c
new file mode 100644
index 0000000000..e6491bb944
--- /dev/null
+++ b/libio/getc_u.c
@@ -0,0 +1,38 @@
+/*
+Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU IO Library.  This library is free
+software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this library; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+As a special exception, if you link this library with files
+compiled with a GNU compiler to produce an executable, this does not cause
+the resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why
+the executable file might be covered by the GNU General Public License. */
+
+#include "libioP.h"
+#include "stdio.h"
+
+#undef getc_unlocked
+
+int
+__getc_unlocked (fp)
+     FILE *fp;
+{
+  CHECK_FILE (fp, EOF);
+  return _IO_getc_unlocked (fp);
+}
+
+weak_alias (getc_unlocked, __getc_unlocked)
diff --git a/libio/getchar.c b/libio/getchar.c
index 875bceb83d..fa5c11f731 100644
--- a/libio/getchar.c
+++ b/libio/getchar.c
@@ -1,5 +1,5 @@
 /*
-Copyright (C) 1993 Free Software Foundation
+Copyright (C) 1993, 1996 Free Software Foundation, Inc.
 
 This file is part of the GNU IO Library.  This library is free
 software; you can redistribute it and/or modify it under the
@@ -30,5 +30,15 @@ the executable file might be covered by the GNU General Public License. */
 int
 getchar ()
 {
-  return _IO_getc (stdin);
+  int result;
+  _IO_flockfile (stdin);
+  result = _IO_getc_unlocked (stdin);
+  _IO_funlockfile (stdin);
+  return result;
 }
+
+#ifdef _IO_MTSAFE_IO
+# undef getchar_locked
+
+weak_alias (getchar_locked, getchar)
+#endif
diff --git a/libio/getchar_u.c b/libio/getchar_u.c
new file mode 100644
index 0000000000..40cfbf6625
--- /dev/null
+++ b/libio/getchar_u.c
@@ -0,0 +1,36 @@
+/*
+Copyright (C) 1993, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU IO Library.  This library is free
+software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this library; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+As a special exception, if you link this library with files
+compiled with a GNU compiler to produce an executable, this does not cause
+the resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why
+the executable file might be covered by the GNU General Public License. */
+
+#include "libioP.h"
+#include "stdio.h"
+
+#undef getchar_unlocked
+
+int
+__getchar_unlocked ()
+{
+  return _IO_getc_unlocked (stdin);
+}
+
+weak_alias (getchar_unlocked, __getchar_unlocked)
diff --git a/libio/iofclose.c b/libio/iofclose.c
index c797d86fd8..e5cae966fd 100644
--- a/libio/iofclose.c
+++ b/libio/iofclose.c
@@ -35,6 +35,7 @@ _IO_fclose (fp)
 
   CHECK_FILE(fp, EOF);
 
+  _IO_flockfile (fp);
   if (fp->_IO_file_flags & _IO_IS_FILEBUF)
     status = _IO_file_close_it (fp);
   else
@@ -45,6 +46,7 @@ _IO_fclose (fp)
       fp->_IO_file_flags = 0;
       free(fp);
     }
+  _IO_funlockfile (fp);
   return status;
 }
 
diff --git a/libio/iofflush.c b/libio/iofflush.c
index 1f549505c5..6fe2d5262d 100644
--- a/libio/iofflush.c
+++ b/libio/iofflush.c
@@ -32,9 +32,17 @@ _IO_fflush (fp)
     return _IO_flush_all ();
   else
     {
+      int result;
+      _IO_flockfile (fp);
       CHECK_FILE (fp, EOF);
-      return _IO_SYNC (fp) ? EOF : 0;
+      result = _IO_SYNC (fp) ? EOF : 0;
+      _IO_funlockfile (fp);
+      return result;
     }
 }
 
 weak_alias (_IO_fflush, fflush)
+
+#ifdef _IO_MTSAFE_IO
+weak_alias (_IO_fflush, fflush_locked)
+#endif
diff --git a/libio/iofflush_u.c b/libio/iofflush_u.c
new file mode 100644
index 0000000000..b7a91952b4
--- /dev/null
+++ b/libio/iofflush_u.c
@@ -0,0 +1,41 @@
+/*
+Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the GNU IO Library.  This library is free
+software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this library; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+As a special exception, if you link this library with files
+compiled with a GNU compiler to produce an executable, this does not cause
+the resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why
+the executable file might be covered by the GNU General Public License. */
+
+#include "libioP.h"
+
+int
+_IO_fflush_unlocked (fp)
+     register _IO_FILE *fp;
+{
+  if (fp == NULL)
+    return _IO_flush_all ();
+  else
+    {
+      CHECK_FILE (fp, EOF);
+      return _IO_SYNC (fp) ? EOF : 0;
+    }
+}
+
+weak_alias (_IO_fflush_unlocked, fflush_unlocked)
+
diff --git a/libio/iofgetpos.c b/libio/iofgetpos.c
index bc2215fc01..50014765f9 100644
--- a/libio/iofgetpos.c
+++ b/libio/iofgetpos.c
@@ -33,7 +33,9 @@ _IO_fgetpos (fp, posp)
 {
   _IO_fpos_t pos;
   CHECK_FILE (fp, EOF);
+  _IO_flockfile (fp);
   pos = _IO_seekoff (fp, 0, _IO_seek_cur, 0);
+  _IO_funlockfile (fp);
   if (pos == _IO_pos_BAD)
     {
 #ifdef EIO
diff --git a/libio/iofgets.c b/libio/iofgets.c
index a9f161dce8..88d4bd518e 100644
--- a/libio/iofgets.c
+++ b/libio/iofgets.c
@@ -31,14 +31,21 @@ _IO_fgets (buf, n, fp)
      _IO_FILE* fp;
 {
   _IO_size_t count;
+  char *result;
   CHECK_FILE (fp, NULL);
   if (n <= 0)
     return NULL;
+  _IO_flockfile (fp);
   count = _IO_getline (fp, buf, n - 1, '\n', 1);
   if (count == 0 || (fp->_IO_file_flags & _IO_ERR_SEEN))
-    return NULL;
-  buf[count] = 0;
-  return buf;
+    result = NULL;
+  else
+    {
+      buf[count] = '\0';
+      result = buf;
+    }
+  _IO_funlockfile (fp);
+  return result;
 }
 
 weak_alias (_IO_fgets, fgets)
diff --git a/libio/iofputs.c b/libio/iofputs.c
index 62bc981e1d..3359515ac8 100644
--- a/libio/iofputs.c
+++ b/libio/iofputs.c
@@ -1,5 +1,5 @@
 /*
-Copyright (C) 1993 Free Software Foundation
+Copyright (C) 1993, 1996 Free Software Foundation, Inc.
 
 This file is part of the GNU IO Library.  This library is free
 software; you can redistribute it and/or modify it under the
@@ -31,10 +31,15 @@ _IO_fputs (str, fp)
       _IO_FILE *fp;
 {
   _IO_size_t len = strlen (str);
+  int result;
   CHECK_FILE (fp, EOF);
-  if (_IO_sputn( fp, str, len) != len)
-    return EOF;
-  return 1;
+  _IO_flockfile (fp);
+  if (_IO_sputn (fp, str, len) != len)
+    result = EOF;
+  else
+    result = 1;
+  _IO_funlockfile (fp);
+  return result;
 }
 
 weak_alias (_IO_fputs, fputs)
diff --git a/libio/iofread.c b/libio/iofread.c
index babe2c54cc..bad94ca17b 100644
--- a/libio/iofread.c
+++ b/libio/iofread.c
@@ -36,7 +36,9 @@ _IO_fread (buf, size, count, fp)
   CHECK_FILE (fp, 0);
   if (bytes_requested == 0)
     return 0;
+  _IO_flockfile (fp);
   bytes_read = _IO_sgetn (fp, (char *) buf, bytes_requested);
+  _IO_funlockfile (fp);
   return bytes_requested == bytes_read ? count : bytes_read / size;
 }
 weak_alias (_IO_fread, fread)
diff --git a/libio/iofsetpos.c b/libio/iofsetpos.c
index 72db3b1fa0..c8897522d6 100644
--- a/libio/iofsetpos.c
+++ b/libio/iofsetpos.c
@@ -30,7 +30,9 @@ _IO_fsetpos (fp, posp)
      _IO_FILE* fp;
      const _IO_fpos_t *posp;
 {
+  int result;
   CHECK_FILE (fp, EOF);
+  _IO_flockfile (fp);
   if (_IO_seekpos (fp, *posp, _IOS_INPUT|_IOS_OUTPUT) == _IO_pos_BAD)
     {
       /*ANSI explicily requires setting errno to a positive value on failure.*/
@@ -38,9 +40,12 @@ _IO_fsetpos (fp, posp)
       if (errno == 0)
 	errno = EIO;
 #endif
-      return EOF;
+      result = EOF;
     }
-  return 0;
+  else
+    result = 0;
+  _IO_funlockfile (fp);
+  return result;
 }
 
 weak_alias (_IO_fsetpos, fsetpos)
diff --git a/libio/ioftell.c b/libio/ioftell.c
index 8af2ce7f1f..d49f8c3553 100644
--- a/libio/ioftell.c
+++ b/libio/ioftell.c
@@ -32,7 +32,9 @@ _IO_ftell (fp)
 {
   _IO_pos_t pos;
   CHECK_FILE (fp, -1L);
+  _IO_flockfile (fp);
   pos = _IO_seekoff (fp, 0, _IO_seek_cur, 0);
+  _IO_funlockfile (fp);
   if (pos == _IO_pos_BAD)
     {
 #ifdef EIO
diff --git a/libio/iofwrite.c b/libio/iofwrite.c
index b8f02f2dd0..0bbeef2646 100644
--- a/libio/iofwrite.c
+++ b/libio/iofwrite.c
@@ -36,7 +36,9 @@ _IO_fwrite (buf, size, count, fp)
   CHECK_FILE (fp, 0);
   if (request == 0)
     return 0;
+  _IO_flockfile (fp);
   written = _IO_sputn (fp, (const char *) buf, request);
+  _IO_funlockfile (fp);
   /* Many traditional implementations return 0 if size==0 && count > 0,
      but ANSI seems to require us to return count in this case. */
   if (written == request)
diff --git a/libio/iogetdelim.c b/libio/iogetdelim.c
index ecb360b1f5..1d14551615 100644
--- a/libio/iogetdelim.c
+++ b/libio/iogetdelim.c
@@ -42,6 +42,7 @@ _IO_getdelim (lineptr, n, delimiter, fp)
       int delimiter;
       _IO_FILE *fp;
 {
+  int result;
   register _IO_ssize_t cur_len = 0;
   _IO_ssize_t len;
 
@@ -53,22 +54,32 @@ _IO_getdelim (lineptr, n, delimiter, fp)
       return -1;
     }
   CHECK_FILE (fp, -1);
-  if (_IO_ferror (fp))
-    return -1;
+  _IO_flockfile (fp);
+  if (_IO_ferror_unlocked (fp))
+    {
+      result = -1;
+      goto unlock_return;
+    }
 
   if (*lineptr == NULL || *n == 0)
     {
       *n = 120;
       *lineptr = (char *) malloc (*n);
       if (*lineptr == NULL)
-	return -1;
+	{
+	  result = -1;
+	  goto unlock_return;
+	}
     }
 
   len = fp->_IO_read_end - fp->_IO_read_ptr;
   if (len <= 0)
     {
       if (__underflow (fp) == EOF)
-	return -1;
+	{
+	  result = -1;
+	  goto unlock_return;
+	}
       len = fp->_IO_read_end - fp->_IO_read_ptr;
     }
 
@@ -88,7 +99,10 @@ _IO_getdelim (lineptr, n, delimiter, fp)
 	  *n = needed;
 	  *lineptr = (char *) realloc (*lineptr, needed);
 	  if (*lineptr == NULL)
-	    return -1;
+	    {
+	      result = -1;
+	      goto unlock_return;
+	    }
 	}
       memcpy (*lineptr + cur_len, (void *) fp->_IO_read_ptr, len);
       fp->_IO_read_ptr += len;
@@ -98,7 +112,11 @@ _IO_getdelim (lineptr, n, delimiter, fp)
       len = fp->_IO_read_end - fp->_IO_read_ptr;
     }
   (*lineptr)[cur_len] = '\0';
-  return cur_len;
+  result = cur_len;
+
+unlock_return:
+  _IO_funlockfile (fp);
+  return result;
 }
 
 weak_alias (_IO_getdelim, __getdelim)
diff --git a/libio/iogets.c b/libio/iogets.c
index 419342fb12..352e80244b 100644
--- a/libio/iogets.c
+++ b/libio/iogets.c
@@ -30,7 +30,10 @@ _IO_gets (buf)
      char* buf;
 {
   _IO_size_t count;
-  int ch = _IO_getc (_IO_stdin);
+  int ch;
+
+  _IO_flockfile (_IO_stdin);
+  ch = _IO_getc_unlocked (_IO_stdin);
   if (ch == EOF)
     return NULL;
   if (ch == '\n')
@@ -42,6 +45,7 @@ _IO_gets (buf)
       if (_IO_stdin->_IO_file_flags & _IO_ERR_SEEN)
 	return NULL;
     }
+  _IO_funlockfile (_IO_stdin);
   buf[count] = 0;
   return buf;
 }
diff --git a/libio/ioputs.c b/libio/ioputs.c
index 129da1d821..6c52f7521c 100644
--- a/libio/ioputs.c
+++ b/libio/ioputs.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993 Free Software Foundation
+/* Copyright (C) 1993, 1996 Free Software Foundation, Inc.
 
 This file is part of the GNU IO Library.  This library is free
 software; you can redistribute it and/or modify it under the
@@ -28,11 +28,15 @@ int
 _IO_puts (str)
       const char *str;
 {
+  int result;
   _IO_size_t len = strlen (str);
-  if (_IO_sputn (_IO_stdout, str, len) != len)
-    return EOF;
-  if (_IO_putc ('\n', _IO_stdout) == EOF)
-    return EOF;
-  return len+1;
+  _IO_flockfile (fp);
+  if (_IO_sputn (_IO_stdout, str, len) == len
+      && _IO_putc_unlocked ('\n', _IO_stdout) != EOF)
+    result = len + 1;
+  else
+    result = EOF;
+  _IO_funlockfile (fp);
+  return result;
 }
 weak_alias (_IO_puts, puts)
diff --git a/libio/iosetbuffer.c b/libio/iosetbuffer.c
index 0ad38111d6..d3fc7e5917 100644
--- a/libio/iosetbuffer.c
+++ b/libio/iosetbuffer.c
@@ -1,5 +1,5 @@
 /*
-Copyright (C) 1993 Free Software Foundation
+Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
 
 This file is part of the GNU IO Library.  This library is free
 software; you can redistribute it and/or modify it under the
@@ -31,8 +31,12 @@ _IO_setbuffer (fp, buf, size)
      _IO_size_t size;
 {
   CHECK_FILE (fp, );
+  _IO_flockfile (fp);
   fp->_flags &= ~_IO_LINE_BUF;
   if (!buf)
     size = 0;
   (void) _IO_SETBUF (fp, buf, size);
+  _IO_funlockfile (fp);
 }
+
+weak_alias (_IO_setbuffer, setbuffer)
diff --git a/libio/iosetvbuf.c b/libio/iosetvbuf.c
index 396ef2fb14..6d4bcff2bc 100644
--- a/libio/iosetvbuf.c
+++ b/libio/iosetvbuf.c
@@ -35,7 +35,9 @@ _IO_setvbuf (fp, buf, mode, size)
      int mode;
      _IO_size_t size;
 {
+  int result;
   CHECK_FILE (fp, EOF);
+  _IO_flockfile (fp);
   switch (mode)
     {
     case _IOFBF:
@@ -58,25 +60,36 @@ _IO_setvbuf (fp, buf, mode, size)
 		 A possibly cleaner alternative would be to add an
 		 extra flag, but then flags are a finite resource.  */
 	      if (_IO_DOALLOCATE (fp) < 0)
-		return EOF;
+		{
+		  result = EOF;
+		  goto unlock_return;
+		}
 	      fp->_IO_file_flags &= ~_IO_LINE_BUF;
 	    }
-	  return 0;
+	  result = 0;
+	  goto unlock_return;
 	}
       break;
     case _IOLBF:
       fp->_IO_file_flags |= _IO_LINE_BUF;
       if (buf == NULL)
-	return 0;
+	{
+	  result = 0;
+	  goto unlock_return;
+	}
       break;
     case _IONBF:
       buf = NULL;
       size = 0;
       break;
     default:
-      return EOF;
+      result = EOF;
+      goto unlock_return;
     }
-  return _IO_SETBUF (fp, buf, size) == NULL ? EOF : 0;
+  result = _IO_SETBUF (fp, buf, size) == NULL ? EOF : 0;
+unlock_return:
+  _IO_funlockfile (fp);
+  return result;
 }
 
 weak_alias (_IO_setvbuf, setvbuf)
diff --git a/libio/ioungetc.c b/libio/ioungetc.c
index 1a6988ef16..c1237b5f9b 100644
--- a/libio/ioungetc.c
+++ b/libio/ioungetc.c
@@ -1,5 +1,5 @@
 /*
-Copyright (C) 1993 Free Software Foundation
+Copyright (C) 1993, 1996 Free Software Foundation, Inc.
 
 This file is part of the GNU IO Library.  This library is free
 software; you can redistribute it and/or modify it under the
@@ -29,10 +29,14 @@ _IO_ungetc (c, fp)
      int c;
      _IO_FILE *fp;
 {
+  int result;
   CHECK_FILE (fp, EOF);
   if (c == EOF)
     return EOF;
-  return _IO_sputbackc (fp, (unsigned char) c);
+  _IO_flockfile (fp);
+  result = _IO_sputbackc (fp, (unsigned char) c);
+  _IO_funlockfile (fp);
+  return result;
 }
 
 weak_alias (_IO_ungetc, ungetc)
diff --git a/libio/iovsprintf.c b/libio/iovsprintf.c
index 182c4ff306..2c5d77503d 100644
--- a/libio/iovsprintf.c
+++ b/libio/iovsprintf.c
@@ -37,7 +37,7 @@ _IO_vsprintf (string, format, args)
   _IO_JUMPS ((_IO_FILE *) &sf) = &_IO_str_jumps;
   _IO_str_init_static ((_IO_FILE *) &sf, string, -1, string);
   ret = _IO_vfprintf ((_IO_FILE *) &sf, format, args);
-  _IO_putc('\0', (_IO_FILE *) &sf);
+  _IO_putc_unlocked ('\0', (_IO_FILE *) &sf);
   return ret;
 }
 
diff --git a/libio/libio.h b/libio/libio.h
index 405036dfb6..fce8a77bf7 100644
--- a/libio/libio.h
+++ b/libio/libio.h
@@ -148,15 +148,13 @@ typedef struct
   int (*close) __P ((struct _IO_FILE *));
 } _IO_cookie_io_functions_t;
 
+/* Handle lock.  */
+#ifdef _IO_MTSAFE_IO
+typedef pthread_mutex_t _IO_lock_t;
+#else
+typedef void _IO_lock_t;
+#endif
 
-/* The reentrant version of the libio implementation needs a semaphore for
-   each _IO_FILE struture.  Because we don't know how the semaphore
-   will be implemented we try to be very general.  */
-struct _IO_lock_t {
-  void *ptr;
-  short int field1;
-  short int field2;
-};
 
 /* A streammarker remembers a position in a buffer. */
 
@@ -217,7 +215,7 @@ struct _IO_FILE {
 
   /*  char* _save_gptr;  char* _save_egptr; */
 
-  struct _IO_lock_t _IO_lock;
+  _IO_lock_t *_lock;
 };
 
 #ifndef __cplusplus
@@ -238,26 +236,38 @@ extern int __underflow __P((_IO_FILE*));
 extern int __uflow __P((_IO_FILE*));
 extern int __overflow __P((_IO_FILE*, int));
 
-#define _IO_getc(_fp) \
+#define _IO_getc_unlocked(_fp) \
        ((_fp)->_IO_read_ptr >= (_fp)->_IO_read_end ? __uflow(_fp) \
 	: *(unsigned char*)(_fp)->_IO_read_ptr++)
-#define _IO_peekc(_fp) \
+#define _IO_peekc_unlocked(_fp) \
        ((_fp)->_IO_read_ptr >= (_fp)->_IO_read_end \
 	  && __underflow(_fp) == EOF ? EOF \
 	: *(unsigned char*)(_fp)->_IO_read_ptr)
 
-#define _IO_putc(_ch, _fp) \
+#define _IO_putc_unlocked(_ch, _fp) \
    (((_fp)->_IO_write_ptr >= (_fp)->_IO_write_end) \
     ? __overflow(_fp, (unsigned char)(_ch)) \
     : (unsigned char)(*(_fp)->_IO_write_ptr++ = (_ch)))
 
-#define _IO_feof(__fp) (((__fp)->_flags & _IO_EOF_SEEN) != 0)
-#define _IO_ferror(__fp) (((__fp)->_flags & _IO_ERR_SEEN) != 0)
+#define _IO_feof_unlocked(__fp) (((__fp)->_flags & _IO_EOF_SEEN) != 0)
+#define _IO_ferror_unlocked(__fp) (((__fp)->_flags & _IO_ERR_SEEN) != 0)
 
 /* This one is for Emacs. */
 #define _IO_PENDING_OUTPUT_COUNT(_fp)	\
 	((_fp)->_IO_write_ptr - (_fp)->_IO_write_base)
 
+extern int _IO_getc_locked __P ((_IO_FILE *));
+extern int _IO_putc_locked __P ((int, _IO_FILE *));
+
+extern void _IO_flockfile __P ((_IO_FILE *));
+extern void _IO_funlockfile __P ((_IO_FILE *));
+
+#if !defined(_REENTRANT) && !defined(_THREAD_SAFE)
+# define _IO_flockfile(FILE) /**/
+# define _IO_funlockfile(FILE) /**/
+#endif /* _REENTRANT || _THREAD_SAFE */
+
+
 extern int _IO_vfscanf __P((_IO_FILE*, const char*, _IO_va_list, int*));
 extern int _IO_vfprintf __P((_IO_FILE*, const char*, _IO_va_list));
 extern _IO_ssize_t _IO_padn __P((_IO_FILE *, int, _IO_ssize_t));
diff --git a/libio/putc.c b/libio/putc.c
index 675fe5eedf..23595ab7b5 100644
--- a/libio/putc.c
+++ b/libio/putc.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1995, 1996 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,9 +22,20 @@ Cambridge, MA 02139, USA.  */
 #undef putc
 
 int
-putc (c, stream)
+putc (c, fp)
      int c;
-     _IO_FILE *stream;
+     _IO_FILE *fp;
 {
-  return _IO_putc (c, stream);
+  int result;
+  CHECK_FILE (fp, EOF);
+  _IO_flockfile (fp);
+  result = _IO_putc_unlocked (c, fp);
+  _IO_funlockfile (fp);
+  return result;
 }
+
+#ifdef _IO_MTSAFE_IO
+# undef putc_locked
+
+weak_alias (putc_locked, putc)
+#endif
diff --git a/libio/putc_u.c b/libio/putc_u.c
new file mode 100644
index 0000000000..18bbd491d8
--- /dev/null
+++ b/libio/putc_u.c
@@ -0,0 +1,31 @@
+/* Copyright (C) 1991, 1995, 1996 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
+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., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include "libioP.h"
+#include "stdio.h"
+
+#undef putc_unlocked
+
+int
+putc_unlocked (c, fp)
+     int c;
+     _IO_FILE *fp;
+{
+  CHECK_FILE (fp, EOF);
+  return _IO_putc_unlocked (c, fp);
+}
diff --git a/libio/putchar.c b/libio/putchar.c
index bf10da9468..d4d52f60d2 100644
--- a/libio/putchar.c
+++ b/libio/putchar.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1995, 1996 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
@@ -25,5 +25,15 @@ int
 putchar (c)
      int c;
 {
-  return _IO_putc (c, stdout);
+  int result;
+  _IO_flockfile (_IO_stdout);
+  result = _IO_putc_unlocked (c, _IO_stdout);
+  _IO_funlockfile (_IO_stdout);
+  return result;
 }
+
+#ifdef _IO_MTSAFE_IO
+# undef putchar_locked
+
+weak_alias (putchar_locked, putchar)
+#endif
diff --git a/libio/putchar_u.c b/libio/putchar_u.c
new file mode 100644
index 0000000000..d29652aadc
--- /dev/null
+++ b/libio/putchar_u.c
@@ -0,0 +1,30 @@
+/* Copyright (C) 1991, 1995, 1996 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
+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., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include "libioP.h"
+#include "stdio.h"
+
+#undef putchar_unlocked
+
+int
+putchar_unlocked (c)
+     int c;
+{
+  CHECK_FILE (fp, EOF);
+  return _IO_putc_unlocked (c, fp);
+}
diff --git a/libio/rewind.c b/libio/rewind.c
index dfb02cc3f2..2f57e0de83 100644
--- a/libio/rewind.c
+++ b/libio/rewind.c
@@ -29,5 +29,7 @@ rewind (fp)
      _IO_FILE* fp;
 {
   CHECK_FILE (fp, );
+  _IO_flockfile (fp);
   _IO_rewind (fp);
+  _IO_funlockfile (fp);
 }
diff --git a/libio/stdio.h b/libio/stdio.h
index e68b6ceeff..bd271ce1fb 100644
--- a/libio/stdio.h
+++ b/libio/stdio.h
@@ -161,6 +161,7 @@ extern int pclose __P ((FILE*));
 #ifdef __USE_GNU
 extern _IO_ssize_t getdelim __P ((char **, size_t *, int, FILE*));
 extern _IO_ssize_t getline __P ((char **, size_t *, FILE *));
+extern _IO_ssize_t __getline __P ((char **, size_t *, FILE *));
 
 extern int snprintf __P ((char *, size_t, __const char *, ...));
 extern int __snprintf __P ((char *, size_t, __const char *, ...));
@@ -178,11 +179,6 @@ extern FILE *open_memstream __P ((char **__bufloc, size_t *__sizeloc));
 extern int __underflow __P ((struct _IO_FILE*));
 extern int __overflow __P ((struct _IO_FILE*, int));
 
-#define getc(fp) _IO_getc (fp)
-#define putc(c, fp) _IO_putc (c, fp)
-#define putchar(c) putc (c, stdout)
-#define getchar() getc (stdin)
-
 #ifdef  __USE_BSD
 extern int sys_nerr;
 extern const char *const sys_errlist[];
@@ -192,8 +188,49 @@ extern int _sys_nerr;
 extern const char *const _sys_errlist[];
 #endif
 
+/* Handle locking of streams.  */
+#if defined(_REENTRANT) || defined(_THREAD_SAFE)
+extern void clearerr_unlocked __P ((FILE *));
+extern void fileno_unlocked __P ((FILE *));
+extern void flockfile __P ((FILE *));
+extern void funlockfile __P ((FILE *));
+extern int fclose_unlocked __P ((FILE *));
+extern int fflush_unlocked __P ((FILE *));
+extern size_t fread_unlocked __P ((void *, size_t, size_t, FILE *));
+extern size_t fwrite_unlocked __P ((const void *, size_t, size_t, FILE *));
+
+# define getc_unlocked(fp) _IO_getc_unlocked (fp)
+# define getc_locked(fp) _IO_fgetc (fp)
+# define getchar_unlocked() getc_unlocked (stdin)
+# define getchar_locked() getc_locked (stdin)
+# define getc(fp) getc_locked (fp)
+
+# define putc_unlocked(c, fp) _IO_putc_unlocked (c, fp)
+# define putc_locked(c, fp) _IO_putc_locked (c, fp)
+# define putchar_unlocked(c) putc_unlocked (c, stdout)
+# define putchar_locked(c) putc_locked (c, stdout)
+# define putc(c, fp) putc_locked (c, fp)
+
+# define feof_unlocked(fp) _IO_feof_unlocked (fp)
+# define ferror_unlocked(fp) _IO_ferror_unlocked (fp)
+
+#else
+# define getc(fp) _IO_getc_unlocked (fp)
+# define putc(c, fp) _IO_putc_unlocked (c, fp)
+
+#endif /* _REENTRANT || _THREAD_SAFE */
+
+#define flockfile(FILE) _IO_flockfile (FILE)
+#define funlockfile(FILE) _IO_funlockfile (FILE)
+
+#define putchar(c) putc (c, stdout)
+#define getchar() getc (stdin)
+
+
 #ifdef __cplusplus
 }
 #endif
 
+
+
 #endif /* !_STDIO_H */
diff --git a/locale/programs/config.h b/locale/programs/config.h
index 6c67813f93..96d9281ce3 100644
--- a/locale/programs/config.h
+++ b/locale/programs/config.h
@@ -23,9 +23,6 @@
 #define HAVE_VPRINTF 1
 
 
-typedef int wint_t;
-
-
 #include_next <config.h>
 
 #endif
diff --git a/locale/programs/ld-collate.c b/locale/programs/ld-collate.c
index 6643ae85c8..629df90ced 100644
--- a/locale/programs/ld-collate.c
+++ b/locale/programs/ld-collate.c
@@ -28,7 +28,7 @@ Boston, MA 02111-1307, USA.  */
 #include <obstack.h>
 #include <stdlib.h>
 #include <string.h>
-#include <wcstr.h>
+#include <wchar.h>
 
 #include "localeinfo.h"
 #include "locales.h"
@@ -36,7 +36,7 @@ Boston, MA 02111-1307, USA.  */
 #include "stringtrans.h"
 
 /* Uncomment the following line in the production version.  */
-/* define NDEBUG 1 */
+/* #define NDEBUG 1 */
 #include <assert.h>
 
 
diff --git a/manual/time.texi b/manual/time.texi
index eae3011e4c..c8ca7e8118 100644
--- a/manual/time.texi
+++ b/manual/time.texi
@@ -672,11 +672,20 @@ The second as a decimal number.
 
 @item %U
 The week number of the current year as a decimal number, starting with
-the first Sunday as the first day of the first week.
+the first Sunday as the first day of the first week.  All days preceding
+the first Sunday in the year are considered to be in week @code{0}.
+
+@item %V
+The week number of the current year as a decimal number, starting with
+the first Monday as the first day of the first week.  If the week
+containing January 1 has four or more days in the new year it is
+considered to be week @code{1}.  Otherwise it is week @code{53} of the
+previous year.  This is standardized in @w{ISO 8601:1988}.
 
 @item %W
 The week number of the current year as a decimal number, starting with
-the first Monday as the first day of the first week.
+the first Monday as the first day of the first week.  All days preceding
+the first Monday in the year are considered to be in week @code{0}.
 
 @item %w
 The day of the week as a decimal number, Sunday being @code{0}.
diff --git a/misc/getusershell.c b/misc/getusershell.c
index 6782c3efe9..3816e1e784 100644
--- a/misc/getusershell.c
+++ b/misc/getusershell.c
@@ -49,9 +49,9 @@ static char sccsid[] = "@(#)getusershell.c	8.1 (Berkeley) 6/4/93";
  * /etc/shells.
  */
 
-static char *okshells[] = { _PATH_BSHELL, _PATH_CSHELL, NULL };
-static char **curshell, **shells, *strings;
-static char **initshells __P((void));
+static const char *okshells[] = { _PATH_BSHELL, _PATH_CSHELL, NULL };
+static const char **curshell, **shells, *strings;
+static const char **initshells __P((void));
 
 /*
  * Get a list of shells from _PATH_SHELLS, if it exists.
@@ -59,14 +59,14 @@ static char **initshells __P((void));
 char *
 getusershell()
 {
-	char *ret;
+	const char *ret;
 
 	if (curshell == NULL)
 		curshell = initshells();
 	ret = *curshell;
 	if (ret != NULL)
 		curshell++;
-	return (ret);
+	return (char *) ret;	/* Cast away `const' for history reasons.  */
 }
 
 void
@@ -89,7 +89,7 @@ setusershell()
 	curshell = initshells();
 }
 
-static char **
+static const char **
 initshells()
 {
 	register char **sp, *cp;
@@ -97,10 +97,10 @@ initshells()
 	struct stat statb;
 
 	if (shells != NULL)
-		free(shells);
+		free((char *) shells);
 	shells = NULL;
 	if (strings != NULL)
-		free(strings);
+		free((char *) strings);
 	strings = NULL;
 	if ((fp = fopen(_PATH_SHELLS, "r")) == NULL)
 		return (okshells);
@@ -119,8 +119,8 @@ initshells()
 		strings = NULL;
 		return (okshells);
 	}
-	sp = shells;
-	cp = strings;
+	sp = (char *) shells;
+	cp = (char *) strings;
 	while (fgets(cp, statb.st_size - (cp - strings), fp) != NULL) {
 		while (*cp != '#' && *cp != '/' && *cp != '\0')
 			cp++;
diff --git a/resolv/gethnamaddr.c b/resolv/gethnamaddr.c
index 87b4db1a6f..41be4fc10d 100644
--- a/resolv/gethnamaddr.c
+++ b/resolv/gethnamaddr.c
@@ -397,9 +397,12 @@ struct hostent *
 gethostbyname(name)
 	const char *name;
 {
+  /* Moved #if line to here because declararing HP would lead to a
+     warining.  --drepper@gnu  */
+#if defined(AF_INET6) && defined(RES_TRY_INET6)
 	struct hostent *hp;
 
-#if defined(AF_INET6) && defined(RES_TRY_INET6)
+/* #if defined(AF_INET6) && defined(RES_TRY_INET6) */
 	if (_res.options & RES_TRY_INET6) {
 		hp = gethostbyname2(name, AF_INET6);
 		if (hp)
diff --git a/stdio-common/_itoa.c b/stdio-common/_itoa.c
index f85b15b030..9d77b39005 100644
--- a/stdio-common/_itoa.c
+++ b/stdio-common/_itoa.c
@@ -260,9 +260,11 @@ _itoa (value, buflim, base, upper_case)
 	   Optimize for frequent cases of 32 bit numbers.  */
 	if ((mp_limb_t) (value >> 32) >= 1)
 	  {
+#if UDIV_TIME > 2 * UMUL_TIME || UDIV_NEEDS_NORMALIZATION
 	    int big_normalization_steps = brec->big.normalization_steps;
-	    mp_limb_t big_base_norm = brec->big.base << big_normalization_steps;
-
+	    mp_limb_t big_base_norm
+	      = brec->big.base << big_normalization_steps;
+#endif
 	    if ((mp_limb_t) (value >> 32) >= brec->big.base)
 	      {
 		mp_limb_t x1hi, x1lo, r;
diff --git a/stdio-common/printf_fp.c b/stdio-common/printf_fp.c
index 237deb99a5..9e14b67509 100644
--- a/stdio-common/printf_fp.c
+++ b/stdio-common/printf_fp.c
@@ -54,7 +54,7 @@ Cambridge, MA 02139, USA.  */
 /* We use this file GNU C library and GNU I/O library.	So make
    names equal.	 */
 #  undef putc
-#  define putc(c, f) _IO_putc (c, f)
+#  define putc(c, f) _IO_putc_unlocked (c, f)
 #  define size_t     _IO_size_t
 #  define FILE	     _IO_FILE
 #else	/* ! USE_IN_LIBIO */
diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c
index 9b24574558..cde7496585 100644
--- a/stdio-common/vfprintf.c
+++ b/stdio-common/vfprintf.c
@@ -62,14 +62,14 @@ ssize_t __printf_pad __P ((FILE *, char pad, size_t n));
 # define ISDIGIT(Ch)	iswdigit (Ch)
 
 # ifdef USE_IN_LIBIO
-# define PUT(F, S, N)	_IO_sputn (F, S, N)
-# define PAD(Padchar)							      \
+#  define PUT(F, S, N)	_IO_sputn (F, S, N)
+#  define PAD(Padchar)							      \
   if (width > 0)							      \
     done += _IO_wpadn (s, Padchar, width)
 # else
 #  define PUTC(C, F)	wputc (C, F)
 ssize_t __wprintf_pad __P ((FILE *, wchar_t pad, size_t n));
-# define PAD(Padchar)							      \
+#  define PAD(Padchar)							      \
   if (width > 0)							      \
     { if (__wprintf_pad (s, Padchar, width) == -1)			      \
 	return -1; else done += width; }
@@ -83,7 +83,7 @@ ssize_t __wprintf_pad __P ((FILE *, wchar_t pad, size_t n));
 #ifdef USE_IN_LIBIO
 /* This code is for use in libio.  */
 # include <libioP.h>
-# define PUTC(C, F)	_IO_putc (C, F)
+# define PUTC(C, F)	_IO_putc_unlocked (C, F)
 # define vfprintf	_IO_vfprintf
 # define size_t		_IO_size_t
 # define FILE		_IO_FILE
@@ -102,6 +102,8 @@ ssize_t __wprintf_pad __P ((FILE *, wchar_t pad, size_t n));
 	}								      \
     } while (0)
 # define UNBUFFERED_P(S) ((S)->_IO_file_flags & _IO_UNBUFFERED)
+# define flockfile(S) _IO_flockfile (S)
+# define fUNlockfile(S) _IO_funlockfile (S)
 #else /* ! USE_IN_LIBIO */
 /* This code is for use in the GNU C library.  */
 # include <stdio.h>
@@ -801,13 +803,19 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
   /* Find the first format specifier.  */
   f = lead_str_end = find_spec (format, &mbstate);
 
+  /* Lock stream.  */
+  flockfile (s);
+  
   /* Write the literal text before the first format.  */
   outstring ((const UCHAR_T *) format,
 	     lead_str_end - (const UCHAR_T *) format);
 
   /* If we only have to print a simple string, return now.  */
   if (*f == L_('\0'))
-    return done;
+    {
+      funlockfile (s);
+      return done;
+    }
 
   /* Process whole format string.  */
   do
@@ -972,8 +980,11 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
 
 	LABEL (form_unknown):
 	  if (spec == L_('\0'))
-	    /* The format string ended before the specifier is complete.  */
-	    return -1;
+	    {
+	      /* The format string ended before the specifier is complete.  */
+	      funlockfile (s);
+	      return -1;
+	    }
 
 	  /* If we are in the fast loop force entering the complicated
 	     one.  */
@@ -988,6 +999,9 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
     }
   while (*f != L_('\0'));
 
+  /* Unlock stream.  */
+  funlockfile (s);
+  
   /* We processed the whole format without any positional parameters.  */
   return done;
 
@@ -1230,7 +1244,10 @@ do_positional:
 	      /* If an error occured we don't have information about #
 		 of chars.  */
 	      if (function_done < 0)
-		return -1;
+		{
+		  funlockfile (s);
+		  return -1;
+		}
 
 	      done += function_done;
 	    }
@@ -1244,6 +1261,9 @@ do_positional:
       }
   }
 
+  /* Unlock the stream.  */
+  funlockfile (s);
+  
   return done;
 }
 
@@ -1378,7 +1398,7 @@ _IO_helper_overflow (_IO_FILE *s, int c)
       _IO_size_t written = _IO_sputn (target, s->_IO_write_base, used);
       s->_IO_write_ptr -= written;
     }
-  return _IO_putc (c, s);
+  return PUTC (c, s);
 }
 
 static const struct _IO_jump_t _IO_helper_jumps =
diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c
index bc7acd60de..4b4dd119ca 100644
--- a/stdio-common/vfscanf.c
+++ b/stdio-common/vfscanf.c
@@ -54,38 +54,59 @@ Cambridge, MA 02139, USA.  */
 
 # define va_list	_IO_va_list
 # define ungetc(c, s)	_IO_ungetc (c, s)
-# define inchar()	((c = _IO_getc (s)), (void) ++read_in, c)
-# define conv_error()	return ((void) (errp != NULL && (*errp |= 2)), \
-				(void) (c == EOF || _IO_ungetc (c, s)), done)
-
-# define input_error()	return ((void) (errp != NULL && (*errp |= 1)), \
-				done == 0 ? EOF : done)
-# define memory_error()	return ((void) (errno = ENOMEM), EOF)
-# define ARGCHECK(s, format)						     \
-  do									     \
-    {									     \
-      /* Check file argument for consistence.  */			     \
-      CHECK_FILE (s, -1);						     \
-      if (s->_flags & _IO_NO_READS || format == NULL)			     \
-       {								     \
-         MAYBE_SET_EINVAL;						     \
-         return -1;							     \
-       }								     \
+# define inchar()	((c = _IO_getc_unlocked (s)), (void) ++read_in, c)
+# define conv_error()	do {						      \
+			  if (errp != NULL) *errp |= 2;			      \
+			  if (c != EOF) _IO_ungetc (c, s);		      \
+			  _IO_funlockfile (s);				      \
+			  return done;					      \
+			} while (0)
+# define input_error()	do {						      \
+			  _IO_funlockfile (s);				      \
+			  if (errp != NULL) *errp |= 1;			      \
+			  return done ?: EOF;				      \
+			} while (0)
+# define memory_error()	do {						      \
+			  _IO_funlockfile (s);				      \
+			  errno = ENOMEM;				      \
+			  return EOF;					      \
+			} while (0)
+# define ARGCHECK(s, format)						      \
+  do									      \
+    {									      \
+      /* Check file argument for consistence.  */			      \
+      CHECK_FILE (s, EOF);						      \
+      if (s->_flags & _IO_NO_READS || format == NULL)			      \
+       {								      \
+         MAYBE_SET_EINVAL;						      \
+         return EOF;							      \
+       }								      \
     } while (0)
 #else
 # define inchar()	((c = getc (s)), (void) ++read_in, c)
-# define conv_error()	return ((void) ungetc (c, s), done)
-# define input_error()	return (done == 0 ? EOF : done)
-# define memory_error()	return ((void) (errno = ENOMEM), EOF)
-# define ARGCHECK(s, format)						     \
-  do									     \
-    {									     \
-      /* Check file argument for consistence.  */			     \
-      if (!__validfp (s) || !s->__mode.__read || format == NULL)	     \
-	{								     \
-	  errno = EINVAL;						     \
-	  return -1;							     \
-	}								     \
+# define conv_error()	do {						      \
+			  funlockfile (s);				      \
+			  ungetc (c, s);				      \
+			  return done;					      \
+			} while (0)
+# define input_error()	do {						      \
+			  funlockfile (s);				      \
+			  return done ?: EOF;				      \
+			} while (0)
+# define memory_error()	do {						      \
+			  funlockfile (s);				      \
+			  errno = ENOMEM;				      \
+			  return EOF;					      \
+			} while (0)
+# define ARGCHECK(s, format)						      \
+  do									      \
+    {									      \
+      /* Check file argument for consistence.  */			      \
+      if (!__validfp (s) || !s->__mode.__read || format == NULL)	      \
+	{								      \
+	  errno = EINVAL;						      \
+	  return EOF;							      \
+	}								      \
     } while (0)
 #endif
 
@@ -173,6 +194,9 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
 	      strlen (_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP))) <= 0)
     thousands = (wchar_t) *_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
 
+  /* Lock the stream.  */
+  flockfile (s);
+  
   c = inchar ();
 
   /* Run through the format string.  */
@@ -781,6 +805,9 @@ __vfscanf (FILE *s, const char *format, va_list argptr)
     while (isspace (c))
       (void) inchar ();
 
+  /* Unlock stream.  */
+  funlockfile (s);
+  
   return ((void) (c == EOF || ungetc (c, s)), done);
 }