summary refs log tree commit diff
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>1996-05-29 04:48:04 +0000
committerRoland McGrath <roland@gnu.org>1996-05-29 04:48:04 +0000
commit0200214b288810fc261b0b65c32f7068fcfa9b40 (patch)
treea488a0a435ccf62b0870121b839b08de0d37a9b5
parent215dbbb1508bd6b86211112dd5ddaf9bd2290690 (diff)
downloadglibc-0200214b288810fc261b0b65c32f7068fcfa9b40.tar.gz
glibc-0200214b288810fc261b0b65c32f7068fcfa9b40.tar.xz
glibc-0200214b288810fc261b0b65c32f7068fcfa9b40.zip
Tue May 28 04:38:10 1996 Ulrich Drepper <drepper@cygnus.com>
	* limits.h: Change MB_LEN_MAX to 6.  A 31-bit ISO 10646
	character in UTF-8 encoding has that many bytes.

	* locale/langinfo.h: New element _NL_CTYPE_MB_CUR_MAX.
	* locale/categories.def: Add description of field _NL_CTYPE_MB_CUR_MAX.
	* locale/Makefile (routines): Add mb_cur_max.
	* locale/mb_cur_max.c: New file.  This function gets called
	when the macro MB_CUR_MAX is used.
	* locale/C-ctype.c: Initialize new mb_cur_max field.
	* locale/localeinfo.h: Change magic value because of incompatible
        change.
	* locale/programs/ld-ctype.c: Determine value of mb_cur_max
        according to current character set and write it out with the rest.
	* stdlib/stdlib.h (MB_CUR_MAX): Not constant anymore.  Get value
        according to currently used locale for catefory LC_CTYPE by
        calling the function __ctype_get_mb_cur_max.

Tue May 28 03:27:46 1996  Ulrich Drepper  <drepper@cygnus.com>

	* FAQ:  Fix some typos.
	Tell that for Linux the kernel header files are necessary.

	* PROJECTS: New file.  List of open jobs for glibc.
	* Makefile (distribute): Add PROJECTS.

	* crypt/GNUmakefile (headers): New variable.  Mention crypt.h.
	* crypt/crypt.h: Header for crypt functions.

	* elf/elf.h: Add some new constants from recent Cygnus ELF
	header files.

	* login/getutid_r.c: Test for correct type.
	Don't depend on ut_type and ut_id unless _HAVE_UT_TYPE and
	_HAVE_UT_ID resp. are defined.
	Make really compliant with specification.

	* login/getutline_r.c, login/pututline_r.c: Don't depend on
	ut_type and ut_id unless _HAVE_UT_TYPE and _HAVE_UT_ID resp. are
	defined.
	Make really compliant with specification.

	* login/setutent_r.c: Don't depend on ut_type and ut_id unless
	_HAVE_UT_TYPE and _HAVE_UT_ID resp. are defined.

	* login/login.c, login/logout.c, login/logwtmp.c: Complete
	rewrite.  Now based on getut*/setut* functions.

	* stdlib/strtol.c: Undo changes of Wed May 22 01:48:54 1996.
	This prevented using this file in other GNU packages.

	* sysdeps/gnu/utmpbits.h: Define _HAVE_UT_TYPE, _HAVE_UT_ID,
	and _HAVE_UT_TV because struct utmp has these members.

	* sysdeps/libm-i387/e_exp.S: Correct exp(+-Inf) case.

	* utmp.h: New file.  Wrapper around login/utmp.h.

	* elf/dl-error.c (struct catch): New type.
	(catch): New static variable, struct catch *.
	(catch_env, signalled_errstring, signalled_objname): Variables removed.
	(_dl_signal_error): If CATCH is non-null, set its errstring and
	objname members and jump to CATCH->env.  If it is null, call
	_dl_sysdep_fatal with a standard message.
	* elf/rtld.c (dl_main): Explode `doit' function into dl_main's body.
	No longer use _dl_catch_error.
-rw-r--r--ChangeLog68
-rw-r--r--FAQ36
-rw-r--r--Makefile4
-rw-r--r--PROJECTS98
-rw-r--r--elf/dl-error.c51
-rw-r--r--elf/elf.h54
-rw-r--r--elf/rtld.c468
-rw-r--r--limits.h7
-rw-r--r--locale/C-ctype.c5
-rw-r--r--locale/Makefile3
-rw-r--r--locale/categories.def1
-rw-r--r--locale/langinfo.h1
-rw-r--r--locale/localeinfo.h2
-rw-r--r--locale/mb_cur_max.c32
-rw-r--r--locale/programs/ld-ctype.c10
-rw-r--r--login/getutid_r.c34
-rw-r--r--login/getutline_r.c23
-rw-r--r--login/login.c148
-rw-r--r--login/logout.c121
-rw-r--r--login/logwtmp.c111
-rw-r--r--login/pututline_r.c56
-rw-r--r--login/setutent_r.c4
-rw-r--r--stdlib/stdlib.h6
-rw-r--r--stdlib/strtol.c24
-rw-r--r--string/strtok.c73
-rw-r--r--sysdeps/gnu/utmpbits.h7
-rw-r--r--sysdeps/libm-i387/e_exp.S14
-rw-r--r--utmp.h1
28 files changed, 900 insertions, 562 deletions
diff --git a/ChangeLog b/ChangeLog
index 8e52bf5d13..23c069582a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,73 @@
+Tue May 28 04:38:10 1996  Ulrich Drepper  <drepper@cygnus.com>
+
+	* limits.h: Change MB_LEN_MAX to 6.  A 31-bit ISO 10646
+	character in UTF-8 encoding has that many bytes.
+
+	* locale/langinfo.h: New element _NL_CTYPE_MB_CUR_MAX.
+	* locale/categories.def: Add description of field _NL_CTYPE_MB_CUR_MAX.
+	* locale/Makefile (routines): Add mb_cur_max.
+	* locale/mb_cur_max.c: New file.  This function gets called
+	when the macro MB_CUR_MAX is used.
+	* locale/C-ctype.c: Initialize new mb_cur_max field.
+	* locale/localeinfo.h: Change magic value because of incompatible
+        change.
+	* locale/programs/ld-ctype.c: Determine value of mb_cur_max
+        according to current character set and write it out with the rest.
+	* stdlib/stdlib.h (MB_CUR_MAX): Not constant anymore.  Get value
+        according to currently used locale for catefory LC_CTYPE by
+        calling the function __ctype_get_mb_cur_max.
+
+Tue May 28 03:27:46 1996  Ulrich Drepper  <drepper@cygnus.com>
+
+	* FAQ:  Fix some typos.
+	Tell that for Linux the kernel header files are necessary.
+
+	* PROJECTS: New file.  List of open jobs for glibc.
+	* Makefile (distribute): Add PROJECTS.
+
+	* crypt/GNUmakefile (headers): New variable.  Mention crypt.h.
+	* crypt/crypt.h: Header for crypt functions.
+
+	* elf/elf.h: Add some new constants from recent Cygnus ELF
+	header files.
+
+	* login/getutid_r.c: Test for correct type.
+	Don't depend on ut_type and ut_id unless _HAVE_UT_TYPE and
+	_HAVE_UT_ID resp. are defined.
+	Make really compliant with specification.
+
+	* login/getutline_r.c, login/pututline_r.c: Don't depend on
+	ut_type and ut_id unless _HAVE_UT_TYPE and _HAVE_UT_ID resp. are
+	defined.
+	Make really compliant with specification.
+
+	* login/setutent_r.c: Don't depend on ut_type and ut_id unless
+	_HAVE_UT_TYPE and _HAVE_UT_ID resp. are defined.
+
+	* login/login.c, login/logout.c, login/logwtmp.c: Complete
+	rewrite.  Now based on getut*/setut* functions.
+
+	* stdlib/strtol.c: Undo changes of Wed May 22 01:48:54 1996.
+	This prevented using this file in other GNU packages.
+
+	* sysdeps/gnu/utmpbits.h: Define _HAVE_UT_TYPE, _HAVE_UT_ID,
+	and _HAVE_UT_TV because struct utmp has these members.
+
+	* sysdeps/libm-i387/e_exp.S: Correct exp(+-Inf) case.
+
+	* utmp.h: New file.  Wrapper around login/utmp.h.
+
 Tue May 28 13:11:19 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
 
+	* elf/dl-error.c (struct catch): New type.
+	(catch): New static variable, struct catch *.
+	(catch_env, signalled_errstring, signalled_objname): Variables removed.
+	(_dl_signal_error): If CATCH is non-null, set its errstring and
+	objname members and jump to CATCH->env.  If it is null, call
+	_dl_sysdep_fatal with a standard message.
+	* elf/rtld.c (dl_main): Explode `doit' function into dl_main's body.
+	No longer use _dl_catch_error.
+
 	* Makerules (sed-remove-objpfx): Avoid extra space in regexp due to
 	continuation line.
 
diff --git a/FAQ b/FAQ
index 9ebd95d7a5..f85b255bbc 100644
--- a/FAQ
+++ b/FAQ
@@ -102,8 +102,8 @@ from your favourite mirror of prep.ai.mit.edu.
 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
 [Q5]	``Do I need a special linker or archiver?''
 
-[A5] {UD} If your native versions are not too buggy you can work with
-them.  But GNU libc works best with GNU binutils.
+[A5] {UD} If your native versions are not too buggy you can probably
+work with them.  But GNU libc works best with GNU binutils.
 
 On systems where the native linker does not support weak symbols you
 will not get a really ISO C compliant C library.  Generally speaking
@@ -119,7 +119,7 @@ Older releases are known to have bugs that affect building the GNU C library.
 
 [A6] {UD} Yes, there are some more :-).
 
-* lots of diskspace (for i386-linux this means, e.g., ~70MB)
+* lots of diskspace (for i386-linux this means, e.g., ~70MB).
 
   You should avoid compiling on a NFS mounted device.  This is very
   slow.
@@ -130,6 +130,12 @@ Older releases are known to have bugs that affect building the GNU C library.
   If you are interested in some more measurements let me know.
 
 
+* When compiling for Linux:
+
+  + the header files of the Linux kernel must be available in the
+    search path of the CPP as <linux/*.h> and <asm/*.h>.
+
+
 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
 [Q7]	``When I run `nm libc.so|grep " U "' on the produced library
 	  I still find unresolved symbols?  Can this be ok?''
@@ -138,7 +144,7 @@ Older releases are known to have bugs that affect building the GNU C library.
 symbols:
 
 * magic symbols automatically generated by the linker.  Names are
-  often like __start_* and __stop_*-
+  often like __start_* and __stop_*
 
 * symbols resolved by using libgcc.a
   (__udivdi3, __umoddi3, or similar)
@@ -161,14 +167,18 @@ and with cleanliness.  With the introduction of a new version number these
 errors now can be corrected.  Here is a list of the known source code
 incompatibilities:
 
-* _GNU_SOURCE: glibc does not automatically define _GNU_SOURCE.  Thus, if a
-  program depends on GNU extensions, it is necessary to compile it with C
-  compiler option -D_GNU_SOURCE, or better, to put `#define _GNU_SOURCE' at
-  the beginning of your source files, before any C library header files are
-  included.  This difference normally mainfests itself in the form of
-  missing prototypes and/or data type definitions.  Thus, if you get such
-  errors, the first thing you should do is try defining _GNU_SOURCE and see
-  if that makes the problem go away.
+* _GNU_SOURCE: glibc does not automatically define _GNU_SOURCE.  Thus,
+  if a program depends on GNU extensions or some other non-standard
+  functionality, it is necessary to compile it with C compiler option
+  -D_GNU_SOURCE, or better, to put `#define _GNU_SOURCE' at the beginning
+  of your source files, before any C library header files are included.
+  This difference normally manifests itself in the form of missing
+  prototypes and/or data type definitions.  Thus, if you get such errors,
+  the first thing you should do is try defining _GNU_SOURCE and see if
+  that makes the problem go away.
+
+  For more information consult the file `NOTES' part of the GNU C
+  library sources.
 
 * reboot(): GNU libc sanitizes the interface of reboot() to be more
   compatible with the interface used on other OSes.  In particular,
@@ -209,7 +219,7 @@ Answers were given by:
 {DMT} David Mosberger-Tang, <davidm@AZStarNet.com>
 
 Amended by:
-{RM} Roland McGrath <roland@gnu.ai.mit.edu>
+{RM} Roland McGrath, <roland@gnu.ai.mit.edu>
 
 Local Variables:
  mode:text
diff --git a/Makefile b/Makefile
index 8ff7284d73..c33e40f6b2 100644
--- a/Makefile
+++ b/Makefile
@@ -222,8 +222,8 @@ parent_echo-distinfo:
 
 # Make the distribution tarfile.
 
-distribute  := README INSTALL FAQ NOTES COPYING.LIB COPYING NEWS	\
-	       ChangeLog ChangeLog.[0-9]				\
+distribute  := README INSTALL FAQ NOTES NEWS PROJECTS			\
+	        COPYING.LIB COPYING ChangeLog ChangeLog.[0-9]		\
 	       Makefile Makeconfig Makerules Rules Make-dist MakeTAGS	\
 	       extra-lib.mk o-iterator.mk				\
 	       ansidecl.h mkinstalldirs move-if-change install-sh	\
diff --git a/PROJECTS b/PROJECTS
new file mode 100644
index 0000000000..3150ce11cf
--- /dev/null
+++ b/PROJECTS
@@ -0,0 +1,98 @@
+Open jobs for finishing GNU libc:
+---------------------------------
+Status: May 1996
+
+If you have time and talent to take over any of the jobs below please
+contact <bug-glibc@prep.ai.mit.edu>
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+[ 1] Port to new platforms or test current version on formerly supported
+     platforms.
+
+
+[ 2] Test compliance with standards.  If you have access to recent
+     standards (IEEE, ISO, ANSI, X/Open, ...) and/or test suites you
+     could do some checks as the goal is to be compliant with all
+     standards if they do not contradict each other.
+
+
+[ 3] Write translations for the GNU libc message for the so far
+     unsupported languages.  GNU libc is fully internationalized and
+     users can immediately benefit from this.
+
+     Take a look at the matrix in
+	ftp://prep.ai.mit.edu/pub/gnu/ABOUT-NLS
+     for the current status (of course better use a mirror of prep).
+
+
+[ 4] Write wordexp() function; this is described in POSIX.2, The
+     header <wordexp.h> already exists.
+
+     Implementation idea: use some functions from bash.
+
+
+[ 5] Write reentrent versions of crypt() et.al.
+
+     Implementation idea: Define in <crypt.h>
+
+	struct crypt_data
+	{
+	  <... all the needed data ...>
+	};
+
+     and define additional functions
+
+	char *crypt_r (__const char *__key, __const char *__salt,
+		       struct crypt_data *__data);
+
+	void setkey_r (__const char *__key, struct crypt_data *__data);
+
+	void encrypt_r (char *__block, int __edflag,
+			struct crypt_data *__data);
+
+     If possible the non-reentrent functions should use the reentrent
+     ones.
+
+     Because of the US export restrictions it might be a good idea if
+     some non-american person does this job.
+
+
+[ 6] Write `long double' versions of the math functions.  This should be
+     done in collaboration with the NetBSD and FreeBSD people.
+
+     The libm is in fact fdlibm (not the same as in Linux libc).
+
+
+[ 7] If you enjoy assembler programming (as I do --drepper :-) you might
+     be interested in writing optimized versions for some functions.
+     Especially the string handling functions can be optimized a lot.
+
+     Take a look at
+
+	Faster String Functions
+	Henry Spencer, University of Toronto
+	Usenix Winter '92, pp. 419--428
+
+     or just ask.  Currently mostly i?86 optimized versions exist.
+
+
+[ 8] Write nftw() function.  Perhaps it might be good to reimplement the
+     ftw() function as well to share most of the code.
+
+
+[ 9] Write AVL-tree based tsearch() et.al. functions.  Currently only
+     a very simple algorithm is used.
+
+
+[10] Extend regex and/or rx to work with wide characters.
+
+
+[11] Add mmap() support to malloc().
+     Doug Lea's malloc implementation might give some ideas.  Perhaps
+     switching completly to his implementation is an option if it
+     a) can work without mmap() support (not all system GNU libc
+	is running on have mmap)
+     b) is without mmap support at least as fast as the current
+	implementation
+     c) will be extended with the current hooks and additional functions
diff --git a/elf/dl-error.c b/elf/dl-error.c
index a5c861190f..737bba7421 100644
--- a/elf/dl-error.c
+++ b/elf/dl-error.c
@@ -1,5 +1,5 @@
 /* Error handling for runtime dynamic linker.
-Copyright (C) 1995 Free Software Foundation, Inc.
+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
@@ -20,18 +20,47 @@ Cambridge, MA 02139, USA.  */
 #include <stddef.h>
 #include <link.h>
 #include <setjmp.h>
+#include <string.h>
+
+/* This structure communicates state between _dl_catch_error and
+   _dl_signal_error.  */
+struct catch
+  {
+    const char *errstring, *objname; /* Error detail filled in here.  */
+    jmp_buf env;		/* longjmp here on error.  */
+  };
+
+/* This points to such a structure during a call to _dl_catch_error.
+   During implicit startup and run-time work for needed shared libraries,
+   this is null.  */
+static struct catch *catch;
 
-static jmp_buf catch_env;
-static const char *signalled_errstring, *signalled_objname;
 
 void
 _dl_signal_error (int errcode,
 		  const char *objname,
 		  const char *errstring)
 {
-  signalled_errstring = errstring ?: "DYNAMIC LINKER BUG!!!";
-  signalled_objname = objname;
-  longjmp (catch_env, errcode ?: -1);
+  if (! errstring)
+    errstring = "DYNAMIC LINKER BUG!!!";
+
+  if (catch)
+    {
+      /* We are inside _dl_catch_error.  Return to it.  */
+      catch->errstring = errstring;
+      catch->objname = objname;
+      longjmp (catch->env, errcode ?: -1);
+    }
+  else
+    {
+      /* Lossage while resolving the program's own symbols is always fatal.  */
+      extern char **_dl_argv;	/* Set in rtld.c at startup.  */
+      _dl_sysdep_fatal (_dl_argv[0] ?: "<program name unknown>",
+			": error in loading shared libraries\n",
+			objname ?: "", objname ? ": " : "",
+			errstring, errcode ? ": " : "",
+			errcode ? strerror (errcode) : "", "\n", NULL);
+    }
 }
 
 int
@@ -40,18 +69,20 @@ _dl_catch_error (const char **errstring,
 		 void (*operate) (void))
 {
   int errcode;
+  struct catch c = { errstring: NULL, objname: NULL };
 
-  signalled_errstring = signalled_objname = NULL;
-  errcode = setjmp (catch_env);
+  errcode = setjmp (c.env);
   if (errcode == 0)
     {
+      catch = &c;
       (*operate) ();
+      catch = NULL;
       *errstring = *objname = NULL;
       return 0;
     }
 
   /* We get here only if we longjmp'd out of OPERATE.  */
-  *errstring = signalled_errstring;
-  *objname = signalled_objname;
+  *errstring = c.errstring;
+  *objname = c.objname;
   return errcode == -1 ? 0 : errcode;
 }
diff --git a/elf/elf.h b/elf/elf.h
index a78432039f..2b41ff0cbc 100644
--- a/elf/elf.h
+++ b/elf/elf.h
@@ -119,6 +119,7 @@ typedef struct
 #define EM_SPARC64     11		/* SPARC v9 (not official) 64-bit */
 
 #define EM_PARISC      15		/* HPPA */
+#define EM_PPC         20		/* PowerPC */
 
 /* If it is necessary to assign new unofficial EM_* values, please
    pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the
@@ -255,6 +256,10 @@ typedef struct
 #define ELF32_R_TYPE(val)		((val) & 0xff)
 #define ELF32_R_INFO(sym, type)		(((sym) << 8) + ((type) & 0xff))
 
+#define ELF64_R_SYM(i)			((i) >> 32)
+#define ELF64_R_TYPE(i)			((i) & 0xffffffff)
+#define ELF64_R_INFO(sym,type)		(((sym) << 32) + (type))
+
 /* Program segment header.  */
 
 typedef struct {
@@ -288,6 +293,17 @@ typedef struct {
 #define PF_R		(1 << 2)	/* Segment is readable */
 #define PF_MASKPROC	0xf0000000	/* Processor-specific */
 
+/* Legal values for note segment descriptor types for core files. */
+
+#define NT_PRSTATUS	1		/* Contains copy of prstatus struct */
+#define NT_FPREGSET	2		/* Contains copy of fpregset struct */
+#define NT_PRPSINFO	3		/* Contains copy of prpsinfo struct */
+
+/* Legal values for the  note segment descriptor types for object files.  */
+
+#define NT_VERSION	1		/* Contains a version string.  */
+
+
 /* Dynamic section entry.  */
 
 typedef struct
@@ -521,9 +537,17 @@ typedef struct
 #define EF_MIPS_CPIC	  4		/* Uses PIC calling sequence */
 #define EF_MIPS_ARCH	  0xf0000000	/* MIPS architecture level */
 
+/* Legal values for MIPS architecture level.  */
+
+#define E_MIPS_ARCH_1	  0x00000000	/* -mips1 code.  */
+#define E_MIPS_ARCH_2	  0x10000000	/* -mips2 code.  */
+#define E_MIPS_ARCH_3	  0x20000000	/* -mips3 code.  */
+
 /* Special section indices.  */
 
 #define SHN_MIPS_ACOMMON 0xff00		/* Allocated common symbols */
+#define SHN_MIPS_TEXT	 0xff01		/* Allocated test symbol.  */
+#define SHN_MIPS_DATA	 0xff02		/* Allocated data symbol.  */
 #define SHN_MIPS_SCOMMON 0xff03		/* Small common symbols */
 #define SHN_MIPS_SUNDEFINED 0xff04	/* Small undefined symbols */
 
@@ -535,6 +559,9 @@ typedef struct
 #define SHT_MIPS_UCODE	  0x70000004	/* Reserved for SGI/MIPS compilers */
 #define SHT_MIPS_DEBUG	  0x70000005	/* MIPS ECOFF debugging information */
 #define SHT_MIPS_REGINFO  0x70000006	/* Register usage information */
+#define SHT_MIPS_OPTIONS  0x7000000d	/* Miscellaneous options.  */
+#define SHT_MIPS_DWARF    0x7000001e	/* DWARF debugging information.  */
+#define SHT_MIPS_EVENTS	  0x70000021	/* Event section.  */
 
 /* Legal values for sh_flags field of Elf32_Shdr.  */
 
@@ -602,7 +629,8 @@ typedef struct
 #define DT_MIPS_UNREFEXTNO   0x70000012	/* First external DYNSYM */
 #define DT_MIPS_GOTSYM	     0x70000013	/* First GOT entry in DYNSYM */
 #define DT_MIPS_HIPAGENO     0x70000014	/* Number of GOT page table entries */
-#define DT_MIPS_NUM	     0x15
+#define DT_MIPS_RLD_MAP	     0x70000016	/* Address of run time loader map.  */
+#define DT_MIPS_NUM	     0x17
 
 /* Legal values for DT_MIPS_FLAG Elf32_Dyn entry.  */
 
@@ -632,4 +660,28 @@ typedef struct
 typedef Elf32_Addr Elf32_Conflict;
 
 
+/* HPPA specific definitions.  */
+
+/* Legal values for sh_type field of Elf32_Shdr.  */
+
+#define SHT_PARISC_GOT		0x70000000 /* GOT for external data.  */
+#define SHT_PARISC_ARCH		0x70000001 /* Architecture extensions.  */
+#define SHT_PARISC_GLOBAL	0x70000002 /* Definition of $global$.  */
+#define SHT_PARISC_MILLI	0x70000003 /* Millicode routines.  */
+#define SHT_PARISC_UNWIND	0x70000004 /* Unwind information.  */
+#define SHT_PARISC_PLT		0x70000005 /* Procedure linkage table.  */
+#define SHT_PARISC_SDATA	0x70000006 /* Short initialized data.  */
+#define SHT_PARISC_SBSS		0x70000007 /* Short uninitialized data.  */
+#define SHT_PARISC_SYMEXTN	0x70000008 /* Argument/relocation info.  */
+#define SHT_PARISC_STUBS	0x70000009 /* Linker stubs.  */
+
+/* Legal values for sh_flags field of Elf32_Shdr.  */
+
+#define SHF_PARISC_SHORT	0x20000000 /* Section with short addressing. */
+
+/* Legal values for ST_TYPE subfield of st_info (symbol type).  */
+
+#define STT_PARISC_MILLICODE	13	/* Millicode function entry point.  */
+
+
 #endif	/* elf.h */
diff --git a/elf/rtld.c b/elf/rtld.c
index d727e1361f..edd9c514d8 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -123,33 +123,31 @@ dl_main (const Elf32_Phdr *phdr,
 	 Elf32_Word phent,
 	 Elf32_Addr *user_entry)
 {
-  void doit (void)
-    {
-      const Elf32_Phdr *ph;
-      struct link_map *l, *last, *before_rtld;
-      const char *interpreter_name;
-      int lazy;
-      int list_only = 0;
+  const Elf32_Phdr *ph;
+  struct link_map *l, *last, *before_rtld;
+  const char *interpreter_name;
+  int lazy;
+  int list_only = 0;
 
-      if (*user_entry == (Elf32_Addr) &_start)
-	{
-	  /* Ho ho.  We are not the program interpreter!  We are the program
-	     itself!  This means someone ran ld.so as a command.  Well, that
-	     might be convenient to do sometimes.  We support it by
-	     interpreting the args like this:
-
-	     ld.so PROGRAM ARGS...
-
-	     The first argument is the name of a file containing an ELF
-	     executable we will load and run with the following arguments.
-	     To simplify life here, PROGRAM is searched for using the
-	     normal rules for shared objects, rather than $PATH or anything
-	     like that.  We just load it and use its entry point; we don't
-	     pay attention to its PT_INTERP command (we are the interpreter
-	     ourselves).  This is an easy way to test a new ld.so before
-	     installing it.  */
-	  if (_dl_argc < 2)
-	    _dl_sysdep_fatal ("\
+  if (*user_entry == (Elf32_Addr) &_start)
+    {
+      /* Ho ho.  We are not the program interpreter!  We are the program
+	 itself!  This means someone ran ld.so as a command.  Well, that
+	 might be convenient to do sometimes.  We support it by
+	 interpreting the args like this:
+
+	 ld.so PROGRAM ARGS...
+
+	 The first argument is the name of a file containing an ELF
+	 executable we will load and run with the following arguments.
+	 To simplify life here, PROGRAM is searched for using the
+	 normal rules for shared objects, rather than $PATH or anything
+	 like that.  We just load it and use its entry point; we don't
+	 pay attention to its PT_INTERP command (we are the interpreter
+	 ourselves).  This is an easy way to test a new ld.so before
+	 installing it.  */
+      if (_dl_argc < 2)
+	_dl_sysdep_fatal ("\
 Usage: ld.so [--list] EXECUTABLE-FILE [ARGS-FOR-PROGRAM...]\n\
 You have invoked `ld.so', the helper program for shared library executables.\n\
 This program usually lives in the file `/lib/ld.so', and special directives\n\
@@ -162,243 +160,231 @@ that file itself, but always uses this helper program from the file you\n\
 specified, instead of the helper program file specified in the executable\n\
 file you run.  This is mostly of use for maintainers to test new versions\n\
 of this helper program; chances are you did not intend to run this program.\n",
-			      NULL);
+			  NULL);
 
-	  interpreter_name = _dl_argv[0];
+      interpreter_name = _dl_argv[0];
 
-	  if (! strcmp (_dl_argv[1], "--list"))
-	    {
-	      list_only = 1;
-
-	      ++_dl_skip_args;
-	      --_dl_argc;
-	      ++_dl_argv;
-	    }
+      if (! strcmp (_dl_argv[1], "--list"))
+	{
+	  list_only = 1;
 
 	  ++_dl_skip_args;
 	  --_dl_argc;
 	  ++_dl_argv;
-
-	  l = _dl_map_object (NULL, _dl_argv[0]);
-	  phdr = l->l_phdr;
-	  phent = l->l_phnum;
-	  l->l_name = (char *) "";
-	  *user_entry = l->l_entry;
-	}
-      else
-	{
-	  /* Create a link_map for the executable itself.
-	     This will be what dlopen on "" returns.  */
-	  l = _dl_new_object ((char *) "", "", lt_executable);
-	  l->l_phdr = phdr;
-	  l->l_phnum = phent;
-	  interpreter_name = 0;
-	  l->l_entry = *user_entry;
 	}
 
-      if (l != _dl_loaded)
-	{
-	  /* GDB assumes that the first element on the chain is the
-	     link_map for the executable itself, and always skips it.
-	     Make sure the first one is indeed that one.  */
-	  l->l_prev->l_next = l->l_next;
-	  if (l->l_next)
-	    l->l_next->l_prev = l->l_prev;
-	  l->l_prev = NULL;
-	  l->l_next = _dl_loaded;
-	  _dl_loaded->l_prev = l;
-	  _dl_loaded = l;
-	}
+      ++_dl_skip_args;
+      --_dl_argc;
+      ++_dl_argv;
 
-      /* Scan the program header table for the dynamic section.  */
-      for (ph = phdr; ph < &phdr[phent]; ++ph)
-	switch (ph->p_type)
-	  {
-	  case PT_DYNAMIC:
-	    /* This tells us where to find the dynamic section,
-	       which tells us everything we need to do.  */
-	    l->l_ld = (void *) l->l_addr + ph->p_vaddr;
-	    break;
-	  case PT_INTERP:
-	    /* This "interpreter segment" was used by the program loader to
-	       find the program interpreter, which is this program itself, the
-	       dynamic linker.  We note what name finds us, so that a future
-	       dlopen call or DT_NEEDED entry, for something that wants to link
-	       against the dynamic linker as a shared library, will know that
-	       the shared object is already loaded.  */
-	    interpreter_name = (void *) l->l_addr + ph->p_vaddr;
-	    break;
-	  }
-      assert (interpreter_name); /* How else did we get here?  */
-
-      /* Extract the contents of the dynamic section for easy access.  */
-      elf_get_dynamic_info (l->l_ld, l->l_info);
-      if (l->l_info[DT_HASH])
-	/* Set up our cache of pointers into the hash table.  */
-	_dl_setup_hash (l);
-
-      if (l->l_info[DT_DEBUG])
-	/* There is a DT_DEBUG entry in the dynamic section.  Fill it in
-	   with the run-time address of the r_debug structure, which we
-	   will set up later to communicate with the debugger.  */
-	l->l_info[DT_DEBUG]->d_un.d_ptr = (Elf32_Addr) &dl_r_debug;
-
-      /* Put the link_map for ourselves on the chain so it can be found by
-	 name.  */
-      rtld_map.l_name = (char *) rtld_map.l_libname = interpreter_name;
-      rtld_map.l_type = lt_interpreter;
-      while (l->l_next)
-	l = l->l_next;
-      l->l_next = &rtld_map;
-      rtld_map.l_prev = l;
-
-      /* Now process all the DT_NEEDED entries and map in the objects.
-	 Each new link_map will go on the end of the chain, so we will
-	 come across it later in the loop to map in its dependencies.  */
-      before_rtld = NULL;
-      for (l = _dl_loaded; l; l = l->l_next)
+      l = _dl_map_object (NULL, _dl_argv[0]);
+      phdr = l->l_phdr;
+      phent = l->l_phnum;
+      l->l_name = (char *) "";
+      *user_entry = l->l_entry;
+    }
+  else
+    {
+      /* Create a link_map for the executable itself.
+	 This will be what dlopen on "" returns.  */
+      l = _dl_new_object ((char *) "", "", lt_executable);
+      l->l_phdr = phdr;
+      l->l_phnum = phent;
+      interpreter_name = 0;
+      l->l_entry = *user_entry;
+    }
+
+  if (l != _dl_loaded)
+    {
+      /* GDB assumes that the first element on the chain is the
+	 link_map for the executable itself, and always skips it.
+	 Make sure the first one is indeed that one.  */
+      l->l_prev->l_next = l->l_next;
+      if (l->l_next)
+	l->l_next->l_prev = l->l_prev;
+      l->l_prev = NULL;
+      l->l_next = _dl_loaded;
+      _dl_loaded->l_prev = l;
+      _dl_loaded = l;
+    }
+
+  /* Scan the program header table for the dynamic section.  */
+  for (ph = phdr; ph < &phdr[phent]; ++ph)
+    switch (ph->p_type)
+      {
+      case PT_DYNAMIC:
+	/* This tells us where to find the dynamic section,
+	   which tells us everything we need to do.  */
+	l->l_ld = (void *) l->l_addr + ph->p_vaddr;
+	break;
+      case PT_INTERP:
+	/* This "interpreter segment" was used by the program loader to
+	   find the program interpreter, which is this program itself, the
+	   dynamic linker.  We note what name finds us, so that a future
+	   dlopen call or DT_NEEDED entry, for something that wants to link
+	   against the dynamic linker as a shared library, will know that
+	   the shared object is already loaded.  */
+	interpreter_name = (void *) l->l_addr + ph->p_vaddr;
+	break;
+      }
+  assert (interpreter_name);	/* How else did we get here?  */
+
+  /* Extract the contents of the dynamic section for easy access.  */
+  elf_get_dynamic_info (l->l_ld, l->l_info);
+  if (l->l_info[DT_HASH])
+    /* Set up our cache of pointers into the hash table.  */
+    _dl_setup_hash (l);
+
+  if (l->l_info[DT_DEBUG])
+    /* There is a DT_DEBUG entry in the dynamic section.  Fill it in
+       with the run-time address of the r_debug structure, which we
+       will set up later to communicate with the debugger.  */
+    l->l_info[DT_DEBUG]->d_un.d_ptr = (Elf32_Addr) &dl_r_debug;
+
+  /* Put the link_map for ourselves on the chain so it can be found by
+     name.  */
+  rtld_map.l_name = (char *) rtld_map.l_libname = interpreter_name;
+  rtld_map.l_type = lt_interpreter;
+  while (l->l_next)
+    l = l->l_next;
+  l->l_next = &rtld_map;
+  rtld_map.l_prev = l;
+
+  /* Now process all the DT_NEEDED entries and map in the objects.
+     Each new link_map will go on the end of the chain, so we will
+     come across it later in the loop to map in its dependencies.  */
+  before_rtld = NULL;
+  for (l = _dl_loaded; l; l = l->l_next)
+    {
+      if (l->l_info[DT_NEEDED])
 	{
-	  if (l->l_info[DT_NEEDED])
-	    {
-	      const char *strtab
-		= (void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr;
-	      const Elf32_Dyn *d;
-	      last = l;
-	      for (d = l->l_ld; d->d_tag != DT_NULL; ++d)
-		if (d->d_tag == DT_NEEDED)
-		  {
-		    struct link_map *new;
-		    new = _dl_map_object (l, strtab + d->d_un.d_val);
-		    if (!before_rtld && new == &rtld_map)
-		      before_rtld = last;
-		    last = new;
-		  }
-	    }
-	  l->l_deps_loaded = 1;
+	  const char *strtab
+	    = (void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr;
+	  const Elf32_Dyn *d;
+	  last = l;
+	  for (d = l->l_ld; d->d_tag != DT_NULL; ++d)
+	    if (d->d_tag == DT_NEEDED)
+	      {
+		struct link_map *new;
+		new = _dl_map_object (l, strtab + d->d_un.d_val);
+		if (!before_rtld && new == &rtld_map)
+		  before_rtld = last;
+		last = new;
+	      }
 	}
+      l->l_deps_loaded = 1;
+    }
 
-      /* If any DT_NEEDED entry referred to the interpreter object itself,
-	 reorder the list so it appears after its dependent.  If not,
-	 remove it from the maps we will use for symbol resolution.  */
-      rtld_map.l_prev->l_next = rtld_map.l_next;
+  /* If any DT_NEEDED entry referred to the interpreter object itself,
+     reorder the list so it appears after its dependent.  If not,
+     remove it from the maps we will use for symbol resolution.  */
+  rtld_map.l_prev->l_next = rtld_map.l_next;
+  if (rtld_map.l_next)
+    rtld_map.l_next->l_prev = rtld_map.l_prev;
+  if (before_rtld)
+    {
+      rtld_map.l_prev = before_rtld;
+      rtld_map.l_next = before_rtld->l_next;
+      before_rtld->l_next = &rtld_map;
       if (rtld_map.l_next)
-	rtld_map.l_next->l_prev = rtld_map.l_prev;
-      if (before_rtld)
-	{
-	  rtld_map.l_prev = before_rtld;
-	  rtld_map.l_next = before_rtld->l_next;
-	  before_rtld->l_next = &rtld_map;
-	  if (rtld_map.l_next)
-	    rtld_map.l_next->l_prev = &rtld_map;
-	}
+	rtld_map.l_next->l_prev = &rtld_map;
+    }
 
-      if (list_only)
-	{
-	  /* We were run just to list the shared libraries.  It is
-	     important that we do this before real relocation, because the
-	     functions we call below for output may no longer work properly
-	     after relocation.  */
+  if (list_only)
+    {
+      /* We were run just to list the shared libraries.  It is
+	 important that we do this before real relocation, because the
+	 functions we call below for output may no longer work properly
+	 after relocation.  */
 
-	  int i;
+      int i;
 
-	  if (! _dl_loaded->l_info[DT_NEEDED])
-	    _dl_sysdep_message ("\t", "statically linked\n", NULL);
-	  else
-	    for (l = _dl_loaded->l_next; l; l = l->l_next)
-	      {
-		char buf[20], *bp;
-		buf[sizeof buf - 1] = '\0';
-		bp = _itoa (l->l_addr, &buf[sizeof buf - 1], 16, 0);
-		while (&buf[sizeof buf - 1] - bp < sizeof l->l_addr * 2)
-		  *--bp = '0';
-		_dl_sysdep_message ("\t", l->l_libname, " => ", l->l_name,
-				    " (0x", bp, ")\n", NULL);
-	      }
+      if (! _dl_loaded->l_info[DT_NEEDED])
+	_dl_sysdep_message ("\t", "statically linked\n", NULL);
+      else
+	for (l = _dl_loaded->l_next; l; l = l->l_next)
+	  {
+	    char buf[20], *bp;
+	    buf[sizeof buf - 1] = '\0';
+	    bp = _itoa (l->l_addr, &buf[sizeof buf - 1], 16, 0);
+	    while (&buf[sizeof buf - 1] - bp < sizeof l->l_addr * 2)
+	      *--bp = '0';
+	    _dl_sysdep_message ("\t", l->l_libname, " => ", l->l_name,
+				" (0x", bp, ")\n", NULL);
+	  }
 
-	  for (i = 1; i < _dl_argc; ++i)
-	    {
-	      const Elf32_Sym *ref = NULL;
-	      Elf32_Addr loadbase = _dl_lookup_symbol (_dl_argv[i], &ref,
-						       _dl_loaded, "argument",
-						       1);
-	      char buf[20], *bp;
-	      buf[sizeof buf - 1] = '\0';
-	      bp = _itoa (ref->st_value, &buf[sizeof buf - 1], 16, 0);
-	      while (&buf[sizeof buf - 1] - bp < sizeof loadbase * 2)
-		*--bp = '0';
-	      _dl_sysdep_message (_dl_argv[i], " found at 0x", bp, NULL);
-	      buf[sizeof buf - 1] = '\0';
-	      bp = _itoa (loadbase, &buf[sizeof buf - 1], 16, 0);
-	      while (&buf[sizeof buf - 1] - bp < sizeof loadbase * 2)
-		*--bp = '0';
-	      _dl_sysdep_message (" in object at 0x", bp, "\n", NULL);
-	    }
-
-	  _exit (0);
+      for (i = 1; i < _dl_argc; ++i)
+	{
+	  const Elf32_Sym *ref = NULL;
+	  Elf32_Addr loadbase = _dl_lookup_symbol (_dl_argv[i], &ref,
+						   _dl_loaded, "argument",
+						   1);
+	  char buf[20], *bp;
+	  buf[sizeof buf - 1] = '\0';
+	  bp = _itoa (ref->st_value, &buf[sizeof buf - 1], 16, 0);
+	  while (&buf[sizeof buf - 1] - bp < sizeof loadbase * 2)
+	    *--bp = '0';
+	  _dl_sysdep_message (_dl_argv[i], " found at 0x", bp, NULL);
+	  buf[sizeof buf - 1] = '\0';
+	  bp = _itoa (loadbase, &buf[sizeof buf - 1], 16, 0);
+	  while (&buf[sizeof buf - 1] - bp < sizeof loadbase * 2)
+	    *--bp = '0';
+	  _dl_sysdep_message (" in object at 0x", bp, "\n", NULL);
 	}
 
-      lazy = !_dl_secure && *(getenv ("LD_BIND_NOW") ?: "") == '\0';
-
-      /* Now we have all the objects loaded.  Relocate them all except for
-	 the dynamic linker itself.  We do this in reverse order so that
-	 copy relocs of earlier objects overwrite the data written by later
-	 objects.  We do not re-relocate the dynamic linker itself in this
-	 loop because that could result in the GOT entries for functions we
-	 call being changed, and that would break us.  It is safe to
-	 relocate the dynamic linker out of order because it has no copy
-	 relocs (we know that because it is self-contained).  */
-      l = _dl_loaded;
-      while (l->l_next)
-	l = l->l_next;
-      do
-	{
-	  if (l != &rtld_map)
-	    _dl_relocate_object (l, lazy);
-	  l = l->l_prev;
-	} while (l);
-
-      /* Do any necessary cleanups for the startup OS interface code.
-	 We do these now so that no calls are made after rtld re-relocation
-	 which might be resolved to different functions than we expect.
-	 We cannot do this before relocating the other objects because
-	 _dl_relocate_object might need to call `mprotect' for DT_TEXTREL.  */
-      _dl_sysdep_start_cleanup ();
-
-      if (rtld_map.l_opencount > 0)
-	/* There was an explicit ref to the dynamic linker as a shared lib.
-	   Re-relocate ourselves with user-controlled symbol definitions.  */
-	_dl_relocate_object (&rtld_map, lazy);
-
-      /* Tell the debugger where to find the map of loaded objects.  */
-      dl_r_debug.r_version = 1	/* R_DEBUG_VERSION XXX */;
-      dl_r_debug.r_ldbase = rtld_map.l_addr; /* Record our load address.  */
-      dl_r_debug.r_map = _dl_loaded;
-      dl_r_debug.r_brk = (Elf32_Addr) &_dl_r_debug_state;
-
-      if (rtld_map.l_info[DT_INIT])
-	{
-	  /* Call the initializer for the compatibility version of the
-	     dynamic linker.  There is no additional initialization
-	     required for the ABI-compliant dynamic linker.  */
+      _exit (0);
+    }
 
-	  (*(void (*) (void)) (rtld_map.l_addr +
-			       rtld_map.l_info[DT_INIT]->d_un.d_ptr)) ();
+  lazy = !_dl_secure && *(getenv ("LD_BIND_NOW") ?: "") == '\0';
+
+  /* Now we have all the objects loaded.  Relocate them all except for
+     the dynamic linker itself.  We do this in reverse order so that
+     copy relocs of earlier objects overwrite the data written by later
+     objects.  We do not re-relocate the dynamic linker itself in this
+     loop because that could result in the GOT entries for functions we
+     call being changed, and that would break us.  It is safe to
+     relocate the dynamic linker out of order because it has no copy
+     relocs (we know that because it is self-contained).  */
+  l = _dl_loaded;
+  while (l->l_next)
+    l = l->l_next;
+  do
+    {
+      if (l != &rtld_map)
+	_dl_relocate_object (l, lazy);
+      l = l->l_prev;
+    } while (l);
+
+  /* Do any necessary cleanups for the startup OS interface code.
+     We do these now so that no calls are made after rtld re-relocation
+     which might be resolved to different functions than we expect.
+     We cannot do this before relocating the other objects because
+     _dl_relocate_object might need to call `mprotect' for DT_TEXTREL.  */
+  _dl_sysdep_start_cleanup ();
+
+  if (rtld_map.l_opencount > 0)
+    /* There was an explicit ref to the dynamic linker as a shared lib.
+       Re-relocate ourselves with user-controlled symbol definitions.  */
+    _dl_relocate_object (&rtld_map, lazy);
+
+  /* Tell the debugger where to find the map of loaded objects.  */
+  dl_r_debug.r_version = 1	/* R_DEBUG_VERSION XXX */;
+  dl_r_debug.r_ldbase = rtld_map.l_addr; /* Record our load address.  */
+  dl_r_debug.r_map = _dl_loaded;
+  dl_r_debug.r_brk = (Elf32_Addr) &_dl_r_debug_state;
+
+  if (rtld_map.l_info[DT_INIT])
+    {
+      /* Call the initializer for the compatibility version of the
+	 dynamic linker.  There is no additional initialization
+	 required for the ABI-compliant dynamic linker.  */
 
-	  /* Clear the field so a future dlopen won't run it again.  */
-	  rtld_map.l_info[DT_INIT] = NULL;
-	}
+      (*(void (*) (void)) (rtld_map.l_addr +
+			   rtld_map.l_info[DT_INIT]->d_un.d_ptr)) ();
+
+      /* Clear the field so a future dlopen won't run it again.  */
+      rtld_map.l_info[DT_INIT] = NULL;
     }
-  const char *errstring;
-  const char *errobj;
-  int err;
-
-  err = _dl_catch_error (&errstring, &errobj, &doit);
-  if (errstring)
-    _dl_sysdep_fatal (_dl_argv[0] ?: "<program name unknown>",
-		      ": error in loading shared libraries\n",
-		      errobj ?: "", errobj ? ": " : "",
-		      errstring, err ? ": " : "",
-		      err ? strerror (err) : "", "\n", NULL);
 
   /* Once we return, _dl_sysdep_start will invoke
      the DT_INIT functions and then *USER_ENTRY.  */
diff --git a/limits.h b/limits.h
index 383dfd324a..e0993d67ac 100644
--- a/limits.h
+++ b/limits.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1992, 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
@@ -59,9 +59,8 @@ Cambridge, MA 02139, USA.  */
 /* Number of bits in a `char'.	*/
 #define	CHAR_BIT	8
 
-/* Maximum length of any multibyte character in any locale.
-   Locale-writers should change this as necessary.  */
-#define	MB_LEN_MAX	1
+/* Maximum length of any multibyte character in any locale.  */
+#define	MB_LEN_MAX	6
 
 /* Minimum and maximum values a `signed char' can hold.  */
 #define	SCHAR_MIN	(-128)
diff --git a/locale/C-ctype.c b/locale/C-ctype.c
index ea990da8af..0eb131c050 100644
--- a/locale/C-ctype.c
+++ b/locale/C-ctype.c
@@ -898,7 +898,7 @@ const struct locale_data _nl_C_LC_CTYPE =
 {
   _nl_C_name,
   NULL, 0, /* no file mapped */
-  13,
+  14,
   {
     { string: _nl_C_LC_CTYPE_class },
 #if BYTE_ORDER == LITTLE_ENDIAN
@@ -919,6 +919,7 @@ const struct locale_data _nl_C_LC_CTYPE =
     { string: "upper\0" "lower\0" "alpha\0" "digit\0" "xdigit\0" "space\0"
 	      "print\0" "graph\0" "blank\0" "cntrl\0" "punct\0"  "alnum\0" },
     { string: "tolower\0" "toupper\0" },
-    { string: _nl_C_LC_CTYPE_width }
+    { string: _nl_C_LC_CTYPE_width },
+    { word: 2 }
   }
 };
diff --git a/locale/Makefile b/locale/Makefile
index d7941d689f..e0618c0a01 100644
--- a/locale/Makefile
+++ b/locale/Makefile
@@ -28,7 +28,8 @@ distribute	= localeinfo.h categories.def \
 		  charmap-kw.gperf charmap-kw.h locfile-token.h \
 		  locfile-kw.gperf locfile-kw.h linereader.h \
 		  locales.h locfile.h stringtrans.h
-routines	= setlocale findlocale loadlocale localeconv nl_langinfo
+routines	= setlocale findlocale loadlocale localeconv nl_langinfo \
+		  mb_cur_max
 categories	= ctype messages monetary numeric time collate
 aux		= $(categories:%=lc-%) $(categories:%=C-%) SYS_libc C_name
 others		= localedef locale
diff --git a/locale/categories.def b/locale/categories.def
index f65140f7af..d3caef2265 100644
--- a/locale/categories.def
+++ b/locale/categories.def
@@ -74,6 +74,7 @@ DEFINE_CATEGORY
   DEFINE_ELEMENT (_NL_CTYPE_CLASS_NAMES, "ctype-class-names", std, string)
   DEFINE_ELEMENT (_NL_CTYPE_MAP_NAMES,	 "ctype-map-names",   std, string)
   DEFINE_ELEMENT (_NL_CTYPE_WIDTH,	 "ctype-width",	      std, bytearray)
+  DEFINE_ELEMENT (_NL_CTYPE_MB_CUR_MAX,	 "ctype-mb-cur-max",  std, word)
   ), _nl_postload_ctype, ctype_input, ctype_check, ctype_output)
 
 
diff --git a/locale/langinfo.h b/locale/langinfo.h
index af081e7614..3490045654 100644
--- a/locale/langinfo.h
+++ b/locale/langinfo.h
@@ -133,6 +133,7 @@ typedef enum
   _NL_CTYPE_CLASS_NAMES,
   _NL_CTYPE_MAP_NAMES,
   _NL_CTYPE_WIDTH,
+  _NL_CTYPE_MB_CUR_MAX,
   _NL_NUM_LC_CTYPE,
 
   /* LC_MONETARY category: formatting of monetary quantities.
diff --git a/locale/localeinfo.h b/locale/localeinfo.h
index ac14626dc0..9d4b302b01 100644
--- a/locale/localeinfo.h
+++ b/locale/localeinfo.h
@@ -27,7 +27,7 @@ Cambridge, MA 02139, USA.  */
 #include "../intl/loadinfo.h"	/* For loaded_l10nfile definition.  */
 
 /* Magic number at the beginning of a locale data file for CATEGORY.  */
-#define	LIMAGIC(category)	(0x960316de ^ (category))
+#define	LIMAGIC(category)	(0x960528de ^ (category))
 
 /* Two special weight constants for the collation data.  */
 #define FORWARD_CHAR ((wchar_t) 0xfffffffd)
diff --git a/locale/mb_cur_max.c b/locale/mb_cur_max.c
new file mode 100644
index 0000000000..750d2155c8
--- /dev/null
+++ b/locale/mb_cur_max.c
@@ -0,0 +1,32 @@
+/* Return number of characters in multibyte representation for current
+   character set.
+Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+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 <langinfo.h>
+#include <locale.h>
+#include <stdlib.h>
+#include "localeinfo.h"
+
+
+int
+__ctype_get_mb_cur_max (void)
+{
+  return _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MB_CUR_MAX);
+}
diff --git a/locale/programs/ld-ctype.c b/locale/programs/ld-ctype.c
index 96124988ce..c4a6f7ba64 100644
--- a/locale/programs/ld-ctype.c
+++ b/locale/programs/ld-ctype.c
@@ -108,6 +108,7 @@ struct locale_ctype_t
   u_int32_t *class_name_ptr;
   u_int32_t *map_name_ptr;
   unsigned char *width;
+  u_int32_t mb_cur_max;
 };
 
 
@@ -471,6 +472,9 @@ ctype_output (struct localedef_t *locale, struct charset_t *charset,
 	  CTYPE_DATA (_NL_CTYPE_WIDTH,
 		      ctype->width, ctype->plane_size * ctype->plane_cnt);
 
+	  CTYPE_DATA (_NL_CTYPE_MB_CUR_MAX,
+		      &ctype->mb_cur_max, sizeof (u_int32_t));
+
 	  default:
 	    assert (! "unknown CTYPE element");
 	  }
@@ -1372,4 +1376,10 @@ Computing table size for character classes might take a while..."),
 		= charset->width_rules[cnt].width;
 	    }
     }
+
+  /* Compute MB_CUR_MAX.  Please note the value mb_cur_max in the
+     character set definition gives the number of bytes in the wide
+     character representation.  We compute the number of bytes used
+     for the UTF-8 encoded form.  */
+  ctype->mb_cur_max = ((int []) { 2, 3, 5, 6 }) [charset->mb_cur_max - 1];
 }
diff --git a/login/getutid_r.c b/login/getutid_r.c
index 351f96e65e..02013c29b9 100644
--- a/login/getutid_r.c
+++ b/login/getutid_r.c
@@ -18,6 +18,7 @@ not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
 #include <errno.h>
+#include <string.h>
 #include <unistd.h>
 #include <utmp.h>
 
@@ -28,6 +29,18 @@ int
 getutid_r (const struct utmp *id, struct utmp **utmp,
 	   struct utmp_data *utmp_data)
 {
+#if (_HAVE_UT_ID - 0) && (_HAVE_UT_TYPE - 0)
+  /* Test whether ID has any of the legal types.  */
+  if (id->ut_type != RUN_LVL && id->ut_type != BOOT_TIME
+      && id->ut_type != OLD_TIME && id->ut_type != NEW_TIME
+      && id->ut_type != INIT_PROCESS && id->ut_type != LOGIN_PROCESS
+      && id->ut_type != USER_PROCESS && id->ut_type != DEAD_PROCESS)
+    /* No, using '<' and '>' for the test is not possible.  */
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
   /* Open utmp file if not already done.  */
   if (utmp_data->ut_fd == -1)
     {
@@ -40,7 +53,7 @@ getutid_r (const struct utmp *id, struct utmp **utmp,
   if (lseek (utmp_data->ut_fd, utmp_data->loc_utmp, SEEK_SET) == -1)
     return -1;
 
-  do
+  while (1)
     {
       /* Read the next entry.  */
       if (read (utmp_data->ut_fd, &utmp_data->ubuf, sizeof (struct utmp))
@@ -52,10 +65,27 @@ getutid_r (const struct utmp *id, struct utmp **utmp,
 
       /* Update position pointer.  */
       utmp_data->loc_utmp += sizeof (struct utmp);
+
+      if ((id->ut_type == RUN_LVL || id->ut_type == BOOT_TIME
+	   || id->ut_type == OLD_TIME || id->ut_type == NEW_TIME)
+	  && id->ut_type != utmp_data->ubuf.ut_type)
+	/* Stop at the next entry with type RUN_LVL, BOOT_TIME,
+	   OLD_TIME, or NEW_TIME.  */
+	break;
+
+      if ((id->ut_type == INIT_PROCESS || id->ut_type == LOGIN_PROCESS
+	   || id->ut_type == USER_PROCESS || id->ut_type == DEAD_PROCESS)
+	  && strncmp (id->ut_id, utmp_data->ubuf.ut_id, sizeof id->ut_id) == 0)
+	/* Stop at the next entry with the specified ID and with type
+	   INIT_PROCESS, LOGIN_PROCESS, USER_PROCESS, or DEAD_PROCESS.  */
+	break;
     }
-  while (id->ut_type != utmp_data->ubuf.ut_type);
 
   *utmp = &utmp_data->ubuf;
 
   return 0;
+#else	/* !_HAVE_UT_ID && !_HAVE_UT_TYPE */
+  errno = ENOSYS;
+  return -1;
+#endif
 }
diff --git a/login/getutline_r.c b/login/getutline_r.c
index 8df48786dd..0956164eab 100644
--- a/login/getutline_r.c
+++ b/login/getutline_r.c
@@ -18,9 +18,9 @@ not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
 #include <errno.h>
+#include <string.h>
 #include <unistd.h>
 #include <utmp.h>
-#include <string.h>
 
 
 /* For implementing this function we don't use the getutent_r function
@@ -41,7 +41,7 @@ getutline_r (const struct utmp *line, struct utmp **utmp,
   if (lseek (utmp_data->ut_fd, utmp_data->loc_utmp, SEEK_SET) == -1)
     return -1;
 
-  do
+  while (1)
     {
       /* Read the next entry.  */
       if (read (utmp_data->ut_fd, &utmp_data->ubuf, sizeof (struct utmp))
@@ -53,9 +53,24 @@ getutline_r (const struct utmp *line, struct utmp **utmp,
 
       /* Update position pointer.  */
       utmp_data->loc_utmp += sizeof (struct utmp);
+
+#if _HAVE_UT_TYPE - 0
+      if (utmp_data->ubuf.ut_type == USER_PROCESS
+	  && strncmp (line->ut_line, utmp_data->ubuf.ut_line,
+		      sizeof line->ut_line) == 0)
+	/* Stop if we found an user entry.  */
+	break;
+
+      if (utmp_data->ubuf.ut_type == LOGIN_PROCESS)
+	/* Stop if we found a login entry.  */
+	break;
+#else	/* !_HAVE_UT_TYPE */
+      if (strncmp (line->ut_line, utmp_data->ubuf.ut_line,
+		      sizeof line->ut_line) == 0)
+	/* Stop if the line match.  */
+	break;
+#endif
     }
-  while (strncmp (line->ut_line, utmp_data->ubuf.ut_line,
-		  sizeof line->ut_line));
 
   *utmp = &utmp_data->ubuf;
 
diff --git a/login/login.c b/login/login.c
index 5b71082c52..f74ce41ad8 100644
--- a/login/login.c
+++ b/login/login.c
@@ -1,63 +1,101 @@
-/*
- * Copyright (c) 1988, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)login.c	8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/types.h>
-
-#include <fcntl.h>
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+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 <errno.h>
+#include <limits.h>
+#include <string.h>
 #include <unistd.h>
-#include <stdlib.h>
 #include <utmp.h>
-#include <stdio.h>
+
 
 void
-login(ut)
-	const struct utmp *ut;
+login (const struct utmp *ut)
 {
-	register int fd;
-	int tty;
-
-	tty = ttyslot();
-	if (tty > 0 && (fd = open(_PATH_UTMP, O_WRONLY|O_CREAT, 0644)) >= 0) {
-		(void)lseek(fd, (off_t)(tty * sizeof(struct utmp)), L_SET);
-		(void)write(fd, ut, sizeof(struct utmp));
-		(void)close(fd);
+  char tty[PATH_MAX + UT_LINESIZE];
+  int found_tty;
+  const char *ttyp;
+  struct utmp_data data;
+
+  /* Seek tty.  */
+  found_tty = ttyname_r (STDIN_FILENO, tty, sizeof tty);
+  if (found_tty < 0)
+    found_tty = ttyname_r (STDOUT_FILENO, tty, sizeof tty);
+  if (found_tty < 0)
+    found_tty = ttyname_r (STDERR_FILENO, tty, sizeof tty);
+
+  if (found_tty >= 0)
+    {
+      /* Tell that we want to use the UTMP file.  */
+      if (utmpname (_PATH_UTMP) != 0)
+	{
+	  struct utmp tmp;
+	  struct utmp *old;
+
+	  /* Open UTMP file.  */
+	  setutent_r (&data);
+
+	  /* We only want to insert the name of the tty without path.  */
+	  ttyp = basename (tty);
+
+	  /* Position to record for this tty.  */
+#if _HAVE_UT_TYPE - 0
+	  tmp.ut_type = USER_PROCESS;
+#endif
+	  strncpy (tmp.ut_line, ttyp, UT_LINESIZE);
+
+	  /* Read the record.  */
+	  if (getutline_r (&tmp, &old, &data) >= 0 || errno == ESRCH)
+	    {
+#if _HAVE_UT_TYPE - 0
+	      /* We have to fake the old entry because this `login'
+		 function does not fit well into the UTMP file
+		 handling scheme.  */
+	      old->ut_type = ut->ut_type;
+#endif
+	      pututline_r (ut, &data);
+	    }
+
+	  /* Close UTMP file.  */
+	  endutent_r (&data);
 	}
-	if ((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0)) >= 0) {
-		(void)write(fd, ut, sizeof(struct utmp));
-		(void)close(fd);
+    }
+
+  /* Update the WTMP file.  Here we have to add a new entry.  */
+  if (utmpname (_PATH_WTMP) != 0)
+    {
+      /* Open the WTMP file.  */
+      setutent_r (&data);
+
+      /* Position at end of file.  */
+      data.loc_utmp = lseek (data.ut_fd, 0, SEEK_END);
+      if (data.loc_utmp != -1)
+	{
+#if _HAVE_UT_TYPE - 0
+	  /* We have to fake the old entry because this `login'
+	     function does not fit well into the UTMP file handling
+	     scheme.  */
+	  data.ubuf.ut_type = ut->ut_type;
+#endif
+	  pututline_r (ut, &data);
 	}
+
+      /* Close WTMP file.  */
+      endutent_r (&data);
+    }
 }
diff --git a/login/logout.c b/login/logout.c
index 40ae25456f..d47a392699 100644
--- a/login/logout.c
+++ b/login/logout.c
@@ -1,72 +1,67 @@
-/*
- * Copyright (c) 1988, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
 
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)logout.c	8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
+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.
 
-#include <sys/types.h>
-#include <sys/time.h>
+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.
 
-#include <fcntl.h>
-#include <utmp.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
+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.  */
 
-typedef struct utmp UTMP;
+#include <errno.h>
+#include <string.h>
+#include <utmp.h>
+#include <sys/time.h>
 
 int
-logout(line)
-	register const char *line;
+logout (const char *line)
 {
-	register int fd;
-	UTMP ut;
-	int rval;
+  struct utmp_data data;
+  struct utmp tmp;
+  struct utmp *ut;
+  int result = 0;
+
+  /* Tell that we want to use the UTMP file.  */
+  if (utmpname (_PATH_UTMP) == 0)
+    return 0;
+
+  /* Open UTMP file.  */
+  setutent_r (&data);
+
+  /* Fill in search information.  */
+#if _HAVE_UT_TYPE - 0
+  tmp.ut_type = USER_PROCESS;
+#endif
+  strncpy (tmp.ut_line, line, UT_LINESIZE);
+
+  /* Read the record.  */
+  if (getutline_r (&tmp, &ut, &data) >= 0 || errno == ESRCH)
+    {
+      /* Clear information about who & from where.  */
+      bzero (ut->ut_name, UT_NAMESIZE);
+      bzero (ut->ut_host, UT_HOSTSIZE);
+
+#if _HAVE_UT_TV - 0
+      gettimeofday (&ut->ut_tv, NULL);
+#else
+      time (&ut->ut_time);
+#endif
+
+      if (pututline_r (ut, &data) >= 0)
+	result = 1;
+    }
+
+  /* Close UTMP file.  */
+  endutent_r (&data);
 
-	if ((fd = open(_PATH_UTMP, O_RDWR, 0)) < 0)
-		return(0);
-	rval = 0;
-	while (read(fd, &ut, sizeof(UTMP)) == sizeof(UTMP)) {
-		if (!ut.ut_name[0] || strncmp(ut.ut_line, line, UT_LINESIZE))
-			continue;
-		bzero(ut.ut_name, UT_NAMESIZE);
-		bzero(ut.ut_host, UT_HOSTSIZE);
-		(void)time(&ut.ut_time);
-		(void)lseek(fd, -(off_t)sizeof(UTMP), L_INCR);
-		(void)write(fd, &ut, sizeof(UTMP));
-		rval = 1;
-	}
-	(void)close(fd);
-	return(rval);
+  return result;
 }
diff --git a/login/logwtmp.c b/login/logwtmp.c
index 7734ca9624..10f7384f6c 100644
--- a/login/logwtmp.c
+++ b/login/logwtmp.c
@@ -1,67 +1,64 @@
-/*
- * Copyright (c) 1988, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
 
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)logwtmp.c	8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
+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.
 
-#include <sys/types.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-#include <time.h>
-#include <string.h>
+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 <string.h>
 #include <unistd.h>
 #include <utmp.h>
 
+
 void
-logwtmp(line, name, host)
-     const char *line, *name, *host;
+logwtmp (const char *line, const char *name, const char *host)
 {
-	struct utmp ut;
-	struct stat buf;
-	int fd;
+  struct utmp_data data;
+  struct utmp ut;
+
+  /* Tell that we want to use the UTMP file.  */
+  if (utmpname (_PATH_WTMP) == 0)
+    return;
+
+  /* Open UTMP file.  */
+  setutent_r (&data);
+
+  /* Position at end of file.  */
+  data.loc_utmp = lseek (data.ut_fd, 0, SEEK_END);
+  if (data.loc_utmp == -1)
+    return;
+
+  /* Set information in new entry.  */
+  bzero (&ut, sizeof (ut));
+#if _HAVE_UT_TYPE - 0
+  ut.ut_type = USER_PROCESS;
+#endif
+  strncpy (ut.ut_line, line, UT_LINESIZE);
+  strncpy (ut.ut_name, name, UT_NAMESIZE);
+  strncpy (ut.ut_host, host, UT_HOSTSIZE);
+
+#if _HAVE_UT_TV - 0
+  gettimeofday (&ut.ut_tv, NULL);
+#else
+  time (&ut.ut_time);
+#endif
+
+  /* Write the entry.  */
+  pututline_r (&ut, &data);
+
+  /* Close UTMP file.  */
+  endutent_r (&data);
 
-	if ((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0)) < 0)
-		return;
-	if (fstat(fd, &buf) == 0) {
-		(void) strncpy(ut.ut_line, line, sizeof(ut.ut_line));
-		(void) strncpy(ut.ut_name, name, sizeof(ut.ut_name));
-		(void) strncpy(ut.ut_host, host, sizeof(ut.ut_host));
-		(void) time(&ut.ut_time);
-		if (write(fd, (char *)&ut, sizeof(struct utmp)) !=
-		    sizeof(struct utmp))
-			(void) ftruncate(fd, buf.st_size);
-	}
-	(void) close(fd);
 }
diff --git a/login/pututline_r.c b/login/pututline_r.c
index 92ba8fb308..07322e5740 100644
--- a/login/pututline_r.c
+++ b/login/pututline_r.c
@@ -26,9 +26,29 @@ Boston, MA 02111-1307, USA.  */
 #include <sys/file.h>
 
 
+/* XXX An alternative solution would be to call a SUID root program
+   which write the new value.  */
+
 int
 pututline_r (const struct utmp *utmp_ptr, struct utmp_data *utmp_data)
 {
+  struct stat st;
+  int result = 0;
+
+#if _HAVE_UT_TYPE - 0
+  /* Test whether ID has any of the legal types because we have to
+     prevent illegal entries.  */
+  if (id->ut_type != RUN_LVL && id->ut_type != BOOT_TIME
+      && id->ut_type != OLD_TIME && id->ut_type != NEW_TIME
+      && id->ut_type != INIT_PROCESS && id->ut_type != LOGIN_PROCESS
+      && id->ut_type != USER_PROCESS && id->ut_type != DEAD_PROCESS)
+    /* No, using '<' and '>' for the test is not possible.  */
+    {
+      errno = EINVAL;
+      return -1;
+    }
+#endif
+
   /* Open utmp file if not already done.  */
   if (utmp_data->ut_fd == -1)
     {
@@ -37,12 +57,14 @@ pututline_r (const struct utmp *utmp_ptr, struct utmp_data *utmp_data)
 	return -1;
     }
 
+#if _HAVE_UT_TYPE - 0
   /* Seek position to write.  */
   if (utmp_data->ubuf.ut_type != utmp_ptr->ut_type)
     {
       /* We must not overwrite the data in UTMP_DATA.  */
       struct utmp_data *data_tmp = alloca (sizeof (utmp_data));
       struct utmp *dummy;
+      off_t new_pos;
 
       *data_tmp = *utmp_data;
       utmp_data = data_tmp;
@@ -50,23 +72,25 @@ pututline_r (const struct utmp *utmp_ptr, struct utmp_data *utmp_data)
       if (getutid_r (utmp_ptr, &dummy, utmp_data) < 0)
 	{
 	  if (errno != ESRCH)
+	    /* Some error occured.  If no entry was found, the position
+	       pointer now is at the end of the file.  */
 	    return -1;
 
-	  utmp_data->loc_utmp = lseek (utmp_data->ut_fd, 0, SEEK_END);
-	  if (utmp_data->loc_utmp == -1)
-	    return -1;
-	}
+	  /* Set position pointer to position after adding of the record.  */
+	  utmp_data->loc_utmp += sizeof (struct utmp);
     }
+#endif
+
+  /* Find out how large the file is.  */
+  if (fstat (utmp_data->ut_fd, &st) < 0)
+    return -1;
 
   /* Position file correctly.  */
-  if (utmp_data->loc_utmp > 0
+  if (utmp_data->loc_utmp <= st.st_size
       && lseek (utmp_data->ut_fd, utmp_data->loc_utmp - sizeof (struct utmp),
 		SEEK_SET) < 0)
     return -1;
 
-  /* XXX An alternative solution would be to call an SUID root program
-     which write the new value.  */
-
   /* Try to lock the file.  */
   if (flock (utmp_data->ut_fd, LOCK_EX | LOCK_NB) < 0 && errno != ENOSYS)
     {
@@ -78,12 +102,22 @@ pututline_r (const struct utmp *utmp_ptr, struct utmp_data *utmp_data)
     }
 
   /* Write the new data.  */
-  if (write (utmp_data->ut_fd, &utmp_data->ubuf, sizeof (struct utmp))
+  if (write (utmp_data->ut_fd, utmp_ptr, sizeof (struct utmp))
       != sizeof (struct utmp))
-    return -1;
+    {
+      /* If we appended a new record this is only partially written.
+	 Remove it.  */
+      if (utmp_data->loc_utmp > st.st_size)
+	{
+	  (void) ftruncate (utmp_data->ut_fd, st.st_size);
+	  utmp_data->loc_utmp = st.st_size;
+	}
+
+      result = -1;
+    }
 
   /* And unlock the file.  */
   (void) flock (utmp_data->ut_fd, LOCK_UN);
 
-  return 0;
+  return result;
 }
diff --git a/login/setutent_r.c b/login/setutent_r.c
index 715101d659..4b980cf1a7 100644
--- a/login/setutent_r.c
+++ b/login/setutent_r.c
@@ -52,7 +52,9 @@ setutent_r (struct utmp_data *utmp_data)
 
   /* Remember we are at beginning of file.  */
   utmp_data->loc_utmp = 0;
-  utmp_data->ubuf.ut_type = -1;
+#if _HAVE_UT_TYPE - 0
+  utmp_data->ubuf.ut_type = UT_UNKNOWN;
+#endif
 }
 
 
diff --git a/stdlib/stdlib.h b/stdlib/stdlib.h
index 97b257248e..d34f56256a 100644
--- a/stdlib/stdlib.h
+++ b/stdlib/stdlib.h
@@ -70,9 +70,9 @@ typedef struct
 #define	EXIT_SUCCESS	0	/* Successful exit status.  */
 
 
-/* Maximum length of a multibyte character in the current locale.
-   This is just one until the fancy locale support is finished.  */
-#define	MB_CUR_MAX	1
+/* Maximum length of a multibyte character in the current locale.  */
+#define	MB_CUR_MAX	(__ctype_get_mb_cur_max ())
+extern int __ctype_get_mb_cur_max __P ((void));
 
 
 /* Convert a string to a floating-point number.  */
diff --git a/stdlib/strtol.c b/stdlib/strtol.c
index 3b073ce333..dd92fb250c 100644
--- a/stdlib/strtol.c
+++ b/stdlib/strtol.c
@@ -136,10 +136,8 @@ extern int errno;
 # define INTERNAL(x) INTERNAL1(x)
 # define INTERNAL1(x) __##x##_internal
 # define WEAKNAME(x) WEAKNAME1(x)
-# define WEAKNAME1(x) __##x
 #else
 # define INTERNAL(x) __/**/x/**/_internal
-# define WEAKNAME(x) __/**/x
 #endif
 
 #ifdef USE_NUMBER_GROUPING
@@ -322,7 +320,7 @@ INTERNAL (strtol) (nptr, endptr, base, group)
 
 noconv:
   /* We must handle a special case here: the base is 0 or 16 and the
-     first two characters and '0' and 'x', but the rest are no
+     first two characters are '0' and 'x', but the rest are no
      hexadecimal digits.  This is no error case.  We return 0 and
      ENDPTR points to the `x`.  */
   if (endptr != NULL)
@@ -337,24 +335,18 @@ noconv:
 }
 
 /* External user entry point.  */
-
-/* Prototype.  */
-INT WEAKNAME (strtol) __P ((const STRING_TYPE *nptr, STRING_TYPE **endptr,
-			    int base));
-
-
 INT
-WEAKNAME (strtol) (nptr, endptr, base)
+strtol (nptr, endptr, base)
      const STRING_TYPE *nptr;
      STRING_TYPE **endptr;
      int base;
 {
   return INTERNAL (strtol) (nptr, endptr, base, 0);
 }
-
-#ifdef weak_alias
-/* We need this indirection when `strtol' is defined as a macro
-   for one of the other names.  */
-#define weak1(x, y) weak_alias (x, y)
-weak1 (WEAKNAME (strtol), strtol)
+#ifdef weak_symbol
+/* We need to weaken this symbol because some the the defined
+   functions do not come from ANSI.  The indirection is necessary
+   because `strtol' might be a macro.  */
+#define weak_this(x) weak_symbol (x)
+weak_this (strtol)
 #endif
diff --git a/string/strtok.c b/string/strtok.c
deleted file mode 100644
index 954471322b..0000000000
--- a/string/strtok.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/* Copyright (C) 1991, 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 <errno.h>
-#include <string.h>
-
-
-static char *olds = NULL;
-
-/* Parse S into tokens separated by characters in DELIM.
-   If S is NULL, the last string strtok() was called with is
-   used.  For example:
-	char s[] = "-abc-=-def";
-	x = strtok(s, "-");		// x = "abc"
-	x = strtok(NULL, "-=");		// x = "def"
-	x = strtok(NULL, "=");		// x = NULL
-		// s = "abc\0-def\0"
-*/
-char *
-strtok (s, delim)
-     char *s;
-     const char *delim;
-{
-  char *token;
-
-  if (s == NULL)
-    {
-      if (olds == NULL)
-	{
-	  errno = EINVAL;
-	  return NULL;
-	}
-      else
-	s = olds;
-    }
-
-  /* Scan leading delimiters.  */
-  s += strspn (s, delim);
-  if (*s == '\0')
-    {
-      olds = NULL;
-      return NULL;
-    }
-
-  /* Find the end of the token.  */
-  token = s;
-  s = strpbrk (token, delim);
-  if (s == NULL)
-    /* This token finishes the string.  */
-    olds = NULL;
-  else
-    {
-      /* Terminate the token and make OLDS point past it.  */
-      *s = '\0';
-      olds = s + 1;
-    }
-  return token;
-}
diff --git a/sysdeps/gnu/utmpbits.h b/sysdeps/gnu/utmpbits.h
index 8b939cee86..e8c41f8814 100644
--- a/sysdeps/gnu/utmpbits.h
+++ b/sysdeps/gnu/utmpbits.h
@@ -77,7 +77,12 @@ struct utmp
 
 #define ut_time	ut_tv.tv_sec	/* Backwards compatibility.  */
 
+/* Tell the user that we have a modern system with UT_TYPE, UT_ID
+   and UT_TV fields.  */
+#define _HAVE_UT_TYPE	1
+#define _HAVE_UT_ID	1
+#define _HAVE_UT_TV	1
+
 __END_DECLS
 
 #endif /* !_UTMP_H_ */
-
diff --git a/sysdeps/libm-i387/e_exp.S b/sysdeps/libm-i387/e_exp.S
index 8c41ce09dd..3ed039bc87 100644
--- a/sysdeps/libm-i387/e_exp.S
+++ b/sysdeps/libm-i387/e_exp.S
@@ -10,14 +10,26 @@ RCSID("$NetBSD: e_exp.S,v 1.4 1995/05/08 23:47:04 jtc Exp $")
 /* e^x = 2^(x * log2(e)) */
 ENTRY(__ieee754_exp)
 	fldl	4(%esp)
+	fxam
+	fstsw	%ax
+	sahf
+	jnc	.LnoInf
+	jp	.LisInf
+.LnoInf:
 	fldl2e
 	fmulp				/* x * log2(e) */
 	fstl	%st(1)
 	frndint				/* int(x * log2(e)) */
 	fstl	%st(2)
 	fsubrp				/* fract(x * log2(e)) */
-	f2xm1				/* 2^(fract(x * log2(e))) - 1 */ 
+	f2xm1				/* 2^(fract(x * log2(e))) - 1 */
 	fld1
 	faddp				/* 2^(fract(x * log2(e))) */
 	fscale				/* e^x */
 	ret
+
+.LisInf:
+	andb	$2, %ah
+	jz	.LpInf
+	fldz
+.LpInf:	ret
diff --git a/utmp.h b/utmp.h
new file mode 100644
index 0000000000..c0c21a4436
--- /dev/null
+++ b/utmp.h
@@ -0,0 +1 @@
+#include <login/utmp.h>