update from main archive 961214 libc-961215
authordrepper <drepper>
Sun, 15 Dec 1996 02:14:01 +0000 (02:14 +0000)
committerdrepper <drepper>
Sun, 15 Dec 1996 02:14:01 +0000 (02:14 +0000)
76 files changed:
ChangeLog
FAQ
Makefile
hurd/hurdinit.c
hurd/hurdstartup.c
interp.c
libio/clearerr.c
libio/fgetc.c
libio/filedoalloc.c
libio/fileops.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/iopadn.c
libio/ioputs.c
libio/ioseekoff.c
libio/ioseekpos.c
libio/iosetbuffer.c
libio/iosetvbuf.c
libio/ioungetc.c
libio/iovsprintf.c
libio/iovsscanf.c
libio/libio.h
libio/libioP.h
login/utmp_file.c
md5-crypt/Makefile [new file with mode: 0644]
md5-crypt/md5-crypt.c [new file with mode: 0644]
md5-crypt/md5.c [new file with mode: 0644]
md5-crypt/md5.h [new file with mode: 0644]
md5-crypt/md5c-test.c [new file with mode: 0644]
md5-crypt/md5test.c [new file with mode: 0644]
nis/ypclnt.c
nss/Makefile
nss/XXX-lookup.c
nss/nss_dns/dns-host.c [deleted file]
nss/nss_dns/dns-network.c [deleted file]
nss/nsswitch.c
nss/nsswitch.h
nss/spwd-lookup.c
rellns-sh
resolv/Makefile
resolv/nss_dns/dns-host.c [new file with mode: 0644]
resolv/nss_dns/dns-network.c [new file with mode: 0644]
stdio-common/Makefile
stdio-common/fcloseall.c [new file with mode: 0644]
stdio-common/printf-parse.h
stdio-common/vfprintf.c
stdio/fclose.c
stdio/fflush.c
string/tst-strlen.c
sysdeps/generic/abort.c
sysdeps/mach/libc-lock.h
sysdeps/posix/fpathconf.c
sysdeps/posix/pathconf.c
sysdeps/stub/libc-lock.h
sysdeps/unix/inet/Subdirs
sysdeps/unix/sysv/linux/configure
sysdeps/unix/sysv/linux/configure.in
sysdeps/unix/sysv/linux/paths.h
time/localtime.c
time/strftime.c
time/tzset.c

index 4e03465..27ad480 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,141 @@
+Sun Dec 15 01:53:20 1996  Ulrich Drepper  <drepper@cygnus.com>
+
+       * Makefile (subdirs): Change crypt to md5-crypt.
+       * crypt/Makefile, crypt/md5-crypt.c, crypt/md5.c, crypt/md5.h,
+       crypt/md5c-test.c, crypt/md5test.c: Move to new directory
+       md5-crypt.
+       * sysdeps/unix/sysv/linux/configure.in: Refer to linuxthreads and
+       crypt instead of LinuxThreads and des-crypt.
+
+       * Makefile (subdirs): Add nss back.
+       * sysdeps/unix/inet/Subdirs: Move nis to end of file to fulfill
+       dependencies.
+
+       * libio/iofclose.c: Implement fclose(NULL) as closing all streams.
+       * stdio-common/Makefile (routines): Add fcloseall.
+       * stdio-common/fcloseall.c: New file.
+       * sysdeps/generic/abort.c: Make implementation POSIX.1 compatible.
+
+       * sysdeps/mach/libc-lock.h: Add definition of __libc_lock_trylock.
+       * sysdeps/stub/libc-lock.h: Define __libc_lock_trylock to always
+       return 0.
+
+       * stdio-common/printf.h: Define MIN and MAX only if not already
+       defined.
+
+       * stdio-common/vfprintf.c: Set errno to EBADF if stream does not
+       allow writing.  Required by POSIX.1.
+
+       * libio/libioP.h (CHECK_FILE): Use MAYBE_SET_EINVAL instead of
+       assignment.
+
+       * interp.c: Update copyright.
+       * libio/clearerr.c: Likewise.
+       * libio/ioseekoff.c: Likewise.
+       * libio/ioseekpos.c: Likewise.
+       * stdio/fclose.c: Likewise.
+       * stdio/fflus.c: Likewise.
+
+       * libio/libio.h [!_IO_MTSAFE_IO]: Define _IO_cleanup_region_start
+       and _IO_cleanup_region_end as empty.
+       * libio/fgetc.c: Use _IO_cleanup_region_start and
+       _IO_cleanup_region_end instead of __libc_cleanup_region_start and
+       __libc_cleanup_region_end.
+       * libio/fputc.c: Likewise.
+       * libio/freopen.c: Likewise.
+       * libio/fseek.c: Likewise.
+       * libio/getc.c: Likewise.
+       * libio/getchar.c: Likewise.
+       * libio/iofclose.c: Likewise.
+       * libio/iofflush.c: Likewise.
+       * libio/iofgetpos.c: Likewise.
+       * libio/iofgets.c: Likewise.
+       * libio/iofputs.c: Likewise.
+       * libio/iofread.c: Likewise.
+       * libio/iofsetpos.c: Likewise.
+       * libio/ioftell.c: Likewise.
+       * libio/iofwrite.c: Likewise.
+       * libio/iogetdelim.c: Likewise.
+       * libio/iogets.c: Likewise.
+       * libio/ioputs.c: Likewise.
+       * libio/iosetbuffer.c: Likewise.
+       * libio/iosetvbuf.c: Likewise.
+       * libio/ioungetc.c: Likewise.
+
+       * libio/iovspintf.c: Use cleanup handler to make sure no dangling
+       locks can stay over.
+       * libio/iovsscanf.c: Likewise.
+
+       * libio/genops.c: Use _IO_lock_init_recursive and _IO_lock_fini
+       instead of __libc_lock_init_recursive and __libc_lock_fini.
+
+       * libio/filedoalloc.c: Only use __isatty when compiling GNU libc.
+       Otherwise use isatty.
+       * libio/fileops.c: Likewise for __open and open.
+
+       * login/utmp_file.c (getutent_r_file): Use fcntl instead of
+       flock.
+
+       * nis/ypclnt.h: Add more casts to prevent warnings.
+
+       * nss/Makefile (services): Remove dns.
+       (libnss_dns, libnss_dns-inhibit-o): Remove definition.
+       ($(objpfx)libnss_dns.so): Removed.
+       * nss/nss_dns/dns-host.c, nss/nss_dns/dns-network.c: Moved to...
+       * resolv/nss_dns: ...here.
+       * resolv/Makefile (extra-libs): Add libnss_dns.
+       (libnss_dns-routines, libnss_dns-inhibit-o): Define as in
+       nss/Makefile.
+
+       * nss/XXX-lookup.c: Call __nss_database_lookup with new argument
+       specifying alternate name for entry in /etc/nsswitch.conf
+       * nss/nsswitch.c: If no entry with primary name is found in
+       /etc/nsswitch.conf try alternate name if given.
+       * nss/nsswitch.h: Add new parameter in prototype for
+       __nss_database_lookup.
+       * nss/spwd-lookup.c: Provide alternative entry name to look for.
+       This makes our NSS compatible with Solaris' nsswitch.conf files.
+
+       * string/tst-strlen.c: Change all counting variables to type size_t
+       to prevent warnings.
+
+       * sysdeps/posix/fpathconf.c: Update copyright.
+       * sysdeps/posix/pathconf.c: Don't call fpathconf to do the work.
+       Opening the file at this path may fail if it is a FIFO or pipe.
+
+       These changes make the time implementation POSIX.1 compliant.
+       * time/localtime.c (__localtime_r): Always call __tzset not only
+       if __tzset_run is zero.
+       * time/strftime.c: Add definition of memset_space to help to
+       reduce for systems which have memset.
+       (strftime): Don't use tm_zone member of argument for zone name.
+       Instead always use tzname[].
+       Call tzset() as required by POSIX.1 before any action.
+       * time/tzset.c (tzset): Set tzname[] as required by POSIX.1.
+       Remove global variable __tzset_run.  __tzset is now called always
+       when a dependent function is used.
+       (__tzset): Caching happens based on the contents of the
+       environment variable TZ.
+
+Fri Dec 13 01:06:52 1996  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+       * sysdeps/unix/sysv/linux/paths.h: Add _PATH_KLOG.
+
+Thu Dec 12 09:16:35 1996  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+       * rellns-sh: Correctly handle a relative source file name.
+
+Wed Dec 11 19:18:40 1996  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+       * login/utmp_file.c (setutent_file): Seek back to beginning of the
+       file if resetting.
+
+Thu Dec 12 16:39:12 1996  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+       * hurd/hurdinit.c (map0): Delete function.  Don't do this on
+       _hurd_preinit_hook.
+       * hurd/hurdstartup.c (_hurd_startup): Map page zero redzone here.
+
 Thu Dec 12 03:32:21 1996  Ulrich Drepper  <drepper@cygnus.com>
 
        * libio/_G_config.h: Add definition of _G_int16_t, _G_int32_t,
diff --git a/FAQ b/FAQ
index fbbae10..e5b18bf 100644 (file)
--- a/FAQ
+++ b/FAQ
@@ -71,6 +71,9 @@ please let me know.
 
 [Q19]  ``My XXX kernel emulates a floating-point coprocessor for me.
          Should I enable --with-fp?''
+
+[Q20]  ``How can I compile gcc 2.7.2.1 from the gcc source code using
+         glibc 2.x?
 \f
 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
 [Q1]   ``What systems does the GNU C Library run on?''
@@ -422,7 +425,7 @@ the package and tell the configuration script about these additional
 subdirectories using the --enable-add-ons option.  When you add the
 crypt add-on you just have to use
 
-       configure --enable-add-ons=des-crypt,XXX ...
+       configure --enable-add-ons=crypt,XXX ...
 
 where XXX are possible other add-ons and ... means the rest of the
 normal option list.
@@ -473,7 +476,7 @@ use it instead of the old libc.  In this case the needed startup files
 and libraries are not found in the regular places.  So the specs file
 must tell the compiler and linker exactly what to use.  Here is for
 example the gcc-2.7.2 specs file when GNU libc is installed at
-/home/gnu:
+/usr:
 
 -----------------------------------------------------------------------
 *asm:
@@ -483,28 +486,28 @@ example the gcc-2.7.2 specs file when GNU libc is installed at
 %{pipe:-}
 
 *cpp:
-%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{!m386:-D__i486__} %{posix:-D_POSIX_SOURCE} -I/home/gnu/include
+%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{!m386:-D__i486__} %{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}
 
 *cc1:
-
+%{profile:-p}
 
 *cc1plus:
 
 
 *endfile:
-%{!shared:crtend.o%s} %{shared:crtendS.o%s} /home/gnu/lib/crtn.o%s
+%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s
 
 *link:
--m elf_i386 -rpath=/home/gnu/lib -L/home/gnu/lib %{shared:-shared}   %{!shared:     %{!ibcs:       %{!static:  %{rdynamic:-export-dynamic}     %{!dynamic-linker:-dynamic-linker=/home/gnu/lib/ld.so.1}}       %{static:-static}}}
+-m elf_i386 %{shared:-shared}   %{!shared:     %{!ibcs:       %{!static:       %{rdynamic:-export-dynamic}     %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2}}  %{static:-static}}}
 
 *lib:
-%{!shared: %{mieee-fp:-lieee} %{p:-lc_p} %{!p:%{pg:-lc_p} %{!pg:-lc}}}
+%{!shared: %{pthread:-lpthread}        %{profile:-lc_p} %{!profile: -lc}}
 
 *libgcc:
-%{!shared:-lgcc}
+-lgcc
 
 *startfile:
-%{!shared: %{pg:/home/gnu/lib/gcrt1.o%s} %{!pg:%{p:/home/gnu/lib/gcrt1.o} %{!p:/home/gnu/lib/crt1.o%s}}} /home/gnu/lib/crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}
+%{!shared:      %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s}                  %{!p:%{profile:gcrt1.o%s}                         %{!profile:crt1.o%s}}}}    crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}
 
 *switches_need_spaces:
 
@@ -523,15 +526,15 @@ example the gcc-2.7.2 specs file when GNU libc is installed at
 
 -----------------------------------------------------------------------
 
-The above is currently correct for all systems but ix86/Linux.
-Because of compatibility issues on this platform the dynamic linker
-must have a different name: ld-linux.so.2.  So you have to replace
+The above is currently correct for ix86/Linux.  Because of
+compatibility issues on this platform the dynamic linker must have
+a different name: ld-linux.so.2.  So you have to replace
 
-       %{!dynamic-linker:-dynamic-linker=/home/gnu/lib/ld.so.1}
-by
        %{!dynamic-linker:-dynamic-linker=/home/gnu/lib/ld-linux.so.2}
+by
+       %{!dynamic-linker:-dynamic-linker=/home/gnu/lib/ld.so.1}
 
-in the above example specs file.
+in the above example specs file ti make it work for other systems.
 
 Future versions of GCC will automatically provide the correct specs.
 
@@ -583,11 +586,26 @@ invalid.  I.e., an emulated FPU is for the libc as good as a real one.
 
 
 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+[Q20]  ``How can I compile gcc 2.7.2.1 from the gcc source code using
+         glibc 2.x?
+
+[A20] {HJL} There is no support in gcc for glibc 2.0 before gcc 2.8. It
+is very tricky to compile gcc 2.7.2.1 using glibc 2.x. You have to
+build it manually or with one pass only. You also have to use the
+specs file in this FAQ while compiling gcc.
+
+A pre-compiled binary version of gcc 2.7.2.1 linked with glibc 2.x for
+Linux/x86 is available in the same directory at the glibc 2.x source
+code ftp sites.
+
+
+~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
 \f
 Answers were given by:
 {UD} Ulrich Drepper, <drepper@cygnus.com>
 {DMT} David Mosberger-Tang, <davidm@AZStarNet.com>
 {RM} Roland McGrath, <roland@gnu.ai.mit.edu>
+{HJL} H.J. Lu, <hjl@gnu.ai.mit.edu>
 \f
 Local Variables:
  mode:text
index 7ebd3b7..db83529 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -54,7 +54,8 @@ endif
 subdirs = csu assert ctype db locale intl catgets math setjmp signal stdlib \
          stdio-common $(stdio) $(malloc) string wcsmbs time dirent grp pwd \
          posix io termios resource misc login socket sysvipc gmon gnulib \
-         wctype manual shadow crypt $(sysdep-subdirs) nss elf po $(add-ons)
+         wctype manual shadow md5-crypt nss $(sysdep-subdirs) elf po \
+         $(add-ons)
 export subdirs := $(subdirs)   # Benign, useless in GNU make before 3.63.
 
 # The mach and hurd subdirectories have many generated header files which
index bc2334e..1704fa8 100644 (file)
@@ -203,23 +203,3 @@ _hurd_setproc (process_t procserver)
 
   return 0;
 }
-\f
-/* Map the page at address zero with no access allowed, so
-   dereferencing NULL will fault and no "anywhere" allocations
-   (e.g. the out of line memory containing the argument strings)
-   can be assigned address zero, which C says is not a valid pointer.
-
-   When dynamically linked, this should be done by the dynamic linker
-   before we run, but failing is harmless and we ignore the error.  */
-
-static void map0 (void) __attribute__ ((unused));
-text_set_element (_hurd_preinit_hook, map0);
-
-static void
-map0 (void)
-{
-  vm_address_t addr = 0;
-  __vm_map (__mach_task_self (),
-           &addr, __vm_page_size, 0, 0, MACH_PORT_NULL, 0, 1,
-           VM_PROT_NONE, VM_PROT_NONE, VM_INHERIT_COPY);
-}
index 17a7705..cd6922f 100644 (file)
@@ -75,6 +75,14 @@ _hurd_startup (void **argptr, void (*main) (int *data))
   char **argv, **envp;
   int argc, envc;
   int *argcptr;
+  vm_address_t addr;
+
+  /* Attempt to map page zero redzoned before we receive any RPC
+     data that might get allocated there.  We can ignore errors.  */
+  addr = 0;
+  __vm_map (__mach_task_self (),
+           &addr, __vm_page_size, 0, 0, MACH_PORT_NULL, 0, 1,
+           VM_PROT_NONE, VM_PROT_NONE, VM_INHERIT_COPY);
 
   if (err = __task_get_special_port (__mach_task_self (), TASK_BOOTSTRAP_PORT,
                                     &in_bootstrap))
index 722fb66..d8a1882 100644 (file)
--- a/interp.c
+++ b/interp.c
@@ -1,21 +1,21 @@
 /* interp - add information about dynamic loader to shared libray obejcts.
-Copyright (C) 1996 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
+   Copyright (C) 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 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.
+   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.  */
+   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.  */
 
 const char __invoke_dynamic_linker__[] __attribute__ ((section (".interp")))
   = RUNTIME_LINKER;
index 9dfdb11..7c7fb93 100644 (file)
@@ -1,20 +1,20 @@
 /* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
+   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 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.
+   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.  */
+   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"
index a754c4b..25bfed5 100644 (file)
@@ -31,9 +31,9 @@ fgetc (fp)
 {
   int result;
   CHECK_FILE (fp, EOF);
-  __libc_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
+  _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
   _IO_flockfile (fp);
   result = _IO_getc_unlocked (fp);
-  __libc_cleanup_region_end (1);
+  _IO_cleanup_region_end (1);
   return result;
 }
index f36bfb3..836c56b 100644 (file)
@@ -49,9 +49,12 @@ the executable file might be covered by the GNU General Public License. */
 #include <sys/stat.h>
 #ifdef __STDC__
 #include <stdlib.h>
+#include <unistd.h>
 #endif
+
 #ifdef _LIBC
-# include <unistd.h>
+# undef isatty
+# define isatty(Fd) __isatty (Fd)
 #endif
 
 /*
@@ -100,7 +103,7 @@ DEFUN(_IO_file_doallocate, (fp),
     }
   ALLOC_BUF(p, size, EOF);
   _IO_setb(fp, p, p+size, 1);
-  if (couldbetty && __isatty (fp->_fileno))
+  if (couldbetty && isatty(fp->_fileno))
     fp->_flags |= _IO_LINE_BUF;
   return 1;
 }
index 3294bef..dd1f573 100644 (file)
@@ -37,6 +37,11 @@ the executable file might be covered by the GNU General Public License. */
 extern int errno;
 #endif
 
+
+#ifdef _LIBC
+# define open(Name, Flags, Prot) __open ((Name), (Flags), (Prot))
+#endif
+
 /* An fstream can be in at most one of put mode, get mode, or putback mode.
    Putback mode is a variant of get mode.
 
@@ -177,7 +182,7 @@ DEFUN(_IO_file_fopen, (fp, filename, mode),
     omode = O_RDWR;
     read_write &= _IO_IS_APPENDING;
   }
-  fdesc = __open (filename, omode|oflags, oprot);
+  fdesc = open(filename, omode|oflags, oprot);
   if (fdesc < 0)
     return NULL;
   fp->_fileno = fdesc;
@@ -223,7 +228,7 @@ DEFUN(_IO_file_setbuf, (fp, p, len),
 }
 
 /* Write TO_DO bytes from DATA to FP.
-   Then mark FP has having empty buffers. */
+   Then mark FP as having empty buffers. */
 
 int
 DEFUN(_IO_do_write, (fp, data, to_do),
@@ -548,6 +553,10 @@ DEFUN(_IO_file_read, (fp, buf, size),
     {
       _IO_ssize_t count = _IO_read(fp->_fileno, buf, size);
 #if 0 && defined EINTR
+      /* We must not do this optimization since POSIX.1 explicitly
+        requests that the stream operations must return with the
+        error EINTR if this happens.  There must be the possibility
+        that stream operations time out.  --drepper  */
       if (count == -1 && errno == EINTR)
        continue;
 #endif
@@ -587,6 +596,10 @@ DEFUN(_IO_file_write, (f, data, n),
       if (count == EOF)
        {
 #if 0 && defined EINTR
+         /* We must not do this optimization since POSIX.1 explicitly
+            requests that the stream operations must return with the
+            error EINTR if this happens.  There must be the
+            possibility that stream operations time out.  --drepper  */
          if (errno == EINTR)
            continue;
          else
index 865ac8c..89359dc 100644 (file)
@@ -32,10 +32,10 @@ fputc (c, fp)
 {
   int result;
   CHECK_FILE (fp, EOF);
-  __libc_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
+  _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
   _IO_flockfile (fp);
   result = _IO_putc_unlocked (c, fp);
-  __libc_cleanup_region_end (1);
+  _IO_cleanup_region_end (1);
   return result;
 }
 
index 0b782dd..bb0c597 100644 (file)
@@ -35,9 +35,9 @@ freopen (filename, mode, fp)
   CHECK_FILE (fp, NULL);
   if (!(fp->_flags & _IO_IS_FILEBUF))
     return NULL;
-  __libc_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
+  _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
   _IO_flockfile (fp);
   result = _IO_freopen (filename, mode, fp);
-  __libc_cleanup_region_end (1);
+  _IO_cleanup_region_end (1);
   return result;
 }
index 61f2e92..3d4e492 100644 (file)
@@ -33,9 +33,9 @@ fseek (fp, offset, whence)
 {
   int result;
   CHECK_FILE (fp, -1);
-  __libc_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
+  _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
   _IO_flockfile (fp);
   result = _IO_fseek (fp, offset, whence);
-  __libc_cleanup_region_end (1);
+  _IO_cleanup_region_end (1);
   return result;
 }
index 52b8fc3..7679445 100644 (file)
@@ -466,7 +466,7 @@ DEFUN(_IO_init, (fp, flags),
   fp->_markers = NULL;
   fp->_cur_column = 0;
 #ifdef _IO_MTSAFE_IO
-  __libc_lock_init_recursive (*fp->_lock);
+  _IO_lock_init_recursive (*fp->_lock);
 #endif
 }
 
@@ -501,7 +501,7 @@ DEFUN(_IO_default_finish, (fp),
     }
 
 #ifdef _IO_MTSAFE_IO
-  __libc_lock_fini (*fp->_lock);
+  _IO_lock_fini (*fp->_lock);
 #endif
 
   _IO_un_link(fp);
index 0c0b6b8..eede639 100644 (file)
@@ -33,10 +33,10 @@ _IO_getc (fp)
 {
   int result;
   CHECK_FILE (fp, EOF);
-  __libc_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
+  _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
   _IO_flockfile (fp);
   result = _IO_getc_unlocked (fp);
-  __libc_cleanup_region_end (1);
+  _IO_cleanup_region_end (1);
   return result;
 }
 #undef getc
index d54ec58..aa67559 100644 (file)
@@ -31,11 +31,10 @@ int
 getchar ()
 {
   int result;
-  __libc_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
-                              stdin);
+  _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, stdin);
   _IO_flockfile (stdin);
   result = _IO_getc_unlocked (stdin);
-  __libc_cleanup_region_end (1);
+  _IO_cleanup_region_end (1);
   return result;
 }
 
index 77c7b50..79a0543 100644 (file)
@@ -33,21 +33,31 @@ _IO_fclose (fp)
 {
   int status;
 
-  CHECK_FILE(fp, EOF);
-
-  __libc_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
-  _IO_flockfile (fp);
-  if (fp->_IO_file_flags & _IO_IS_FILEBUF)
-    status = _IO_file_close_it (fp);
+  if (fp == NULL)
+    {
+      /* Close all streams.  */
+      _IO_cleanup ();
+      status = 0;
+    }
   else
-    status = fp->_flags & _IO_ERR_SEEN ? -1 : 0;
-  _IO_FINISH (fp);
-  __libc_cleanup_region_end (1);
-  if (fp != _IO_stdin && fp != _IO_stdout && fp != _IO_stderr)
     {
-      fp->_IO_file_flags = 0;
-      free(fp);
+      CHECK_FILE(fp, EOF);
+
+      _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
+      _IO_flockfile (fp);
+      if (fp->_IO_file_flags & _IO_IS_FILEBUF)
+       status = _IO_file_close_it (fp);
+      else
+       status = fp->_flags & _IO_ERR_SEEN ? -1 : 0;
+      _IO_FINISH (fp);
+      _IO_cleanup_region_end (1);
+      if (fp != _IO_stdin && fp != _IO_stdout && fp != _IO_stderr)
+       {
+         fp->_IO_file_flags = 0;
+         free(fp);
+       }
     }
+
   return status;
 }
 
index 385c962..af69486 100644 (file)
@@ -35,11 +35,10 @@ _IO_fflush (fp)
     {
       int result;
       CHECK_FILE (fp, EOF);
-      __libc_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
-                                  fp);
+      _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
       _IO_flockfile (fp);
       result = _IO_SYNC (fp) ? EOF : 0;
-      __libc_cleanup_region_end (1);
+      _IO_cleanup_region_end (1);
       return result;
     }
 }
index 07128c1..cae5df7 100644 (file)
@@ -33,10 +33,10 @@ _IO_fgetpos (fp, posp)
 {
   _IO_fpos_t pos;
   CHECK_FILE (fp, EOF);
-  __libc_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
+  _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
   _IO_flockfile (fp);
   pos = _IO_seekoff (fp, 0, _IO_seek_cur, 0);
-  __libc_cleanup_region_end (1);
+  _IO_cleanup_region_end (1);
   if (pos == _IO_pos_BAD)
     {
 #ifdef EIO
index 79ba1a9..7a1044f 100644 (file)
@@ -36,7 +36,7 @@ _IO_fgets (buf, n, fp)
   CHECK_FILE (fp, NULL);
   if (n <= 0)
     return NULL;
-  __libc_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
+  _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
   _IO_flockfile (fp);
   count = _IO_getline (fp, buf, n - 1, '\n', 1);
   if (count == 0 || (fp->_IO_file_flags & _IO_ERR_SEEN))
@@ -46,7 +46,7 @@ _IO_fgets (buf, n, fp)
       buf[count] = '\0';
       result = buf;
     }
-  __libc_cleanup_region_end (1);
+  _IO_cleanup_region_end (1);
   return result;
 }
 
index 6e94223..9ce3caa 100644 (file)
@@ -33,13 +33,13 @@ _IO_fputs (str, fp)
   _IO_size_t len = strlen (str);
   int result;
   CHECK_FILE (fp, EOF);
-  __libc_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
+  _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
   _IO_flockfile (fp);
   if (_IO_sputn (fp, str, len) != len)
     result = EOF;
   else
     result = 1;
-  __libc_cleanup_region_end (1);
+  _IO_cleanup_region_end (1);
   return result;
 }
 
index 8610b0c..5fed0d8 100644 (file)
@@ -36,10 +36,10 @@ _IO_fread (buf, size, count, fp)
   CHECK_FILE (fp, 0);
   if (bytes_requested == 0)
     return 0;
-  __libc_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
+  _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
   _IO_flockfile (fp);
   bytes_read = _IO_sgetn (fp, (char *) buf, bytes_requested);
-  __libc_cleanup_region_end (1);
+  _IO_cleanup_region_end (1);
   return bytes_requested == bytes_read ? count : bytes_read / size;
 }
 weak_alias (_IO_fread, fread)
index 52700f7..ec913e3 100644 (file)
@@ -32,7 +32,7 @@ _IO_fsetpos (fp, posp)
 {
   int result;
   CHECK_FILE (fp, EOF);
-  __libc_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
+  _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
   _IO_flockfile (fp);
   if (_IO_seekpos (fp, *posp, _IOS_INPUT|_IOS_OUTPUT) == _IO_pos_BAD)
     {
@@ -45,7 +45,7 @@ _IO_fsetpos (fp, posp)
     }
   else
     result = 0;
-  __libc_cleanup_region_end (1);
+  _IO_cleanup_region_end (1);
   return result;
 }
 
index 1fc7c55..7fe18f8 100644 (file)
@@ -32,10 +32,10 @@ _IO_ftell (fp)
 {
   _IO_pos_t pos;
   CHECK_FILE (fp, -1L);
-  __libc_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
+  _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
   _IO_flockfile (fp);
   pos = _IO_seekoff (fp, 0, _IO_seek_cur, 0);
-  __libc_cleanup_region_end (1);
+  _IO_cleanup_region_end (1);
   if (pos == _IO_pos_BAD)
     {
 #ifdef EIO
index 7767a94..542fa77 100644 (file)
@@ -36,10 +36,10 @@ _IO_fwrite (buf, size, count, fp)
   CHECK_FILE (fp, 0);
   if (request == 0)
     return 0;
-  __libc_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
+  _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
   _IO_flockfile (fp);
   written = _IO_sputn (fp, (const char *) buf, request);
-  __libc_cleanup_region_end (1);
+  _IO_cleanup_region_end (1);
   /* 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)
index d41bb6b..b1662e4 100644 (file)
@@ -52,7 +52,7 @@ _IO_getdelim (lineptr, n, delimiter, fp)
       return -1;
     }
   CHECK_FILE (fp, -1);
-  __libc_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
+  _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
   _IO_flockfile (fp);
   if (_IO_ferror_unlocked (fp))
     {
@@ -114,7 +114,7 @@ _IO_getdelim (lineptr, n, delimiter, fp)
   result = cur_len;
 
 unlock_return:
-  __libc_cleanup_region_end (1);
+  _IO_cleanup_region_end (1);
   return result;
 }
 
index b5611f2..0e87504 100644 (file)
@@ -33,8 +33,8 @@ _IO_gets (buf)
   int ch;
   char *retval;
 
-  __libc_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
-                              _IO_stdin);
+  _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
+                           _IO_stdin);
   _IO_flockfile (_IO_stdin);
   ch = _IO_getc_unlocked (_IO_stdin);
   if (ch == EOF)
@@ -57,10 +57,12 @@ _IO_gets (buf)
   buf[count] = 0;
   retval = buf;
 unlock_return:
-  __libc_cleanup_region_end (1);
+  _IO_cleanup_region_end (1);
   return retval;
 }
 
 weak_alias (_IO_gets, gets)
 
+#ifdef _LIBC
 link_warning (gets, "the `gets' function is dangerous and should not be used.")
+#endif
index 94166a3..be2c2a6 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
 Copyright (C) 1993 Free Software Foundation
 
 This file is part of the GNU IO Library.  This library is free
@@ -38,7 +38,7 @@ DEFUN(_IO_padn, (fp, pad, count),
   const char *padptr;
   register int i;
   _IO_size_t written = 0, w;
-  
+
   if (pad == ' ')
     padptr = blanks;
   else if (pad == '0')
@@ -55,7 +55,7 @@ DEFUN(_IO_padn, (fp, pad, count),
       if (w != PADSIZE)
        return written;
     }
-      
+
   if (i > 0)
     {
       w = _IO_sputn(fp, padptr, i);
index 34e68b9..c35ceb8 100644 (file)
@@ -30,7 +30,7 @@ _IO_puts (str)
 {
   int result;
   _IO_size_t len = strlen (str);
-  __libc_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
+  _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
                               _IO_stdout);
   _IO_flockfile (_IO_stdout);
   if (_IO_sputn (_IO_stdout, str, len) == len
@@ -38,7 +38,7 @@ _IO_puts (str)
     result = len + 1;
   else
     result = EOF;
-  __libc_cleanup_region_end (1);
+  _IO_cleanup_region_end (1);
   return result;
 }
 weak_alias (_IO_puts, puts)
index 1de4f7b..80720e5 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
 Copyright (C) 1993 Free Software Foundation
 
 This file is part of the GNU IO Library.  This library is free
@@ -13,8 +13,8 @@ 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 GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+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
index be68633..dfb3b16 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
 Copyright (C) 1993 Free Software Foundation
 
 This file is part of the GNU IO Library.  This library is free
@@ -13,8 +13,8 @@ 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 GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+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
index d14e5d4..09751af 100644 (file)
@@ -31,13 +31,13 @@ _IO_setbuffer (fp, buf, size)
      _IO_size_t size;
 {
   CHECK_FILE (fp, );
-  __libc_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
+  _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
   _IO_flockfile (fp);
   fp->_flags &= ~_IO_LINE_BUF;
   if (!buf)
     size = 0;
   (void) _IO_SETBUF (fp, buf, size);
-  __libc_cleanup_region_end (1);
+  _IO_cleanup_region_end (1);
 }
 
 weak_alias (_IO_setbuffer, setbuffer)
index 8ba9753..0bd6025 100644 (file)
@@ -37,7 +37,7 @@ _IO_setvbuf (fp, buf, mode, size)
 {
   int result;
   CHECK_FILE (fp, EOF);
-  __libc_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
+  _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
   _IO_flockfile (fp);
   switch (mode)
     {
@@ -90,7 +90,7 @@ _IO_setvbuf (fp, buf, mode, size)
     }
   result = _IO_SETBUF (fp, buf, size) == NULL ? EOF : 0;
 unlock_return:
-  __libc_cleanup_region_end (1);
+  _IO_cleanup_region_end (1);
   return result;
 }
 
index 180e789..d36b07a 100644 (file)
@@ -33,10 +33,10 @@ _IO_ungetc (c, fp)
   CHECK_FILE (fp, EOF);
   if (c == EOF)
     return EOF;
-  __libc_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
+  _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, fp);
   _IO_flockfile (fp);
   result = _IO_sputbackc (fp, (unsigned char) c);
-  __libc_cleanup_region_end (1);
+  _IO_cleanup_region_end (1);
   return result;
 }
 
index f0c9889..a4fc949 100644 (file)
@@ -43,8 +43,11 @@ _IO_vsprintf (string, format, args)
   _IO_init ((_IO_FILE *) &sf, 0);
   _IO_JUMPS ((_IO_FILE *) &sf) = &_IO_str_jumps;
   _IO_str_init_static ((_IO_FILE *) &sf, string, -1, string);
+  _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, &sf);
+  _IO_flockfile (&sf);
   ret = _IO_vfprintf ((_IO_FILE *) &sf, format, args);
   _IO_putc_unlocked ('\0', (_IO_FILE *) &sf);
+  _IO_cleanup_region_end (1);
   return ret;
 }
 
index 473b714..6546e2d 100644 (file)
@@ -13,8 +13,8 @@ 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 GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+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
@@ -29,6 +29,7 @@ int
 DEFUN(_IO_vsscanf, (string, format, args),
       const char *string AND const char *format AND _IO_va_list args)
 {
+  int ret;
   _IO_strfile sf;
 #ifdef _IO_MTSAFE_IO
   _IO_lock_t lock;
@@ -37,7 +38,11 @@ DEFUN(_IO_vsscanf, (string, format, args),
   _IO_init((_IO_FILE*)&sf, 0);
   _IO_JUMPS((_IO_FILE*)&sf) = &_IO_str_jumps;
   _IO_str_init_static ((_IO_FILE*)&sf, (char*)string, 0, NULL);
-  return _IO_vfscanf((_IO_FILE*)&sf, format, args, NULL);
+  _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile, &sf);
+  _IO_flockfile (&sf);
+  ret = _IO_vfscanf((_IO_FILE*)&sf, format, args, NULL);
+  _IO_cleanup_region_end (1);
+  return ret;
 }
 weak_alias (_IO_vsscanf, __vsscanf)
 weak_alias (_IO_vsscanf, vsscanf)
index 49f1d8c..f6293ec 100644 (file)
@@ -288,6 +288,8 @@ extern int _IO_ftrylockfile __P ((_IO_FILE *));
 # define _IO_flockfile(_fp) /**/
 # define _IO_funlockfile(_fp) /**/
 # define _IO_ftrylockfile(_fp) /**/
+# define _IO_cleanup_region_start(_fct, _fp) /**/
+# define _IO_cleanup_region_end(_Doit) /**/
 #endif /* !_IO_MTSAFE_IO */
 
 #ifdef __USE_REENTRANT
index c9a639a..1f8d890 100644 (file)
@@ -557,7 +557,7 @@ extern struct _IO_fake_stdiobuf _IO_stdin_buf, _IO_stdout_buf, _IO_stderr_buf;
        if ((FILE) == NULL) { MAYBE_SET_EINVAL; return RET; } \
        else { COERCE_FILE(FILE); \
               if (((FILE)->_IO_file_flags & _IO_MAGIC_MASK) != _IO_MAGIC) \
-         { errno = EINVAL; return RET; }}
+         { MAYBE_SET_EINVAL; return RET; }}
 #else
 #define CHECK_FILE(FILE,RET) \
        COERCE_FILE(FILE)
index 2bb6c92..c728d9a 100644 (file)
@@ -92,6 +92,8 @@ setutent_file (int reset)
     }
   else if (reset)
     {
+      lseek (file_fd, 0, SEEK_SET);
+
       /* Remember we are at beginning of file.  */
       file_offset = 0;
 
@@ -117,6 +119,7 @@ static int
 getutent_r_file (struct utmp *buffer, struct utmp **result)
 {
   int nbytes;
+  struct flock fl;                     /* Information struct for locking.  */
 
   /* Open utmp file if not already done.  */
   if (file_fd == INT_MIN)
@@ -129,10 +132,22 @@ getutent_r_file (struct utmp *buffer, struct utmp **result)
       return -1;
     }
 
+  /* XXX The following is not perfect.  Instead of locking the file itself
+     Marek Michalkiewicz <marekm@i17linuxb.ists.pwr.wroc.pl> suggests to
+     use an extra locking file.  */
+
+  /* Try to get the lock.  */
+  memset (&fl, '\0', sizeof (struct flock));
+  fl.l_type = F_WRLCK;
+  fl.l_whence = SEEK_SET;
+  result = fcntl (file_fd, F_SETLKW, &fl);
+
   /* Read the next entry.  */
-  flock (file_fd, LOCK_SH);
   nbytes = read (file_fd, &last_entry, sizeof (struct utmp));
-  flock (file_fd, LOCK_UN);
+
+  /* And unlock the file.  */
+  fl.l_type = F_UNLCK;
+  result = fcntl (file_fd, F_SETLKW, &fl);
 
   if (nbytes != sizeof (struct utmp))
     {
diff --git a/md5-crypt/Makefile b/md5-crypt/Makefile
new file mode 100644 (file)
index 0000000..4c461b0
--- /dev/null
@@ -0,0 +1,51 @@
+# Copyright (C) 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.
+
+#
+#      Sub-makefile for MD5 crypt portion of the library.
+#
+subdir := md5-crypt
+
+headers := crypt.h
+
+distribute := md5.h
+
+tests  := md5test md5c-test
+
+extra-libs := libcrypt
+extra-libs-others := $(extra-libs)
+
+libcrypt-routines := crypt-entry md5-crypt md5
+
+include ../Makeconfig
+
+rpath-link := $(common-objpfx)crypt:$(rpath-link)
+
+ifeq ($(crypt-in-libc),yes)
+routines += $(libcrypt-routines)
+endif
+
+include ../Rules
+
+ifeq ($(build-shared),yes)
+libdepend = $(common-objpfx)md5-crypt/libcrypt.so$(libcrypt.so-version)
+else
+libdepend = $(common-objpfx)md5-crypt/libcrypt.a
+endif
+
+$(objpfx)md5test $(objpfx)md5c-test: $(libdepend)
diff --git a/md5-crypt/md5-crypt.c b/md5-crypt/md5-crypt.c
new file mode 100644 (file)
index 0000000..308366c
--- /dev/null
@@ -0,0 +1,226 @@
+/* md5-crypt - One way encryption based on MD5 sum.
+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 <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+
+#include "md5.h"
+
+
+/* Define our magic string to mark salt for MD5 "encryption"
+   replacement.  This is meant to be the same as for other MD5 based
+   encryption implementations.  */
+static const char md5_salt_prefix[] = "$1$";
+
+/* Table with characters for base64 transformation.  */
+static const char b64t[64] =
+"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+
+/* Prototypes for local functions.  */
+extern char *md5_crypt_r __P ((const char *key, const char *salt, char *buffer,
+                              int buflen));
+extern char *md5_crypt __P ((const char *key, const char *salt));
+
+
+
+/* This entry point is equivalent to the `crypt' function in Unix
+   libcs.  */
+char *
+md5_crypt_r (key, salt, buffer, buflen)
+     const char *key;
+     const char *salt;
+     char *buffer;
+     int buflen;
+{
+  unsigned char alt_result[16];
+  struct md5_ctx ctx;
+  struct md5_ctx alt_ctx;
+  size_t salt_len;
+  size_t key_len;
+  size_t cnt;
+  char *cp;
+
+  /* Find beginning of salt string.  The prefix should normally always
+     be present.  Just in case it is not.  */
+  if (strncmp (md5_salt_prefix, salt, sizeof (md5_salt_prefix) - 1) == 0)
+    /* Skip salt prefix.  */
+    salt += sizeof (md5_salt_prefix) - 1;
+
+  salt_len = MIN (strcspn (salt, "$"), 8);
+  key_len = strlen (key);
+
+  /* Prepare for the real work.  */
+  md5_init_ctx (&ctx);
+
+  /* Add the key string.  */
+  md5_process_bytes (key, key_len, &ctx);
+
+  /* Because the SALT argument need not always have the salt prefix we
+     add it separately.  */
+  md5_process_bytes (md5_salt_prefix, sizeof (md5_salt_prefix) - 1, &ctx);
+
+  /* The last part is the salt string.  This must be at most 8
+     characters and it ends at the first `$' character (for
+     compatibility which existing solutions).  */
+  md5_process_bytes (salt, salt_len, &ctx);
+
+
+  /* Compute alternate MD5 sum with input KEY, SALT, and KEY.  The
+     final result will be added to the first context.  */
+  md5_init_ctx (&alt_ctx);
+
+  /* Add key.  */
+  md5_process_bytes (key, key_len, &alt_ctx);
+
+  /* Add salt.  */
+  md5_process_bytes (salt, salt_len, &alt_ctx);
+
+  /* Add key again.  */
+  md5_process_bytes (key, key_len, &alt_ctx);
+
+  /* Now get result of this (16 bytes) and add it to the other
+     context.  */
+  md5_finish_ctx (&alt_ctx, alt_result);
+
+  /* Add for any character in the key one byte of the alternate sum.  */
+  for (cnt = key_len; cnt > 16; cnt -= 16)
+    md5_process_bytes (alt_result, 16, &ctx);
+  md5_process_bytes (alt_result, cnt, &ctx);
+
+  /* For the following code we need a NUL byte.  */
+  *alt_result = '\0';
+
+  /* The original implementation now does something weird: for every 1
+     bit in the key the first 0 is added to the buffer, for every 0
+     bit the first character of the key.  This does not seem to be
+     what was intended but we have to follow this to be compatible.  */
+  for (cnt = key_len; cnt > 0; cnt >>= 1)
+    md5_process_bytes ((cnt & 1) != 0 ? (const char *) alt_result : key, 1,
+                      &ctx);
+
+  /* Create intermediate result.  */
+  md5_finish_ctx (&ctx, alt_result);
+
+  /* Now comes another weirdness.  In fear of password crackers here
+     comes a quite long loop which just processes the output of the
+     previous round again.  We cannot ignore this here.  */
+  for (cnt = 0; cnt < 1000; ++cnt)
+    {
+      /* New context.  */
+      md5_init_ctx (&ctx);
+
+      /* Add key or last result.  */
+      if ((cnt & 1) != 0)
+       md5_process_bytes (key, key_len, &ctx);
+      else
+       md5_process_bytes (alt_result, 16, &ctx);
+
+      /* Add salt for numbers not divisible by 3.  */
+      if (cnt % 3 != 0)
+       md5_process_bytes (salt, salt_len, &ctx);
+
+      /* Add key for numbers not divisible by 7.  */
+      if (cnt % 7 != 0)
+       md5_process_bytes (key, key_len, &ctx);
+
+      /* Add key or last result.  */
+      if ((cnt & 1) != 0)
+       md5_process_bytes (alt_result, 16, &ctx);
+      else
+       md5_process_bytes (key, key_len, &ctx);
+
+      /* Create intermediate result.  */
+      md5_finish_ctx (&ctx, alt_result);
+    }
+
+  /* Now we can construct the result string.  It consists of three
+     parts.  */
+  cp = stpncpy (buffer, md5_salt_prefix, MAX (0, buflen));
+  buflen -= sizeof (md5_salt_prefix);
+
+  cp = stpncpy (cp, salt, MIN ((size_t) buflen, salt_len));
+  buflen -= MIN ((size_t) buflen, salt_len);
+
+  if (buflen > 0)
+    {
+      *cp++ = '$';
+      --buflen;
+    }
+
+#define b64_from_24bit(B2, B1, B0, N)                                        \
+  do {                                                                       \
+    unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0);                              \
+    int n = (N);                                                             \
+    while (n-- > 0 && buflen > 0)                                            \
+      {                                                                              \
+       *cp++ = b64t[w & 0x3f];                                               \
+       --buflen;                                                             \
+       w >>= 6;                                                              \
+      }                                                                              \
+  } while (0)
+
+
+  b64_from_24bit (alt_result[0], alt_result[6], alt_result[12], 4);
+  b64_from_24bit (alt_result[1], alt_result[7], alt_result[13], 4);
+  b64_from_24bit (alt_result[2], alt_result[8], alt_result[14], 4);
+  b64_from_24bit (alt_result[3], alt_result[9], alt_result[15], 4);
+  b64_from_24bit (alt_result[4], alt_result[10], alt_result[5], 4);
+  b64_from_24bit (0, 0, alt_result[11], 2);
+  if (buflen <= 0)
+    {
+      __set_errno (ERANGE);
+      buffer = NULL;
+    }
+  else
+    *cp = '\0';                /* Terminate the string.  */
+
+  /* Clear the buffer for the intermediate result so that people
+     attaching to processes or reading core dumps cannot get any
+     information.  */
+  memset (alt_result, '\0', sizeof (alt_result));
+
+  return buffer;
+}
+
+
+char *
+md5_crypt (key, salt)
+     const char *key;
+     const char *salt;
+{
+  /* We don't want to have an arbitrary limit in the size of the
+     password.  We can compute the size of the result in advance and
+     so we can prepare the buffer we pass to `md5_crypt_r'.  */
+  static char *buffer = NULL;
+  static int buflen = 0;
+  int needed = 3 + strlen (salt) + 1 + 26 + 1;
+
+  if (buflen < needed)
+    {
+      buflen = needed;
+      if ((buffer = realloc (buffer, buflen)) == NULL)
+       return NULL;
+    }
+
+  return md5_crypt_r (key, salt, buffer, buflen);
+}
diff --git a/md5-crypt/md5.c b/md5-crypt/md5.c
new file mode 100644 (file)
index 0000000..d7b0f0e
--- /dev/null
@@ -0,0 +1,419 @@
+/* md5.c - Functions to compute MD5 message digest of files or memory blocks
+   according to the definition of MD5 in RFC 1321 from April 1992.
+   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.  */
+
+/* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+
+#if STDC_HEADERS || defined _LIBC
+# include <stdlib.h>
+# include <string.h>
+#else
+# ifndef HAVE_MEMCPY
+#  define memcpy(d, s, n) bcopy ((s), (d), (n))
+# endif
+#endif
+
+#include "md5.h"
+
+#ifdef _LIBC
+# include <endian.h>
+# if __BYTE_ORDER == __BIG_ENDIAN
+#  define WORDS_BIGENDIAN 1
+# endif
+#endif
+
+#ifdef WORDS_BIGENDIAN
+# define SWAP(n)                                                       \
+    (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
+#else
+# define SWAP(n) (n)
+#endif
+
+
+/* This array contains the bytes used to pad the buffer to the next
+   64-byte boundary.  (RFC 1321, 3.1: Step 1)  */
+static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ...  */ };
+
+
+/* Initialize structure containing state of computation.
+   (RFC 1321, 3.3: Step 3)  */
+void
+md5_init_ctx (ctx)
+     struct md5_ctx *ctx;
+{
+  ctx->A = 0x67452301;
+  ctx->B = 0xefcdab89;
+  ctx->C = 0x98badcfe;
+  ctx->D = 0x10325476;
+
+  ctx->total[0] = ctx->total[1] = 0;
+  ctx->buflen = 0;
+}
+
+/* Put result from CTX in first 16 bytes following RESBUF.  The result
+   must be in little endian byte order.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+void *
+md5_read_ctx (ctx, resbuf)
+     const struct md5_ctx *ctx;
+     void *resbuf;
+{
+  ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A);
+  ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B);
+  ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C);
+  ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D);
+
+  return resbuf;
+}
+
+/* Process the remaining bytes in the internal buffer and the usual
+   prolog according to the standard and write the result to RESBUF.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+void *
+md5_finish_ctx (ctx, resbuf)
+     struct md5_ctx *ctx;
+     void *resbuf;
+{
+  /* Take yet unprocessed bytes into account.  */
+  md5_uint32 bytes = ctx->buflen;
+  size_t pad;
+
+  /* Now count remaining bytes.  */
+  ctx->total[0] += bytes;
+  if (ctx->total[0] < bytes)
+    ++ctx->total[1];
+
+  pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
+  memcpy (&ctx->buffer[bytes], fillbuf, pad);
+
+  /* Put the 64-bit file length in *bits* at the end of the buffer.  */
+  *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP (ctx->total[0] << 3);
+  *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP ((ctx->total[1] << 3) |
+                                                       (ctx->total[0] >> 29));
+
+  /* Process last bytes.  */
+  md5_process_block (ctx->buffer, bytes + pad + 8, ctx);
+
+  return md5_read_ctx (ctx, resbuf);
+}
+
+/* Compute MD5 message digest for bytes read from STREAM.  The
+   resulting message digest number will be written into the 16 bytes
+   beginning at RESBLOCK.  */
+int
+md5_stream (stream, resblock)
+     FILE *stream;
+     void *resblock;
+{
+  /* Important: BLOCKSIZE must be a multiple of 64.  */
+#define BLOCKSIZE 4096
+  struct md5_ctx ctx;
+  char buffer[BLOCKSIZE + 72];
+  size_t sum;
+
+  /* Initialize the computation context.  */
+  md5_init_ctx (&ctx);
+
+  /* Iterate over full file contents.  */
+  while (1)
+    {
+      /* We read the file in blocks of BLOCKSIZE bytes.  One call of the
+        computation function processes the whole buffer so that with the
+        next round of the loop another block can be read.  */
+      size_t n;
+      sum = 0;
+
+      /* Read block.  Take care for partial reads.  */
+      do
+       {
+         n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
+
+         sum += n;
+       }
+      while (sum < BLOCKSIZE && n != 0);
+      if (n == 0 && ferror (stream))
+        return 1;
+
+      /* If end of file is reached, end the loop.  */
+      if (n == 0)
+       break;
+
+      /* Process buffer with BLOCKSIZE bytes.  Note that
+                       BLOCKSIZE % 64 == 0
+       */
+      md5_process_block (buffer, BLOCKSIZE, &ctx);
+    }
+
+  /* Add the last bytes if necessary.  */
+  if (sum > 0)
+    md5_process_bytes (buffer, sum, &ctx);
+
+  /* Construct result in desired memory.  */
+  md5_finish_ctx (&ctx, resblock);
+  return 0;
+}
+
+/* Compute MD5 message digest for LEN bytes beginning at BUFFER.  The
+   result is always in little endian byte order, so that a byte-wise
+   output yields to the wanted ASCII representation of the message
+   digest.  */
+void *
+md5_buffer (buffer, len, resblock)
+     const char *buffer;
+     size_t len;
+     void *resblock;
+{
+  struct md5_ctx ctx;
+
+  /* Initialize the computation context.  */
+  md5_init_ctx (&ctx);
+
+  /* Process whole buffer but last len % 64 bytes.  */
+  md5_process_bytes (buffer, len, &ctx);
+
+  /* Put result in desired memory area.  */
+  return md5_finish_ctx (&ctx, resblock);
+}
+
+
+void
+md5_process_bytes (buffer, len, ctx)
+     const void *buffer;
+     size_t len;
+     struct md5_ctx *ctx;
+{
+  /* When we already have some bits in our internal buffer concatenate
+     both inputs first.  */
+  if (ctx->buflen != 0)
+    {
+      size_t left_over = ctx->buflen;
+      size_t add = 128 - left_over > len ? len : 128 - left_over;
+
+      memcpy (&ctx->buffer[left_over], buffer, add);
+      ctx->buflen += add;
+
+      if (left_over + add > 64)
+       {
+         md5_process_block (ctx->buffer, (left_over + add) & ~63, ctx);
+         /* The regions in the following copy operation cannot overlap.  */
+         memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
+                 (left_over + add) & 63);
+         ctx->buflen = (left_over + add) & 63;
+       }
+
+      buffer = (const char *) buffer + add;
+      len -= add;
+    }
+
+  /* Process available complete blocks.  */
+  if (len > 64)
+    {
+      md5_process_block (buffer, len & ~63, ctx);
+      buffer = (const char *) buffer + (len & ~63);
+      len &= 63;
+    }
+
+  /* Move remaining bytes in internal buffer.  */
+  if (len > 0)
+    {
+      memcpy (ctx->buffer, buffer, len);
+      ctx->buflen = len;
+    }
+}
+
+
+/* These are the four functions used in the four steps of the MD5 algorithm
+   and defined in the RFC 1321.  The first function is a little bit optimized
+   (as found in Colin Plumbs public domain implementation).  */
+/* #define FF(b, c, d) ((b & c) | (~b & d)) */
+#define FF(b, c, d) (d ^ (b & (c ^ d)))
+#define FG(b, c, d) FF (d, b, c)
+#define FH(b, c, d) (b ^ c ^ d)
+#define FI(b, c, d) (c ^ (b | ~d))
+
+/* Process LEN bytes of BUFFER, accumulating context into CTX.
+   It is assumed that LEN % 64 == 0.  */
+
+void
+md5_process_block (buffer, len, ctx)
+     const void *buffer;
+     size_t len;
+     struct md5_ctx *ctx;
+{
+  md5_uint32 correct_words[16];
+  const md5_uint32 *words = buffer;
+  size_t nwords = len / sizeof (md5_uint32);
+  const md5_uint32 *endp = words + nwords;
+  md5_uint32 A = ctx->A;
+  md5_uint32 B = ctx->B;
+  md5_uint32 C = ctx->C;
+  md5_uint32 D = ctx->D;
+
+  /* First increment the byte count.  RFC 1321 specifies the possible
+     length of the file up to 2^64 bits.  Here we only compute the
+     number of bytes.  Do a double word increment.  */
+  ctx->total[0] += len;
+  if (ctx->total[0] < len)
+    ++ctx->total[1];
+
+  /* Process all bytes in the buffer with 64 bytes in each round of
+     the loop.  */
+  while (words < endp)
+    {
+      md5_uint32 *cwp = correct_words;
+      md5_uint32 A_save = A;
+      md5_uint32 B_save = B;
+      md5_uint32 C_save = C;
+      md5_uint32 D_save = D;
+
+      /* First round: using the given function, the context and a constant
+        the next context is computed.  Because the algorithms processing
+        unit is a 32-bit word and it is determined to work on words in
+        little endian byte order we perhaps have to change the byte order
+        before the computation.  To reduce the work for the next steps
+        we store the swapped words in the array CORRECT_WORDS.  */
+
+#define OP(a, b, c, d, s, T)                                           \
+      do                                                               \
+        {                                                              \
+         a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T;             \
+         ++words;                                                      \
+         CYCLIC (a, s);                                                \
+         a += b;                                                       \
+        }                                                              \
+      while (0)
+
+      /* It is unfortunate that C does not provide an operator for
+        cyclic rotation.  Hope the C compiler is smart enough.  */
+#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
+
+      /* Before we start, one word to the strange constants.
+        They are defined in RFC 1321 as
+
+        T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
+       */
+
+      /* Round 1.  */
+      OP (A, B, C, D,  7, 0xd76aa478);
+      OP (D, A, B, C, 12, 0xe8c7b756);
+      OP (C, D, A, B, 17, 0x242070db);
+      OP (B, C, D, A, 22, 0xc1bdceee);
+      OP (A, B, C, D,  7, 0xf57c0faf);
+      OP (D, A, B, C, 12, 0x4787c62a);
+      OP (C, D, A, B, 17, 0xa8304613);
+      OP (B, C, D, A, 22, 0xfd469501);
+      OP (A, B, C, D,  7, 0x698098d8);
+      OP (D, A, B, C, 12, 0x8b44f7af);
+      OP (C, D, A, B, 17, 0xffff5bb1);
+      OP (B, C, D, A, 22, 0x895cd7be);
+      OP (A, B, C, D,  7, 0x6b901122);
+      OP (D, A, B, C, 12, 0xfd987193);
+      OP (C, D, A, B, 17, 0xa679438e);
+      OP (B, C, D, A, 22, 0x49b40821);
+
+      /* For the second to fourth round we have the possibly swapped words
+        in CORRECT_WORDS.  Redefine the macro to take an additional first
+        argument specifying the function to use.  */
+#undef OP
+#define OP(f, a, b, c, d, k, s, T)                                     \
+      do                                                               \
+       {                                                               \
+         a += f (b, c, d) + correct_words[k] + T;                      \
+         CYCLIC (a, s);                                                \
+         a += b;                                                       \
+       }                                                               \
+      while (0)
+
+      /* Round 2.  */
+      OP (FG, A, B, C, D,  1,  5, 0xf61e2562);
+      OP (FG, D, A, B, C,  6,  9, 0xc040b340);
+      OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
+      OP (FG, B, C, D, A,  0, 20, 0xe9b6c7aa);
+      OP (FG, A, B, C, D,  5,  5, 0xd62f105d);
+      OP (FG, D, A, B, C, 10,  9, 0x02441453);
+      OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
+      OP (FG, B, C, D, A,  4, 20, 0xe7d3fbc8);
+      OP (FG, A, B, C, D,  9,  5, 0x21e1cde6);
+      OP (FG, D, A, B, C, 14,  9, 0xc33707d6);
+      OP (FG, C, D, A, B,  3, 14, 0xf4d50d87);
+      OP (FG, B, C, D, A,  8, 20, 0x455a14ed);
+      OP (FG, A, B, C, D, 13,  5, 0xa9e3e905);
+      OP (FG, D, A, B, C,  2,  9, 0xfcefa3f8);
+      OP (FG, C, D, A, B,  7, 14, 0x676f02d9);
+      OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
+
+      /* Round 3.  */
+      OP (FH, A, B, C, D,  5,  4, 0xfffa3942);
+      OP (FH, D, A, B, C,  8, 11, 0x8771f681);
+      OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
+      OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
+      OP (FH, A, B, C, D,  1,  4, 0xa4beea44);
+      OP (FH, D, A, B, C,  4, 11, 0x4bdecfa9);
+      OP (FH, C, D, A, B,  7, 16, 0xf6bb4b60);
+      OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
+      OP (FH, A, B, C, D, 13,  4, 0x289b7ec6);
+      OP (FH, D, A, B, C,  0, 11, 0xeaa127fa);
+      OP (FH, C, D, A, B,  3, 16, 0xd4ef3085);
+      OP (FH, B, C, D, A,  6, 23, 0x04881d05);
+      OP (FH, A, B, C, D,  9,  4, 0xd9d4d039);
+      OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
+      OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
+      OP (FH, B, C, D, A,  2, 23, 0xc4ac5665);
+
+      /* Round 4.  */
+      OP (FI, A, B, C, D,  0,  6, 0xf4292244);
+      OP (FI, D, A, B, C,  7, 10, 0x432aff97);
+      OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
+      OP (FI, B, C, D, A,  5, 21, 0xfc93a039);
+      OP (FI, A, B, C, D, 12,  6, 0x655b59c3);
+      OP (FI, D, A, B, C,  3, 10, 0x8f0ccc92);
+      OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
+      OP (FI, B, C, D, A,  1, 21, 0x85845dd1);
+      OP (FI, A, B, C, D,  8,  6, 0x6fa87e4f);
+      OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
+      OP (FI, C, D, A, B,  6, 15, 0xa3014314);
+      OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
+      OP (FI, A, B, C, D,  4,  6, 0xf7537e82);
+      OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
+      OP (FI, C, D, A, B,  2, 15, 0x2ad7d2bb);
+      OP (FI, B, C, D, A,  9, 21, 0xeb86d391);
+
+      /* Add the starting values of the context.  */
+      A += A_save;
+      B += B_save;
+      C += C_save;
+      D += D_save;
+    }
+
+  /* Put checksum in context given as argument.  */
+  ctx->A = A;
+  ctx->B = B;
+  ctx->C = C;
+  ctx->D = D;
+}
diff --git a/md5-crypt/md5.h b/md5-crypt/md5.h
new file mode 100644 (file)
index 0000000..e8ee9dc
--- /dev/null
@@ -0,0 +1,146 @@
+/* md5.h - Declaration of functions and data types used for MD5 sum
+   computing library functions.
+   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.  */
+
+#ifndef _MD5_H
+#define _MD5_H 1
+
+#include <stdio.h>
+
+#if defined HAVE_LIMITS_H || _LIBC
+# include <limits.h>
+#endif
+
+/* The following contortions are an attempt to use the C preprocessor
+   to determine an unsigned integral type that is 32 bits wide.  An
+   alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but
+   doing that would require that the configure script compile and *run*
+   the resulting executable.  Locally running cross-compiled executables
+   is usually not possible.  */
+
+#ifdef _LIBC
+# include <sys/types.h>
+typedef u_int32_t md5_uint32;
+#else
+# if defined __STDC__ && __STDC__
+#  define UINT_MAX_32_BITS 4294967295U
+# else
+#  define UINT_MAX_32_BITS 0xFFFFFFFF
+# endif
+
+/* If UINT_MAX isn't defined, assume it's a 32-bit type.
+   This should be valid for all systems GNU cares about because
+   that doesn't include 16-bit systems, and only modern systems
+   (that certainly have <limits.h>) have 64+-bit integral types.  */
+
+# ifndef UINT_MAX
+#  define UINT_MAX UINT_MAX_32_BITS
+# endif
+
+# if UINT_MAX == UINT_MAX_32_BITS
+   typedef unsigned int md5_uint32;
+# else
+#  if USHRT_MAX == UINT_MAX_32_BITS
+    typedef unsigned short md5_uint32;
+#  else
+#   if ULONG_MAX == UINT_MAX_32_BITS
+     typedef unsigned long md5_uint32;
+#   else
+     /* The following line is intended to evoke an error.
+        Using #error is not portable enough.  */
+     "Cannot determine unsigned 32-bit data type."
+#   endif
+#  endif
+# endif
+#endif
+
+#undef __P
+#if defined (__STDC__) && __STDC__
+#define        __P(x) x
+#else
+#define        __P(x) ()
+#endif
+
+/* Structure to save state of computation between the single steps.  */
+struct md5_ctx
+{
+  md5_uint32 A;
+  md5_uint32 B;
+  md5_uint32 C;
+  md5_uint32 D;
+
+  md5_uint32 total[2];
+  md5_uint32 buflen;
+  char buffer[128];
+};
+
+/*
+ * The following three functions are build up the low level used in
+ * the functions `md5_stream' and `md5_buffer'.
+ */
+
+/* Initialize structure containing state of computation.
+   (RFC 1321, 3.3: Step 3)  */
+extern void md5_init_ctx __P ((struct md5_ctx *ctx));
+
+/* Starting with the result of former calls of this function (or the
+   initialization function update the context for the next LEN bytes
+   starting at BUFFER.
+   It is necessary that LEN is a multiple of 64!!! */
+extern void md5_process_block __P ((const void *buffer, size_t len,
+                                   struct md5_ctx *ctx));
+
+/* Starting with the result of former calls of this function (or the
+   initialization function update the context for the next LEN bytes
+   starting at BUFFER.
+   It is NOT required that LEN is a multiple of 64.  */
+extern void md5_process_bytes __P ((const void *buffer, size_t len,
+                                   struct md5_ctx *ctx));
+
+/* Process the remaining bytes in the buffer and put result from CTX
+   in first 16 bytes following RESBUF.  The result is always in little
+   endian byte order, so that a byte-wise output yields to the wanted
+   ASCII representation of the message digest.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+extern void *md5_finish_ctx __P ((struct md5_ctx *ctx, void *resbuf));
+
+
+/* Put result from CTX in first 16 bytes following RESBUF.  The result is
+   always in little endian byte order, so that a byte-wise output yields
+   to the wanted ASCII representation of the message digest.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+extern void *md5_read_ctx __P ((const struct md5_ctx *ctx, void *resbuf));
+
+
+/* Compute MD5 message digest for bytes read from STREAM.  The
+   resulting message digest number will be written into the 16 bytes
+   beginning at RESBLOCK.  */
+extern int md5_stream __P ((FILE *stream, void *resblock));
+
+/* Compute MD5 message digest for LEN bytes beginning at BUFFER.  The
+   result is always in little endian byte order, so that a byte-wise
+   output yields to the wanted ASCII representation of the message
+   digest.  */
+extern void *md5_buffer __P ((const char *buffer, size_t len, void *resblock));
+
+#endif
diff --git a/md5-crypt/md5c-test.c b/md5-crypt/md5c-test.c
new file mode 100644 (file)
index 0000000..f56d0eb
--- /dev/null
@@ -0,0 +1,15 @@
+#include <crypt.h>
+#include <string.h>
+
+int
+main (int argc, char *argv[])
+{
+  const char salt[] = "$1$saltstring";
+  char *cp;
+  int result = 0;
+
+  cp = crypt ("Hello world!", salt);
+  result |= strcmp ("$1$saltstri$YMyguxXMBpd2TEZ.vS/3q1", cp);
+
+  return result;
+}
diff --git a/md5-crypt/md5test.c b/md5-crypt/md5test.c
new file mode 100644 (file)
index 0000000..abee788
--- /dev/null
@@ -0,0 +1,45 @@
+#include <string.h>
+#include "md5.h"
+
+static const struct
+{
+  const char *input;
+  const char result[16];
+} tests[] =
+  {
+    { "",
+      "\xd4\x1d\x8c\xd9\x8f\x00\xb2\x04\xe9\x80\x09\x98\xec\xf8\x42\x7e" },
+    { "a",
+      "\x0c\xc1\x75\xb9\xc0\xf1\xb6\xa8\x31\xc3\x99\xe2\x69\x77\x26\x61" },
+    { "abc",
+      "\x90\x01\x50\x98\x3c\xd2\x4f\xb0\xd6\x96\x3f\x7d\x28\xe1\x7f\x72" },
+    { "message digest",
+      "\xf9\x6b\x69\x7d\x7c\xb7\x93\x8d\x52\x5a\x2f\x31\xaa\xf1\x61\xd0" },
+    { "abcdefghijklmnopqrstuvwxyz",
+      "\xc3\xfc\xd3\xd7\x61\x92\xe4\x00\x7d\xfb\x49\x6c\xca\x67\xe1\x3b" },
+    { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+      "\xd1\x74\xab\x98\xd2\x77\xd9\xf5\xa5\x61\x1c\x2c\x9f\x41\x9d\x9f" },
+    { "123456789012345678901234567890123456789012345678901234567890"
+      "12345678901234567890",
+      "\x57\xed\xf4\xa2\x2b\xe3\xc9\x55\xac\x49\xda\x2e\x21\x07\xb6\x7a" }
+  };
+
+
+int
+main (int argc, char *argv[])
+{
+  struct md5_ctx ctx;
+  char sum[16];
+  int result = 0;
+  int cnt;
+
+  for (cnt = 0; cnt < (int) (sizeof (tests) / sizeof (tests[0])); ++cnt)
+    {
+      md5_init_ctx (&ctx);
+      md5_process_bytes (tests[cnt].input, strlen (tests[cnt].input), &ctx);
+      md5_finish_ctx (&ctx, sum);
+      result |= memcmp (tests[cnt].result, sum, 16);
+    }
+
+  return result;
+}
index 8e24ca4..d503434 100644 (file)
@@ -349,9 +349,9 @@ yp_match (const char *indomain, const char *inmap, const char *inkey,
       inkey == NULL || inkey[0] == '\0' || inkeylen <= 0)
     return YPERR_BADARGS;
 
-  req.domain = indomain;
-  req.map = inmap;
-  req.key.keydat_val = inkey;
+  req.domain = (char *) indomain;
+  req.map = (char *) inmap;
+  req.key.keydat_val = (char *) inkey;
   req.key.keydat_len = inkeylen;
 
   *outval = NULL;
@@ -389,8 +389,8 @@ yp_first (const char *indomain, const char *inmap, char **outkey,
       inmap == NULL || inmap[0] == '\0')
     return YPERR_BADARGS;
 
-  req.domain = indomain;
-  req.map = inmap;
+  req.domain = (char *) indomain;
+  req.map = (char *) inmap;
 
   *outkey = *outval = NULL;
   *outkeylen = *outvallen = 0;
@@ -433,9 +433,9 @@ yp_next (const char *indomain, const char *inmap, const char *inkey,
       inkeylen <= 0 || inkey == NULL || inkey[0] == '\0')
     return YPERR_BADARGS;
 
-  req.domain = indomain;
-  req.map = inmap;
-  req.key.keydat_val = inkey;
+  req.domain = (char *) indomain;
+  req.map = (char *) inmap;
+  req.key.keydat_val = (char *) inkey;
   req.key.keydat_len = inkeylen;
 
   *outkey = *outval = NULL;
@@ -476,8 +476,8 @@ yp_master (const char *indomain, const char *inmap, char **outname)
       inmap == NULL || inmap[0] == '\0')
     return YPERR_BADARGS;
 
-  req.domain = indomain;
-  req.map = inmap;
+  req.domain = (char *) indomain;
+  req.map = (char *) inmap;
 
   memset (&resp, '\0', sizeof (ypresp_master));
 
@@ -506,8 +506,8 @@ yp_order (const char *indomain, const char *inmap, unsigned int *outorder)
       inmap == NULL || inmap == '\0')
     return YPERR_BADARGS;
 
-  req.domain = indomain;
-  req.map = inmap;
+  req.domain = (char *) indomain;
+  req.map = (char *) inmap;
 
   memset (&resp, '\0', sizeof (resp));
 
@@ -622,8 +622,8 @@ yp_all (const char *indomain, const char *inmap,
          __libc_lock_unlock (ypbindlist_lock);
          return YPERR_PMAP;
        }
-      req.domain = indomain;
-      req.map = inmap;
+      req.domain = (char *) indomain;
+      req.map = (char *) inmap;
 
       ypall_foreach = incallback->foreach;
       ypall_data = (void *) incallback->data;
index ff3e039..a39f631 100644 (file)
@@ -36,7 +36,7 @@ databases             = proto service hosts network grp pwd rpc ethers \
                          spwd netgrp key alias
 
 # Specify rules for the nss_* modules.  We have some services.
-services               := files dns db
+services               := files db
 
 extra-libs             = $(services:%=libnss_%)
 # These libraries will be built in the `others' pass rather than
@@ -51,8 +51,6 @@ vpath %.c $(subdir-dirs)
 libnss_files-routines  := $(addprefix files-,$(filter-out key, $(databases)))
 distribute             += files-XXX.c files-parse.c
 
-libnss_dns-routines    := dns-host dns-network
-
 libnss_db-routines     := $(addprefix db-,$(filter-out hosts network key,\
                                                        $(databases)))
 generated              += $(filter-out db-alias.c db-netgrp.c, \
@@ -60,15 +58,12 @@ generated           += $(filter-out db-alias.c db-netgrp.c, \
 distribute             += db-XXX.c
 
 libnss_files-inhibit-o = $(filter-out .so,$(object-suffixes))
-libnss_dns-inhibit-o   = $(filter-out .so,$(object-suffixes))
 libnss_db-inhibit-o    = $(filter-out .so,$(object-suffixes))
 
 
 include ../Rules
 
 
-$(objpfx)libnss_dns.so: $(common-objpfx)resolv/libresolv.so
-
 $(objpfx)libnss_db.so: $(common-objpfx)db/libdb.so $(objpfx)libnss_files.so
 
 $(libnss_db-routines:%=$(objpfx)%.c): $(objpfx)db-%.c: nss_files/files-%.c
index 1b43018..67a3be1 100644 (file)
@@ -1,21 +1,21 @@
 /* Copyright (C) 1996 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
-Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+   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 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.
+   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.  */
+   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 "nsswitch.h"
 
@@ -40,6 +40,12 @@ Boston, MA 02111-1307, USA.  */
 #define STRINGIFY1(Name) STRINGIFY2 (Name)
 #define STRINGIFY2(Name) #Name
 
+#ifdef ALTERNATE_NAME
+#define ALTERNATE_NAME_STRING STRINGIFY1 (ALTERNATE_NAME)
+#else
+#define ALTERNATE_NAME_STRING NULL
+#endif
+
 #ifndef DEFAULT_CONFIG
 #define DEFAULT_CONFIG NULL
 #endif
@@ -50,8 +56,8 @@ int
 DB_LOOKUP_FCT (service_user **ni, const char *fct_name, void **fctp)
 {
   if (DATABASE_NAME_SYMBOL == NULL
-      && __nss_database_lookup (DATABASE_NAME_STRING, DEFAULT_CONFIG,
-                               &DATABASE_NAME_SYMBOL) < 0)
+      && __nss_database_lookup (DATABASE_NAME_STRING, ALTERNATE_NAME_STRING,
+                               DEFAULT_CONFIG, &DATABASE_NAME_SYMBOL) < 0)
     return -1;
 
   *ni = DATABASE_NAME_SYMBOL;
diff --git a/nss/nss_dns/dns-host.c b/nss/nss_dns/dns-host.c
deleted file mode 100644 (file)
index e396309..0000000
+++ /dev/null
@@ -1,664 +0,0 @@
-/* Copyright (C) 1996 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Extended from original form 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.  */
-
-/* Parts of this file are plain copies of the file `gethtnamadr.c' from
-   the bind package and it has the following copyright.  */
-
-/*
- * ++Copyright++ 1985, 1988, 1993
- * -
- * Copyright (c) 1985, 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.
- * -
- * Portions Copyright (c) 1993 by Digital Equipment Corporation.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies, and that
- * the name of Digital Equipment Corporation not be used in advertising or
- * publicity pertaining to distribution of the document or software without
- * specific, written prior permission.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
- * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
- * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- * -
- * --Copyright--
- */
-
-#include <ctype.h>
-#include <errno.h>
-#include <netdb.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#include <sys/syslog.h>
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <arpa/nameser.h>
-#include <resolv.h>
-
-#include "nsswitch.h"
-
-/* Get implementation for some internal functions.  */
-#include "../resolv/mapv4v6addr.h"
-#include "../resolv/mapv4v6hostent.h"
-
-/* Maximum number of aliases we allow.  */
-#define MAX_NR_ALIASES 48
-#define MAX_NR_ADDRS   48
-
-#if PACKETSZ > 1024
-# define MAXPACKET     PACKETSZ
-#else
-# define MAXPACKET     1024
-#endif
-
-static const char AskedForGot[] = "\
-gethostby*.getanswer: asked for \"%s\", got \"%s\"";
-
-
-/* We need this time later.  */
-typedef union querybuf
-{
-  HEADER hdr;
-  u_char buf[MAXPACKET];
-} querybuf;
-
-
-static enum nss_status getanswer_r (const querybuf *answer, int anslen,
-                                   const char *qname, int qtype,
-                                   struct hostent *result,
-                                   char *buffer, int buflen, int *h_errnop);
-
-enum nss_status
-_nss_dns_gethostbyname2_r (const char *name, int af, struct hostent *result,
-                          char *buffer, int buflen, int *h_errnop)
-{
-  struct host_data
-  {
-    char *aliases[MAX_NR_ALIASES];
-    unsigned char host_addr[16];       /* IPv4 or IPv6 */
-    char *h_addr_ptrs[MAX_NR_ADDRS + 1];
-    char linebuffer[0];
-  } *host_data = (struct host_data *) buffer;
-  int linebuflen = buflen - offsetof (struct host_data, linebuffer);
-  querybuf host_buffer;
-  int size, type, n;
-  const char *cp;
-
-  switch (af) {
-  case AF_INET:
-    size = INADDRSZ;
-    type = T_A;
-    break;
-  case AF_INET6:
-    size = IN6ADDRSZ;
-    type = T_AAAA;
-    break;
-  default:
-    *h_errnop = NETDB_INTERNAL;
-    __set_errno (EAFNOSUPPORT);
-    return NSS_STATUS_UNAVAIL;
-  }
-
-  result->h_addrtype = af;
-  result->h_length = size;
-
-  /*
-   * if there aren't any dots, it could be a user-level alias.
-   * this is also done in res_query() since we are not the only
-   * function that looks up host names.
-   */
-  if (strchr (name, '.') == NULL && (cp = __hostalias (name)) != NULL)
-    name = cp;
-
-  /*
-   * disallow names consisting only of digits/dots, unless
-   * they end in a dot.
-   */
-  if (isdigit (name[0]))
-    for (cp = name;; ++cp)
-      {
-       if (*cp == '\0')
-         {
-           char *bp;
-
-           if (*--cp == '.')
-             break;
-           /*
-            * All-numeric, no dot at the end.  Fake up a hostent
-            * as if we'd actually done a lookup.
-            */
-           if (inet_pton (af, name, host_data->host_addr) <= 0)
-             {
-               *h_errnop = HOST_NOT_FOUND;
-               return NSS_STATUS_NOTFOUND;
-             }
-
-           bp = __stpncpy (host_data->linebuffer, name, linebuflen);
-           host_data->linebuffer[linebuflen - 1] = '\0';
-           linebuflen -= bp - host_data->linebuffer;
-
-           result->h_name = host_data->linebuffer;
-           result->h_aliases = host_data->aliases;
-           host_data->aliases[0] = NULL;
-           host_data->h_addr_ptrs[0] = (char *) host_data->host_addr;
-           host_data->h_addr_ptrs[1] = NULL;
-           result->h_addr_list = host_data->h_addr_ptrs;
-
-           if (_res.options & RES_USE_INET6)
-             map_v4v6_hostent (result, &bp, &linebuflen);
-           *h_errnop = NETDB_SUCCESS;
-           return NSS_STATUS_SUCCESS;
-         }
-       if (!isdigit (*cp) && *cp != '.')
-         break;
-      }
-  if (isxdigit (name[0]) || name[0] == ':')
-    for (cp = name;; ++cp)
-      {
-       if (*cp == '\0')
-         {
-           char *bp;
-
-           if (*--cp == '.')
-             break;
-           /*
-            * All-IPv6-legal, no dot at the end.  Fake up a hostent
-            * as if we'd actually done a lookup.
-            */
-           if (inet_pton (af, name, host_data->host_addr) <= 0)
-             {
-               *h_errnop = HOST_NOT_FOUND;
-               return NSS_STATUS_NOTFOUND;
-             }
-
-           bp = __stpncpy (host_data->linebuffer, name, linebuflen);
-           host_data->linebuffer[linebuflen - 1] = '\0';
-           linebuflen -= bp - host_data->linebuffer;
-
-           result->h_name = host_data->linebuffer;
-           result->h_aliases = host_data->aliases;
-           host_data->aliases[0] = NULL;
-           host_data->h_addr_ptrs[0] = (char *) host_data->host_addr;
-           host_data->h_addr_ptrs[1] = NULL;
-           result->h_addr_list = host_data->h_addr_ptrs;
-           *h_errnop = NETDB_SUCCESS;
-           return NSS_STATUS_SUCCESS;
-         }
-       if (!isxdigit (*cp) && *cp != ':' && *cp != '.')
-         break;
-      }
-
-  n = res_search (name, C_IN, type, host_buffer.buf, sizeof (host_buffer));
-  if (n < 0)
-    return (errno == ECONNREFUSED
-           || errno == EPFNOSUPPORT
-           || errno == EAFNOSUPPORT) 
-      ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND;
-
-  return getanswer_r (&host_buffer, n, name, type, result, buffer, buflen,
-                     h_errnop);
-}
-
-
-enum nss_status
-_nss_dns_gethostbyname_r (const char *name, struct hostent *result,
-                         char *buffer, int buflen, int *h_errnop)
-{
-  enum nss_status status = NSS_STATUS_NOTFOUND;
-
-  if (_res.options & RES_USE_INET6)
-    status = _nss_dns_gethostbyname2_r (name, AF_INET6, result, buffer,
-                                       buflen, h_errnop);
-  if (status == NSS_STATUS_NOTFOUND)
-    status = _nss_dns_gethostbyname2_r (name, AF_INET, result, buffer,
-                                       buflen, h_errnop);
-
-  return status;
-}
-
-
-enum nss_status
-_nss_dns_gethostbyaddr_r (const char *addr, int len, int af,
-                         struct hostent *result, char *buffer, int buflen,
-                         int *h_errnop)
-{
-  static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
-  static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
-  const u_char *uaddr = (const u_char *)addr;
-  struct host_data
-  {
-    char *aliases[MAX_NR_ALIASES];
-    unsigned char host_addr[16];       /* IPv4 or IPv6 */
-    char *h_addr_ptrs[MAX_NR_ADDRS + 1];
-    char linebuffer[0];
-  } *host_data = (struct host_data *) buffer;
-  querybuf host_buffer;
-  char qbuf[MAXDNAME+1], *qp;
-  int size, n, status;
-
-  if (af == AF_INET6 && len == IN6ADDRSZ &&
-      (bcmp (uaddr, mapped, sizeof mapped) == 0
-       || bcmp (uaddr, tunnelled, sizeof tunnelled) == 0))
-    {
-      /* Unmap. */
-      addr += sizeof mapped;
-      uaddr += sizeof mapped;
-      af = AF_INET;
-      len = INADDRSZ;
-    }
-
-  switch (af)
-    {
-    case AF_INET:
-      size = INADDRSZ;
-      break;
-    case AF_INET6:
-      size = IN6ADDRSZ;
-      break;
-    default:
-      __set_errno (EAFNOSUPPORT);
-      *h_errnop = NETDB_INTERNAL;
-      return NSS_STATUS_UNAVAIL;
-    }
-  if (size != len)
-    {
-      __set_errno (EAFNOSUPPORT);
-      *h_errnop = NETDB_INTERNAL;
-      return NSS_STATUS_UNAVAIL;
-    }
-
-  switch (af)
-    {
-    case AF_INET:
-      sprintf (qbuf, "%u.%u.%u.%u.in-addr.arpa", (uaddr[3] & 0xff),
-              (uaddr[2] & 0xff), (uaddr[1] & 0xff), (uaddr[0] & 0xff));
-      break;
-    case AF_INET6:
-      qp = qbuf;
-      for (n = IN6ADDRSZ - 1; n >= 0; n--)
-       qp += sprintf (qp, "%x.%x.", uaddr[n] & 0xf, (uaddr[n] >> 4) & 0xf);
-      strcpy(qp, "ip6.int");
-      break;
-    default:
-      /* Cannot happen.  */
-    }
-
-  n = res_query (qbuf, C_IN, T_PTR, (u_char *)host_buffer.buf,
-                sizeof host_buffer);
-  if (n < 0)
-    return (errno == ECONNREFUSED
-           || errno == EPFNOSUPPORT
-           || errno == EAFNOSUPPORT) 
-      ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND;
-
-  status = getanswer_r (&host_buffer, n, qbuf, T_PTR, result, buffer, buflen,
-                       h_errnop);
-  if (status != NSS_STATUS_SUCCESS)
-    return status;
-
-#ifdef SUNSECURITY
-  This is not implemented because it is not possible to use the current
-  source from bind in a multi-threaded program.
-#endif
-
-  result->h_addrtype = af;
-  result->h_length = len;
-  bcopy (addr, host_data->host_addr, len);
-  host_data->h_addr_ptrs[0] = (char *) host_data->host_addr;
-  host_data->h_addr_ptrs[1] = NULL;
-  if (af == AF_INET && (_res.options & RES_USE_INET6))
-    {
-      map_v4v6_address ((char *) host_data->host_addr,
-                       (char *) host_data->host_addr);
-      result->h_addrtype = AF_INET6;
-      result->h_length = IN6ADDRSZ;
-    }
-  *h_errnop = NETDB_SUCCESS;
-  return NSS_STATUS_SUCCESS;
-}
-
-
-static enum nss_status
-getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
-            struct hostent *result, char *buffer, int buflen, int *h_errnop)
-{
-  struct host_data
-  {
-    char *aliases[MAX_NR_ALIASES];
-    unsigned char host_addr[16];       /* IPv4 or IPv6 */
-    char *h_addr_ptrs[MAX_NR_ADDRS + 1];
-    char linebuffer[0];
-  } *host_data = (struct host_data *) buffer;
-  int linebuflen = buflen - offsetof (struct host_data, linebuffer);
-  register const HEADER *hp;
-  const u_char *end_of_message, *cp;
-  int n, ancount, qdcount;
-  int haveanswer, had_error;
-  char *bp, **ap, **hap;
-  char tbuf[MAXDNAME];
-  const char *tname;
-  int (*name_ok) __P ((const char *));
-
-  tname = qname;
-  result->h_name = NULL;
-  end_of_message = answer->buf + anslen;
-  switch (qtype)
-    {
-    case T_A:
-    case T_AAAA:
-      name_ok = res_hnok;
-      break;
-    case T_PTR:
-      name_ok = res_dnok;
-      break;
-    default:
-      return NSS_STATUS_UNAVAIL;  /* XXX should be abort(); */
-    }
-
-  /*
-   * find first satisfactory answer
-   */
-  hp = &answer->hdr;
-  bp = host_data->linebuffer;
-  ancount = ntohs (hp->ancount);
-  qdcount = ntohs (hp->qdcount);
-  cp = answer->buf + HFIXEDSZ;
-  if (qdcount != 1)
-    {
-      *h_errnop = NO_RECOVERY;
-      return NSS_STATUS_UNAVAIL;
-    }
-
-  n = dn_expand (answer->buf, end_of_message, cp, bp, linebuflen);
-  if (n < 0 || (*name_ok) (bp) == 0)
-    {
-      *h_errnop = NO_RECOVERY;
-      return NSS_STATUS_UNAVAIL;
-    }
-  cp += n + QFIXEDSZ;
-
-  if (qtype == T_A || qtype == T_AAAA)
-    {
-      /* res_send() has already verified that the query name is the
-       * same as the one we sent; this just gets the expanded name
-       * (i.e., with the succeeding search-domain tacked on).
-       */
-      n = strlen (bp) + 1;             /* for the \0 */
-      result->h_name = bp;
-      bp += n;
-      linebuflen -= n;
-      /* The qname can be abbreviated, but h_name is now absolute. */
-      qname = result->h_name;
-    }
-
-  ap = host_data->aliases;
-  *ap = NULL;
-  result->h_aliases = host_data->aliases;
-  hap = host_data->h_addr_ptrs;
-  *hap = NULL;
-  result->h_addr_list = host_data->h_addr_ptrs;
-  haveanswer = 0;
-  had_error = 0;
-
-  while (ancount-- > 0 && cp < end_of_message && had_error == 0)
-    {
-      int type, class;
-
-      n = dn_expand (answer->buf, end_of_message, cp, bp, linebuflen);
-      if (n < 0 || (*name_ok) (bp) == 0)
-       {
-         ++had_error;
-         continue;
-       }
-      cp += n;                         /* name */
-      type = _getshort (cp);
-      cp += INT16SZ;                   /* type */
-      class = _getshort(cp);
-      cp += INT16SZ + INT32SZ;         /* class, TTL */
-      n = _getshort(cp);
-      cp += INT16SZ;                   /* len */
-      if (class != C_IN)
-       {
-         /* XXX - debug? syslog? */
-         cp += n;
-         continue;                     /* XXX - had_error++ ? */
-       }
-
-      if ((qtype ==T_A || qtype == T_AAAA) && type == T_CNAME)
-       {
-         if (ap >= &host_data->aliases[MAX_NR_ALIASES - 1])
-           continue;
-         n = dn_expand (answer->buf, end_of_message, cp, tbuf, sizeof tbuf);
-         if (n < 0 || (*name_ok) (tbuf) == 0)
-           {
-             ++had_error;
-             continue;
-           }
-         cp += n;
-         /* Store alias.  */
-         *ap++ = bp;
-         n = strlen (bp) + 1;          /* For the \0.  */
-         bp += n;
-         linebuflen -= n;
-         /* Get canonical name.  */
-         n = strlen (tbuf) + 1;        /* For the \0.  */
-         if (n > buflen)
-           {
-             ++had_error;
-             continue;
-           }
-         strcpy (bp, tbuf);            /* Cannot overflow.  */
-         result->h_name = bp;
-         bp += n;
-         linebuflen -= n;
-         continue;
-       }
-
-      if (qtype == T_PTR && type == T_CNAME)
-       {
-         n = dn_expand (answer->buf, end_of_message, cp, tbuf, sizeof tbuf);
-         if (n < 0 || res_hnok (tbuf) == 0)
-           {
-             ++had_error;
-             continue;
-           }
-         cp += n;
-         /* Get canonical name. */
-         n = strlen (tbuf) + 1;   /* For the \0.  */
-         if (n > buflen)
-           {
-             ++had_error;
-             continue;
-           }
-         strcpy (bp, tbuf);            /* Cannot overflow.  */
-         tname = bp;
-         bp += n;
-         linebuflen -= n;
-         continue;
-       }
-      if (type != qtype)
-       {
-         syslog (LOG_NOTICE | LOG_AUTH,
-              "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
-                 qname, p_class (C_IN), p_type (qtype), p_type (type));
-         cp += n;
-         continue;                     /* XXX - had_error++ ? */
-       }
-
-      switch (type)
-       {
-       case T_PTR:
-         if (strcasecmp (tname, bp) != 0)
-           {
-             syslog (LOG_NOTICE | LOG_AUTH, AskedForGot, qname, bp);
-             cp += n;
-             continue;                 /* XXX - had_error++ ? */
-           }
-         n = dn_expand (answer->buf, end_of_message, cp, bp, linebuflen);
-         if (n < 0 || res_hnok (bp) == 0)
-           {
-             ++had_error;
-             break;
-           }
-#if MULTI_PTRS_ARE_ALIASES
-         cp += n;
-         if (haveanswer == 0)
-           result->h_name = bp;
-         else if (ap < &host_data->aliases[MAXALIASES-1])
-           *ap++ = bp;
-         else
-           n = -1;
-         if (n != -1)
-           {
-             n = strlen (bp) + 1;      /* for the \0 */
-             bp += n;
-             linebuflen -= n;
-           }
-         break;
-#else
-         result->h_name = bp;
-         if (_res.options & RES_USE_INET6)
-           {
-             n = strlen (bp) + 1;      /* for the \0 */
-             bp += n;
-             linebuflen -= n;
-             map_v4v6_hostent (result, &bp, &linebuflen);
-           }
-         *h_errnop = NETDB_SUCCESS;
-         return NSS_STATUS_SUCCESS;
-#endif
-       case T_A:
-       case T_AAAA:
-         if (strcasecmp (result->h_name, bp) != 0)
-           {
-             syslog (LOG_NOTICE | LOG_AUTH, AskedForGot, result->h_name, bp);
-             cp += n;
-             continue;                 /* XXX - had_error++ ? */
-           }
-         if (n != result->h_length)
-           {
-             cp += n;
-             continue;
-           }
-         if (!haveanswer)
-           {
-             register int nn;
-
-             result->h_name = bp;
-             nn = strlen (bp) + 1;     /* for the \0 */
-             bp += nn;
-             linebuflen -= nn;
-           }
-
-         bp += sizeof (align) - ((u_long) bp % sizeof (align));
-
-         if (n >= linebuflen)
-           {
-             ++had_error;
-             continue;
-           }
-         if (hap >= &host_data->h_addr_ptrs[MAX_NR_ADDRS-1])
-           {
-             cp += n;
-             continue;
-           }
-         bcopy (cp, *hap++ = bp, n);
-         bp += n;
-         cp += n;
-         linebuflen -= n;
-         break;
-       default:
-         abort ();
-       }
-      if (had_error == 0)
-       ++haveanswer;
-    }
-
-  if (haveanswer > 0)
-    {
-      *ap = NULL;
-      *hap = NULL;
-#if defined(RESOLVSORT)
-      /*
-       * Note: we sort even if host can take only one address
-       * in its return structures - should give it the "best"
-       * address in that case, not some random one
-       */
-      if (_res.nsort && haveanswer > 1 && qtype == T_A)
-       addrsort (host_data->h_addr_ptrs, haveanswer);
-#endif /*RESOLVSORT*/
-
-      if (result->h_name == NULL)
-       {
-         n = strlen (qname) + 1;       /* For the \0.  */
-         if (n > linebuflen)
-           goto try_again;
-         strcpy (bp, qname);           /* Cannot overflow.  */
-         result->h_name = bp;
-         bp += n;
-         linebuflen -= n;
-       }
-
-      if (_res.options & RES_USE_INET6)
-       map_v4v6_hostent (result, &bp, &linebuflen);
-      *h_errnop = NETDB_SUCCESS;
-      return NSS_STATUS_SUCCESS;
-    }
-try_again:
-  *h_errnop = TRY_AGAIN;
-  return NSS_STATUS_TRYAGAIN;
-}
diff --git a/nss/nss_dns/dns-network.c b/nss/nss_dns/dns-network.c
deleted file mode 100644 (file)
index d91c1bd..0000000
+++ /dev/null
@@ -1,343 +0,0 @@
-/* Copyright (C) 1996 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Extended from original form 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.  */
-
-/* Parts of this file are plain copies of the file `getnetnamadr.c' from
-   the bind package and it has the following copyright.  */
-
-/* Copyright (c) 1993 Carlos Leandro and Rui Salgueiro
- *      Dep. Matematica Universidade de Coimbra, Portugal, Europe
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- */
-/*
- * Copyright (c) 1983, 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.
- */
-
-#include <ctype.h>
-#include <errno.h>
-#include <netdb.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "nsswitch.h"
-#include <arpa/inet.h>
-
-/* Maximum number of aliases we allow.  */
-#define MAX_NR_ALIASES 48
-
-
-#if PACKETSZ > 1024
-#define MAXPACKET       PACKETSZ
-#else
-#define MAXPACKET       1024
-#endif
-
-
-typedef enum
-{
-  BYADDR,
-  BYNAME
-} lookup_method;
-
-
-/* We need this time later.  */
-typedef union querybuf
-{
-  HEADER hdr;
-  u_char buf[MAXPACKET];
-} querybuf;
-
-
-/* Protortypes for local functions.  */
-static enum nss_status getanswer_r (const querybuf *answer, int anslen,
-                                   struct netent *result, char *buffer,
-                                   int buflen, lookup_method net_i);
-
-
-enum nss_status
-_nss_dns_getnetbyname_r (const char *name, struct netent *result,
-                        char *buffer, int buflen)
-{
-  /* Return entry for network with NAME.  */
-  querybuf net_buffer;
-  int anslen;
-  char *qbuf;
-
-  qbuf = strdupa (name);
-  anslen = res_search (qbuf, C_IN, T_PTR, (u_char *) &net_buffer,
-                      sizeof (querybuf));
-  if (anslen < 0)
-    /* Nothing found.  */
-    return (errno == ECONNREFUSED
-           || errno == EPFNOSUPPORT
-           || errno == EAFNOSUPPORT) 
-      ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND;
-
-  return getanswer_r (&net_buffer, anslen, result, buffer, buflen, BYNAME);
-}
-
-
-enum nss_status
-_nss_dns_getnetbyaddr_r (long net, int type, struct netent *result,
-                        char *buffer, int buflen)
-{
-  /* Return entry for network with NAME.  */
-  enum nss_status status;
-  querybuf net_buffer;
-  unsigned int net_bytes[4];
-  char qbuf[MAXDNAME];
-  int cnt, anslen;
-  u_int32_t net2;
-
-  /* No net address lookup for IPv6 yet.  */
-  if (type != AF_INET)
-    return NSS_STATUS_UNAVAIL;
-
-  net2 = (u_int32_t) net;
-  for (cnt = 4; net2 != 0; net2 >>= 8)
-    net_bytes[--cnt] = net2 & 0xff;
-
-  switch (cnt)
-    {
-    case 3:
-      /* Class A network.  */
-      sprintf (qbuf, "0.0.0.%u.in-addr.arpa", net_bytes[3]);
-      break;
-    case 2:
-      /* Class B network.  */
-      sprintf (qbuf, "0.0.%u.%u.in-addr.arpa", net_bytes[3], net_bytes[2]);
-      break;
-    case 1:
-      /* Class C network.  */
-      sprintf (qbuf, "0.%u.%u.%u.in-addr.arpa", net_bytes[3], net_bytes[2],
-              net_bytes[1]);
-      break;
-    case 0:
-      /* Class D - E network.  */
-      sprintf (qbuf, "%u.%u.%u.%u.in-addr.arpa", net_bytes[3], net_bytes[2],
-              net_bytes[1], net_bytes[0]);
-      break;
-    }
-
-  anslen = res_query (qbuf, C_IN, T_PTR, (u_char *) &net_buffer,
-                     sizeof (querybuf));
-  if (anslen < 0)
-    /* Nothing found.  */
-    return (errno == ECONNREFUSED
-           || errno == EPFNOSUPPORT
-           || errno == EAFNOSUPPORT) 
-      ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND;
-
-  status = getanswer_r (&net_buffer, anslen, result, buffer, buflen, BYADDR);
-  if (status == NSS_STATUS_SUCCESS)
-    {
-      /* Strip trailing zeros.  */
-      unsigned int u_net = net;        /* Maybe net should be unsigned?  */
-
-      while ((u_net & 0xff) == 0 && u_net != 0)
-       u_net >>= 8;
-      result->n_net = u_net;
-    }
-
-  return status;
-}
-
-
-#undef offsetof
-#define offsetof(Type, Member) ((size_t) &((Type *) NULL)->Member)
-
-static enum nss_status
-getanswer_r (const querybuf *answer, int anslen, struct netent *result,
-            char *buffer, int buflen, lookup_method net_i)
-{
-  /*
-   * Find first satisfactory answer
-   *
-   *      answer --> +------------+  ( MESSAGE )
-   *                 |   Header   |
-   *                 +------------+
-   *                 |  Question  | the question for the name server
-   *                 +------------+
-   *                 |   Answer   | RRs answering the question
-   *                 +------------+
-   *                 | Authority  | RRs pointing toward an authority
-   *                 | Additional | RRs holding additional information
-   *                 +------------+
-   */
-  struct net_data
-  {
-    char *aliases[MAX_NR_ALIASES];
-    char linebuffer[0];
-  } *net_data = (struct net_data *) buffer;
-  int linebuflen = buflen - offsetof (struct net_data, linebuffer);
-  const char *end_of_message = &answer->buf[anslen];
-  const HEADER *header_pointer = &answer->hdr;
-  /* #/records in the answer section.  */
-  int answer_count =  ntohs (header_pointer->ancount);
-  /* #/entries in the question section.  */
-  int question_count = ntohs (header_pointer->qdcount);
-  char *bp = net_data->linebuffer;
-  const char *cp = &answer->buf[HFIXEDSZ];
-  char **alias_pointer;
-  int have_answer;
-  char *ans;
-
-  if (question_count == 0)
-    /* FIXME: the Sun version uses for host name lookup an additional
-       parameter for pointing to h_errno.  this is missing here.
-       OSF/1 has a per-thread h_errno variable.  */
-    if (header_pointer->aa != 0)
-      {
-       __set_h_errno (HOST_NOT_FOUND);
-       return NSS_STATUS_NOTFOUND;
-      }
-    else
-      {
-       __set_h_errno (TRY_AGAIN);
-       return NSS_STATUS_TRYAGAIN;
-      }
-
-  /* Skip the question part.  */
-  while (question_count-- > 0)
-    cp += __dn_skipname (cp, end_of_message) + QFIXEDSZ;
-
-  alias_pointer = result->n_aliases = &net_data->aliases[0];
-  *alias_pointer = NULL;
-  have_answer = 0;
-  ans = NULL;
-
-  while (--answer_count >= 0 && cp < end_of_message)
-    {
-      int n = dn_expand (answer->buf, end_of_message, cp, bp, linebuflen);
-      int type, class;
-
-      if (n < 0 || res_dnok (bp) == 0)
-       break;
-      cp += n;
-      ans = strdupa (bp);
-      GETSHORT (type, cp);
-      GETSHORT (class, cp);
-      cp += INT32SZ;           /* TTL */
-      GETSHORT (n, cp);
-
-      if (class == C_IN && type == T_PTR)
-       {
-         n = dn_expand (answer->buf, end_of_message, cp, bp, linebuflen);
-         if (n < 0 || !res_hnok (bp))
-           {
-             /* XXX What does this mean?  The original form from bind
-                returns NULL. Incrementing cp has no effect in any case.
-                What should I return here. ??? */
-             cp += n;
-             return NSS_STATUS_UNAVAIL;
-           }
-         cp += n;
-         *alias_pointer++ = bp;
-         bp += strlen (bp) + 1;
-         result->n_addrtype = class == C_IN ? AF_INET : AF_UNSPEC;
-         ++have_answer;
-       }
-    }
-
-  if (have_answer)
-    {
-      char *tmp;
-      int len;
-      char *in, *cp, *rp, *wp;
-      int cnt, first_flag;
-
-      *alias_pointer = NULL;
-      switch (net_i)
-       {
-       case BYADDR:
-         result->n_name = result->n_aliases[0];
-         result->n_net = 0L;
-         break;
-       case BYNAME:
-         len = strlen (result->n_aliases[0]);
-         tmp = (char *) alloca (len + 1);
-         tmp[len] = 0;
-         wp = &tmp[len - 1];
-
-         rp = in = result->n_aliases[0];
-         result->n_name = ans;
-
-         first_flag = 1;
-         for (cnt = 0; cnt < 4; ++cnt)
-           {
-             char *startp;
-
-             startp = rp;
-             while (*rp != '.')
-               ++rp;
-             if (rp - startp > 1 || *startp != '0' || !first_flag)
-               {
-                 first_flag = 0;
-                 if (cnt > 0)
-                   *wp-- = '.';
-                 cp = rp;
-                 while (cp > startp)
-                   *wp-- = *--cp;
-               }
-             in = rp + 1;
-           }
-
-         result->n_net = inet_network (wp);
-         break;
-       }
-
-      ++result->n_aliases;
-      return NSS_STATUS_SUCCESS;
-    }
-
-  __set_h_errno (TRY_AGAIN);
-  return NSS_STATUS_TRYAGAIN;
-}
index ac743c7..413cc0d 100644 (file)
@@ -74,8 +74,8 @@ static name_database *service_table;
 /* -1 == database not found
     0 == database entry pointer stored */
 int
-__nss_database_lookup (const char *database, const char *defconfig,
-                      service_user **ni)
+__nss_database_lookup (const char *database, const char *alternate_name,
+                      const char *defconfig, service_user **ni)
 {
   /* Prevent multiple threads to change the service table.  */
   __libc_lock_lock (lock);
@@ -103,6 +103,13 @@ __nss_database_lookup (const char *database, const char *defconfig,
       for (entry = service_table->entry; entry != NULL; entry = entry->next)
        if (strcmp (database, entry->name) == 0)
          *ni = entry->service;
+
+      if (*ni == NULL && alternate_name != NULL)
+       /* We haven't found a an entry so far.  Try to find it with
+          the alternative name.  */
+       for (entry = service_table->entry; entry != NULL; entry = entry->next)
+         if (strcmp (alternate_name, entry->name) == 0)
+           *ni = entry->service;
     }
 
   /* No configuration data is available, either because nsswitch.conf
index df4e0f7..a484ef7 100644 (file)
@@ -101,8 +101,8 @@ typedef struct name_database
    If there is no configuration for this database in the file,
    parse a service list from DEFCONFIG and use that.  More
    than one function can use the database.  */
-int __nss_database_lookup (const char *database, const char *defconfig,
-                          service_user **ni);
+int __nss_database_lookup (const char *database, const char *alternative_name,
+                          const char *defconfig, service_user **ni);
 
 
 /* Put first function with name FCT_NAME for SERVICE in FCTP.  The
index 8832805..fd0a04c 100644 (file)
@@ -1,22 +1,23 @@
 /* Copyright (C) 1996 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
-Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+   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 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.
+   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.  */
+   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.  */
 
 #define DATABASE_NAME shadow
+#define ALTERNATE_NAME passwd
 
 #include "XXX-lookup.c"
index 40c4386..61f18c4 100755 (executable)
--- a/rellns-sh
+++ b/rellns-sh
 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 if test $# -ne 2; then
-  echo "Usage: rellns SOURCE DEST"
+  echo "Usage: rellns SOURCE DEST" >&2
+  exit 1
+fi
+
+# We only handle the case where SOURCE is the name of an existing file
+if test ! -f $1; then
+  echo "rellns: $1 must name an existing file" >&2
   exit 1
 fi
 
@@ -38,26 +44,31 @@ case $1 in
   ?*) from=`cd $from && pwd | sed 's%^/%%'` ;;
   *) from=`pwd | sed 's%^/%%'` ;;
   esac
+  ;;
+*)
+  to=$1
 
-  while test -n "$to" && test -n "$from"; do
-    preto=`echo $to | sed 's%^\([^/]*\)/.*%\1%'`
-    prefrom=`echo $from | sed 's%^\([^/]*\)/.*%\1%'`
+  if test -d $2; then
+    from=`echo $2 | sed 's%/*$%%'`
+  else
+    from=`echo $2 | sed 's%/*[^/]*$%%'`
+  fi
+  ;;
+esac
 
-    test "$preto" != "$prefrom" && break
+while test -n "$to" && test -n "$from"; do
+  preto=`echo $to | sed 's%^\([^/]*\)/.*%\1%'`
+  prefrom=`echo $from | sed 's%^\([^/]*\)/.*%\1%'`
 
-    to=`echo $to | sed 's%^[^/]*/*\(.*\)$%\1%'`
-    from=`echo $from | sed 's%^[^/]*/*\(.*\)$%\1%'`
-  done
+  test "$preto" != "$prefrom" && break
 
-  while test -n "$from"; do
-    rfrom="../$rfrom"
-    from=`echo $from | sed 's%^[^/]*/*%%'`
-  done
+  to=`echo $to | sed 's%^[^/]*/*\(.*\)$%\1%'`
+  from=`echo $from | sed 's%^[^/]*/*\(.*\)$%\1%'`
+done
 
-  ln -s $rfrom$to $2
-  ;;
-*)
-  # Nothing to do, the path is already relative.
-  ln -s $1 $2
-  ;;
-esac
+while test -n "$from"; do
+  rfrom="../$rfrom"
+  from=`echo $from | sed 's%^[^/]*/*%%'`
+done
+
+ln -s $rfrom$to $2
index 962dbca..a70ee99 100644 (file)
@@ -27,12 +27,17 @@ distribute := ../conf/portability.h mapv4v6addr.h mapv4v6hostent.h \
 
 routines := herror inet_addr inet_ntop inet_pton nsap_addr res_init
 
-extra-libs := libresolv
+extra-libs := libresolv libnss_dns
 extra-libs-others = $(extra-libs)
 libresolv-routines := gethnamaddr res_comp res_debug   \
                      res_data res_mkquery res_query res_send           \
                      inet_net_ntop inet_net_pton inet_neta base64
 
+vpath %.c nss_dns
+
+libnss_dns-routines    := dns-host dns-network
+libnss_dns-inhibit-o   = $(filter-out .so,$(object-suffixes))
+
 include ../Rules
 
 CPPFLAGS += -Dgethostbyname=res_gethostbyname \
@@ -48,3 +53,6 @@ CPPFLAGS += -Dgethostbyname=res_gethostbyname \
 # This ensures they will load libc.so for needed symbols if loaded by
 # a statically-linked program that hasn't already loaded it.
 $(objpfx)libresolv.so: $(common-objpfx)libc.so
+
+# The DNS NSS modules needs the resolver.
+$(objpfx)libnss_dns.so: $(objpfx)libresolv.so
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
new file mode 100644 (file)
index 0000000..e4a9c78
--- /dev/null
@@ -0,0 +1,658 @@
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Extended from original form 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.  */
+
+/* Parts of this file are plain copies of the file `gethtnamadr.c' from
+   the bind package and it has the following copyright.  */
+
+/*
+ * ++Copyright++ 1985, 1988, 1993
+ * -
+ * Copyright (c) 1985, 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.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * -
+ * --Copyright--
+ */
+
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <sys/syslog.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#include "nsswitch.h"
+
+/* Get implementation for some internal functions.  */
+#include "../resolv/mapv4v6addr.h"
+#include "../resolv/mapv4v6hostent.h"
+
+/* Maximum number of aliases we allow.  */
+#define MAX_NR_ALIASES 48
+#define MAX_NR_ADDRS   48
+
+#if PACKETSZ > 1024
+# define MAXPACKET     PACKETSZ
+#else
+# define MAXPACKET     1024
+#endif
+
+static const char AskedForGot[] = "\
+gethostby*.getanswer: asked for \"%s\", got \"%s\"";
+
+
+/* We need this time later.  */
+typedef union querybuf
+{
+  HEADER hdr;
+  u_char buf[MAXPACKET];
+} querybuf;
+
+
+static enum nss_status getanswer_r (const querybuf *answer, int anslen,
+                                   const char *qname, int qtype,
+                                   struct hostent *result,
+                                   char *buffer, int buflen, int *h_errnop);
+
+enum nss_status
+_nss_dns_gethostbyname2_r (const char *name, int af, struct hostent *result,
+                          char *buffer, int buflen, int *h_errnop)
+{
+  struct host_data
+  {
+    char *aliases[MAX_NR_ALIASES];
+    unsigned char host_addr[16];       /* IPv4 or IPv6 */
+    char *h_addr_ptrs[MAX_NR_ADDRS + 1];
+    char linebuffer[0];
+  } *host_data = (struct host_data *) buffer;
+  int linebuflen = buflen - offsetof (struct host_data, linebuffer);
+  querybuf host_buffer;
+  int size, type, n;
+  const char *cp;
+
+  switch (af) {
+  case AF_INET:
+    size = INADDRSZ;
+    type = T_A;
+    break;
+  case AF_INET6:
+    size = IN6ADDRSZ;
+    type = T_AAAA;
+    break;
+  default:
+    *h_errnop = NETDB_INTERNAL;
+    __set_errno (EAFNOSUPPORT);
+    return NSS_STATUS_UNAVAIL;
+  }
+
+  result->h_addrtype = af;
+  result->h_length = size;
+
+  /*
+   * if there aren't any dots, it could be a user-level alias.
+   * this is also done in res_query() since we are not the only
+   * function that looks up host names.
+   */
+  if (strchr (name, '.') == NULL && (cp = __hostalias (name)) != NULL)
+    name = cp;
+
+  /*
+   * disallow names consisting only of digits/dots, unless
+   * they end in a dot.
+   */
+  if (isdigit (name[0]))
+    for (cp = name;; ++cp)
+      {
+       if (*cp == '\0')
+         {
+           char *bp;
+
+           if (*--cp == '.')
+             break;
+           /*
+            * All-numeric, no dot at the end.  Fake up a hostent
+            * as if we'd actually done a lookup.
+            */
+           if (inet_pton (af, name, host_data->host_addr) <= 0)
+             {
+               *h_errnop = HOST_NOT_FOUND;
+               return NSS_STATUS_NOTFOUND;
+             }
+
+           bp = __stpncpy (host_data->linebuffer, name, linebuflen);
+           host_data->linebuffer[linebuflen - 1] = '\0';
+           linebuflen -= bp - host_data->linebuffer;
+
+           result->h_name = host_data->linebuffer;
+           result->h_aliases = host_data->aliases;
+           host_data->aliases[0] = NULL;
+           host_data->h_addr_ptrs[0] = (char *) host_data->host_addr;
+           host_data->h_addr_ptrs[1] = NULL;
+           result->h_addr_list = host_data->h_addr_ptrs;
+
+           if (_res.options & RES_USE_INET6)
+             map_v4v6_hostent (result, &bp, &linebuflen);
+           *h_errnop = NETDB_SUCCESS;
+           return NSS_STATUS_SUCCESS;
+         }
+       if (!isdigit (*cp) && *cp != '.')
+         break;
+      }
+  if (isxdigit (name[0]) || name[0] == ':')
+    for (cp = name;; ++cp)
+      {
+       if (*cp == '\0')
+         {
+           char *bp;
+
+           if (*--cp == '.')
+             break;
+           /*
+            * All-IPv6-legal, no dot at the end.  Fake up a hostent
+            * as if we'd actually done a lookup.
+            */
+           if (inet_pton (af, name, host_data->host_addr) <= 0)
+             {
+               *h_errnop = HOST_NOT_FOUND;
+               return NSS_STATUS_NOTFOUND;
+             }
+
+           bp = __stpncpy (host_data->linebuffer, name, linebuflen);
+           host_data->linebuffer[linebuflen - 1] = '\0';
+           linebuflen -= bp - host_data->linebuffer;
+
+           result->h_name = host_data->linebuffer;
+           result->h_aliases = host_data->aliases;
+           host_data->aliases[0] = NULL;
+           host_data->h_addr_ptrs[0] = (char *) host_data->host_addr;
+           host_data->h_addr_ptrs[1] = NULL;
+           result->h_addr_list = host_data->h_addr_ptrs;
+           *h_errnop = NETDB_SUCCESS;
+           return NSS_STATUS_SUCCESS;
+         }
+       if (!isxdigit (*cp) && *cp != ':' && *cp != '.')
+         break;
+      }
+
+  n = res_search (name, C_IN, type, host_buffer.buf, sizeof (host_buffer));
+  if (n < 0)
+    return errno == ECONNREFUSED ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND;
+
+  return getanswer_r (&host_buffer, n, name, type, result, buffer, buflen,
+                     h_errnop);
+}
+
+
+enum nss_status
+_nss_dns_gethostbyname_r (const char *name, struct hostent *result,
+                         char *buffer, int buflen, int *h_errnop)
+{
+  enum nss_status status = NSS_STATUS_NOTFOUND;
+
+  if (_res.options & RES_USE_INET6)
+    status = _nss_dns_gethostbyname2_r (name, AF_INET6, result, buffer,
+                                       buflen, h_errnop);
+  if (status == NSS_STATUS_NOTFOUND)
+    status = _nss_dns_gethostbyname2_r (name, AF_INET, result, buffer,
+                                       buflen, h_errnop);
+
+  return status;
+}
+
+
+enum nss_status
+_nss_dns_gethostbyaddr_r (const char *addr, int len, int af,
+                         struct hostent *result, char *buffer, int buflen,
+                         int *h_errnop)
+{
+  static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
+  static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
+  const u_char *uaddr = (const u_char *)addr;
+  struct host_data
+  {
+    char *aliases[MAX_NR_ALIASES];
+    unsigned char host_addr[16];       /* IPv4 or IPv6 */
+    char *h_addr_ptrs[MAX_NR_ADDRS + 1];
+    char linebuffer[0];
+  } *host_data = (struct host_data *) buffer;
+  querybuf host_buffer;
+  char qbuf[MAXDNAME+1], *qp;
+  int size, n, status;
+
+  if (af == AF_INET6 && len == IN6ADDRSZ &&
+      (bcmp (uaddr, mapped, sizeof mapped) == 0
+       || bcmp (uaddr, tunnelled, sizeof tunnelled) == 0))
+    {
+      /* Unmap. */
+      addr += sizeof mapped;
+      uaddr += sizeof mapped;
+      af = AF_INET;
+      len = INADDRSZ;
+    }
+
+  switch (af)
+    {
+    case AF_INET:
+      size = INADDRSZ;
+      break;
+    case AF_INET6:
+      size = IN6ADDRSZ;
+      break;
+    default:
+      __set_errno (EAFNOSUPPORT);
+      *h_errnop = NETDB_INTERNAL;
+      return NSS_STATUS_UNAVAIL;
+    }
+  if (size != len)
+    {
+      __set_errno (EAFNOSUPPORT);
+      *h_errnop = NETDB_INTERNAL;
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  switch (af)
+    {
+    case AF_INET:
+      sprintf (qbuf, "%u.%u.%u.%u.in-addr.arpa", (uaddr[3] & 0xff),
+              (uaddr[2] & 0xff), (uaddr[1] & 0xff), (uaddr[0] & 0xff));
+      break;
+    case AF_INET6:
+      qp = qbuf;
+      for (n = IN6ADDRSZ - 1; n >= 0; n--)
+       qp += sprintf (qp, "%x.%x.", uaddr[n] & 0xf, (uaddr[n] >> 4) & 0xf);
+      strcpy(qp, "ip6.int");
+      break;
+    default:
+      /* Cannot happen.  */
+    }
+
+  n = res_query (qbuf, C_IN, T_PTR, (u_char *)host_buffer.buf,
+                sizeof host_buffer);
+  if (n < 0)
+    return errno == ECONNREFUSED ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND;
+
+  status = getanswer_r (&host_buffer, n, qbuf, T_PTR, result, buffer, buflen,
+                       h_errnop);
+  if (status != NSS_STATUS_SUCCESS)
+    return status;
+
+#ifdef SUNSECURITY
+  This is not implemented because it is not possible to use the current
+  source from bind in a multi-threaded program.
+#endif
+
+  result->h_addrtype = af;
+  result->h_length = len;
+  bcopy (addr, host_data->host_addr, len);
+  host_data->h_addr_ptrs[0] = (char *) host_data->host_addr;
+  host_data->h_addr_ptrs[1] = NULL;
+  if (af == AF_INET && (_res.options & RES_USE_INET6))
+    {
+      map_v4v6_address ((char *) host_data->host_addr,
+                       (char *) host_data->host_addr);
+      result->h_addrtype = AF_INET6;
+      result->h_length = IN6ADDRSZ;
+    }
+  *h_errnop = NETDB_SUCCESS;
+  return NSS_STATUS_SUCCESS;
+}
+
+
+static enum nss_status
+getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
+            struct hostent *result, char *buffer, int buflen, int *h_errnop)
+{
+  struct host_data
+  {
+    char *aliases[MAX_NR_ALIASES];
+    unsigned char host_addr[16];       /* IPv4 or IPv6 */
+    char *h_addr_ptrs[MAX_NR_ADDRS + 1];
+    char linebuffer[0];
+  } *host_data = (struct host_data *) buffer;
+  int linebuflen = buflen - offsetof (struct host_data, linebuffer);
+  register const HEADER *hp;
+  const u_char *end_of_message, *cp;
+  int n, ancount, qdcount;
+  int haveanswer, had_error;
+  char *bp, **ap, **hap;
+  char tbuf[MAXDNAME];
+  const char *tname;
+  int (*name_ok) __P ((const char *));
+
+  tname = qname;
+  result->h_name = NULL;
+  end_of_message = answer->buf + anslen;
+  switch (qtype)
+    {
+    case T_A:
+    case T_AAAA:
+      name_ok = res_hnok;
+      break;
+    case T_PTR:
+      name_ok = res_dnok;
+      break;
+    default:
+      return NSS_STATUS_UNAVAIL;  /* XXX should be abort(); */
+    }
+
+  /*
+   * find first satisfactory answer
+   */
+  hp = &answer->hdr;
+  bp = host_data->linebuffer;
+  ancount = ntohs (hp->ancount);
+  qdcount = ntohs (hp->qdcount);
+  cp = answer->buf + HFIXEDSZ;
+  if (qdcount != 1)
+    {
+      *h_errnop = NO_RECOVERY;
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  n = dn_expand (answer->buf, end_of_message, cp, bp, linebuflen);
+  if (n < 0 || (*name_ok) (bp) == 0)
+    {
+      *h_errnop = NO_RECOVERY;
+      return NSS_STATUS_UNAVAIL;
+    }
+  cp += n + QFIXEDSZ;
+
+  if (qtype == T_A || qtype == T_AAAA)
+    {
+      /* res_send() has already verified that the query name is the
+       * same as the one we sent; this just gets the expanded name
+       * (i.e., with the succeeding search-domain tacked on).
+       */
+      n = strlen (bp) + 1;             /* for the \0 */
+      result->h_name = bp;
+      bp += n;
+      linebuflen -= n;
+      /* The qname can be abbreviated, but h_name is now absolute. */
+      qname = result->h_name;
+    }
+
+  ap = host_data->aliases;
+  *ap = NULL;
+  result->h_aliases = host_data->aliases;
+  hap = host_data->h_addr_ptrs;
+  *hap = NULL;
+  result->h_addr_list = host_data->h_addr_ptrs;
+  haveanswer = 0;
+  had_error = 0;
+
+  while (ancount-- > 0 && cp < end_of_message && had_error == 0)
+    {
+      int type, class;
+
+      n = dn_expand (answer->buf, end_of_message, cp, bp, linebuflen);
+      if (n < 0 || (*name_ok) (bp) == 0)
+       {
+         ++had_error;
+         continue;
+       }
+      cp += n;                         /* name */
+      type = _getshort (cp);
+      cp += INT16SZ;                   /* type */
+      class = _getshort(cp);
+      cp += INT16SZ + INT32SZ;         /* class, TTL */
+      n = _getshort(cp);
+      cp += INT16SZ;                   /* len */
+      if (class != C_IN)
+       {
+         /* XXX - debug? syslog? */
+         cp += n;
+         continue;                     /* XXX - had_error++ ? */
+       }
+
+      if ((qtype ==T_A || qtype == T_AAAA) && type == T_CNAME)
+       {
+         if (ap >= &host_data->aliases[MAX_NR_ALIASES - 1])
+           continue;
+         n = dn_expand (answer->buf, end_of_message, cp, tbuf, sizeof tbuf);
+         if (n < 0 || (*name_ok) (tbuf) == 0)
+           {
+             ++had_error;
+             continue;
+           }
+         cp += n;
+         /* Store alias.  */
+         *ap++ = bp;
+         n = strlen (bp) + 1;          /* For the \0.  */
+         bp += n;
+         linebuflen -= n;
+         /* Get canonical name.  */
+         n = strlen (tbuf) + 1;        /* For the \0.  */
+         if (n > buflen)
+           {
+             ++had_error;
+             continue;
+           }
+         strcpy (bp, tbuf);            /* Cannot overflow.  */
+         result->h_name = bp;
+         bp += n;
+         linebuflen -= n;
+         continue;
+       }
+
+      if (qtype == T_PTR && type == T_CNAME)
+       {
+         n = dn_expand (answer->buf, end_of_message, cp, tbuf, sizeof tbuf);
+         if (n < 0 || res_hnok (tbuf) == 0)
+           {
+             ++had_error;
+             continue;
+           }
+         cp += n;
+         /* Get canonical name. */
+         n = strlen (tbuf) + 1;   /* For the \0.  */
+         if (n > buflen)
+           {
+             ++had_error;
+             continue;
+           }
+         strcpy (bp, tbuf);            /* Cannot overflow.  */
+         tname = bp;
+         bp += n;
+         linebuflen -= n;
+         continue;
+       }
+      if (type != qtype)
+       {
+         syslog (LOG_NOTICE | LOG_AUTH,
+              "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
+                 qname, p_class (C_IN), p_type (qtype), p_type (type));
+         cp += n;
+         continue;                     /* XXX - had_error++ ? */
+       }
+
+      switch (type)
+       {
+       case T_PTR:
+         if (strcasecmp (tname, bp) != 0)
+           {
+             syslog (LOG_NOTICE | LOG_AUTH, AskedForGot, qname, bp);
+             cp += n;
+             continue;                 /* XXX - had_error++ ? */
+           }
+         n = dn_expand (answer->buf, end_of_message, cp, bp, linebuflen);
+         if (n < 0 || res_hnok (bp) == 0)
+           {
+             ++had_error;
+             break;
+           }
+#if MULTI_PTRS_ARE_ALIASES
+         cp += n;
+         if (haveanswer == 0)
+           result->h_name = bp;
+         else if (ap < &host_data->aliases[MAXALIASES-1])
+           *ap++ = bp;
+         else
+           n = -1;
+         if (n != -1)
+           {
+             n = strlen (bp) + 1;      /* for the \0 */
+             bp += n;
+             linebuflen -= n;
+           }
+         break;
+#else
+         result->h_name = bp;
+         if (_res.options & RES_USE_INET6)
+           {
+             n = strlen (bp) + 1;      /* for the \0 */
+             bp += n;
+             linebuflen -= n;
+             map_v4v6_hostent (result, &bp, &linebuflen);
+           }
+         *h_errnop = NETDB_SUCCESS;
+         return NSS_STATUS_SUCCESS;
+#endif
+       case T_A:
+       case T_AAAA:
+         if (strcasecmp (result->h_name, bp) != 0)
+           {
+             syslog (LOG_NOTICE | LOG_AUTH, AskedForGot, result->h_name, bp);
+             cp += n;
+             continue;                 /* XXX - had_error++ ? */
+           }
+         if (n != result->h_length)
+           {
+             cp += n;
+             continue;
+           }
+         if (!haveanswer)
+           {
+             register int nn;
+
+             result->h_name = bp;
+             nn = strlen (bp) + 1;     /* for the \0 */
+             bp += nn;
+             linebuflen -= nn;
+           }
+
+         bp += sizeof (align) - ((u_long) bp % sizeof (align));
+
+         if (n >= linebuflen)
+           {
+             ++had_error;
+             continue;
+           }
+         if (hap >= &host_data->h_addr_ptrs[MAX_NR_ADDRS-1])
+           {
+             cp += n;
+             continue;
+           }
+         bcopy (cp, *hap++ = bp, n);
+         bp += n;
+         cp += n;
+         linebuflen -= n;
+         break;
+       default:
+         abort ();
+       }
+      if (had_error == 0)
+       ++haveanswer;
+    }
+
+  if (haveanswer > 0)
+    {
+      *ap = NULL;
+      *hap = NULL;
+#if defined(RESOLVSORT)
+      /*
+       * Note: we sort even if host can take only one address
+       * in its return structures - should give it the "best"
+       * address in that case, not some random one
+       */
+      if (_res.nsort && haveanswer > 1 && qtype == T_A)
+       addrsort (host_data->h_addr_ptrs, haveanswer);
+#endif /*RESOLVSORT*/
+
+      if (result->h_name == NULL)
+       {
+         n = strlen (qname) + 1;       /* For the \0.  */
+         if (n > linebuflen)
+           goto try_again;
+         strcpy (bp, qname);           /* Cannot overflow.  */
+         result->h_name = bp;
+         bp += n;
+         linebuflen -= n;
+       }
+
+      if (_res.options & RES_USE_INET6)
+       map_v4v6_hostent (result, &bp, &linebuflen);
+      *h_errnop = NETDB_SUCCESS;
+      return NSS_STATUS_SUCCESS;
+    }
+try_again:
+  *h_errnop = TRY_AGAIN;
+  return NSS_STATUS_TRYAGAIN;
+}
diff --git a/resolv/nss_dns/dns-network.c b/resolv/nss_dns/dns-network.c
new file mode 100644 (file)
index 0000000..94fa1c1
--- /dev/null
@@ -0,0 +1,343 @@
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Extended from original form 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.  */
+
+/* Parts of this file are plain copies of the file `getnetnamadr.c' from
+   the bind package and it has the following copyright.  */
+
+/* Copyright (c) 1993 Carlos Leandro and Rui Salgueiro
+ *      Dep. Matematica Universidade de Coimbra, Portugal, Europe
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ */
+/*
+ * Copyright (c) 1983, 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.
+ */
+
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "nsswitch.h"
+#include <arpa/inet.h>
+
+/* Maximum number of aliases we allow.  */
+#define MAX_NR_ALIASES 48
+
+
+#if PACKETSZ > 1024
+#define MAXPACKET       PACKETSZ
+#else
+#define MAXPACKET       1024
+#endif
+
+
+typedef enum
+{
+  BYADDR,
+  BYNAME
+} lookup_method;
+
+
+/* We need this time later.  */
+typedef union querybuf
+{
+  HEADER hdr;
+  u_char buf[MAXPACKET];
+} querybuf;
+
+
+/* Protortypes for local functions.  */
+static enum nss_status getanswer_r (const querybuf *answer, int anslen,
+                                   struct netent *result, char *buffer,
+                                   int buflen, lookup_method net_i);
+
+
+enum nss_status
+_nss_dns_getnetbyname_r (const char *name, struct netent *result,
+                        char *buffer, int buflen)
+{
+  /* Return entry for network with NAME.  */
+  querybuf net_buffer;
+  int anslen;
+  char *qbuf;
+
+  qbuf = strdupa (name);
+  anslen = res_search (qbuf, C_IN, T_PTR, (u_char *) &net_buffer,
+                      sizeof (querybuf));
+  if (anslen < 0)
+    /* Nothing found.  */
+    return (errno == ECONNREFUSED
+           || errno == EPFNOSUPPORT
+           || errno == EAFNOSUPPORT)
+      ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND;
+
+  return getanswer_r (&net_buffer, anslen, result, buffer, buflen, BYNAME);
+}
+
+
+enum nss_status
+_nss_dns_getnetbyaddr_r (long net, int type, struct netent *result,
+                        char *buffer, int buflen)
+{
+  /* Return entry for network with NAME.  */
+  enum nss_status status;
+  querybuf net_buffer;
+  unsigned int net_bytes[4];
+  char qbuf[MAXDNAME];
+  int cnt, anslen;
+  u_int32_t net2;
+
+  /* No net address lookup for IPv6 yet.  */
+  if (type != AF_INET)
+    return NSS_STATUS_UNAVAIL;
+
+  net2 = (u_int32_t) net;
+  for (cnt = 4; net2 != 0; net2 >>= 8)
+    net_bytes[--cnt] = net2 & 0xff;
+
+  switch (cnt)
+    {
+    case 3:
+      /* Class A network.  */
+      sprintf (qbuf, "0.0.0.%u.in-addr.arpa", net_bytes[3]);
+      break;
+    case 2:
+      /* Class B network.  */
+      sprintf (qbuf, "0.0.%u.%u.in-addr.arpa", net_bytes[3], net_bytes[2]);
+      break;
+    case 1:
+      /* Class C network.  */
+      sprintf (qbuf, "0.%u.%u.%u.in-addr.arpa", net_bytes[3], net_bytes[2],
+              net_bytes[1]);
+      break;
+    case 0:
+      /* Class D - E network.  */
+      sprintf (qbuf, "%u.%u.%u.%u.in-addr.arpa", net_bytes[3], net_bytes[2],
+              net_bytes[1], net_bytes[0]);
+      break;
+    }
+
+  anslen = res_query (qbuf, C_IN, T_PTR, (u_char *) &net_buffer,
+                     sizeof (querybuf));
+  if (anslen < 0)
+    /* Nothing found.  */
+    return (errno == ECONNREFUSED
+           || errno == EPFNOSUPPORT
+           || errno == EAFNOSUPPORT)
+      ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND;
+
+  status = getanswer_r (&net_buffer, anslen, result, buffer, buflen, BYADDR);
+  if (status == NSS_STATUS_SUCCESS)
+    {
+      /* Strip trailing zeros.  */
+      unsigned int u_net = net;        /* Maybe net should be unsigned?  */
+
+      while ((u_net & 0xff) == 0 && u_net != 0)
+       u_net >>= 8;
+      result->n_net = u_net;
+    }
+
+  return status;
+}
+
+
+#undef offsetof
+#define offsetof(Type, Member) ((size_t) &((Type *) NULL)->Member)
+
+static enum nss_status
+getanswer_r (const querybuf *answer, int anslen, struct netent *result,
+            char *buffer, int buflen, lookup_method net_i)
+{
+  /*
+   * Find first satisfactory answer
+   *
+   *      answer --> +------------+  ( MESSAGE )
+   *                 |   Header   |
+   *                 +------------+
+   *                 |  Question  | the question for the name server
+   *                 +------------+
+   *                 |   Answer   | RRs answering the question
+   *                 +------------+
+   *                 | Authority  | RRs pointing toward an authority
+   *                 | Additional | RRs holding additional information
+   *                 +------------+
+   */
+  struct net_data
+  {
+    char *aliases[MAX_NR_ALIASES];
+    char linebuffer[0];
+  } *net_data = (struct net_data *) buffer;
+  int linebuflen = buflen - offsetof (struct net_data, linebuffer);
+  const char *end_of_message = &answer->buf[anslen];
+  const HEADER *header_pointer = &answer->hdr;
+  /* #/records in the answer section.  */
+  int answer_count =  ntohs (header_pointer->ancount);
+  /* #/entries in the question section.  */
+  int question_count = ntohs (header_pointer->qdcount);
+  char *bp = net_data->linebuffer;
+  const char *cp = &answer->buf[HFIXEDSZ];
+  char **alias_pointer;
+  int have_answer;
+  char *ans;
+
+  if (question_count == 0)
+    /* FIXME: the Sun version uses for host name lookup an additional
+       parameter for pointing to h_errno.  this is missing here.
+       OSF/1 has a per-thread h_errno variable.  */
+    if (header_pointer->aa != 0)
+      {
+       __set_h_errno (HOST_NOT_FOUND);
+       return NSS_STATUS_NOTFOUND;
+      }
+    else
+      {
+       __set_h_errno (TRY_AGAIN);
+       return NSS_STATUS_TRYAGAIN;
+      }
+
+  /* Skip the question part.  */
+  while (question_count-- > 0)
+    cp += __dn_skipname (cp, end_of_message) + QFIXEDSZ;
+
+  alias_pointer = result->n_aliases = &net_data->aliases[0];
+  *alias_pointer = NULL;
+  have_answer = 0;
+  ans = NULL;
+
+  while (--answer_count >= 0 && cp < end_of_message)
+    {
+      int n = dn_expand (answer->buf, end_of_message, cp, bp, linebuflen);
+      int type, class;
+
+      if (n < 0 || res_dnok (bp) == 0)
+       break;
+      cp += n;
+      ans = strdupa (bp);
+      GETSHORT (type, cp);
+      GETSHORT (class, cp);
+      cp += INT32SZ;           /* TTL */
+      GETSHORT (n, cp);
+
+      if (class == C_IN && type == T_PTR)
+       {
+         n = dn_expand (answer->buf, end_of_message, cp, bp, linebuflen);
+         if (n < 0 || !res_hnok (bp))
+           {
+             /* XXX What does this mean?  The original form from bind
+                returns NULL. Incrementing cp has no effect in any case.
+                What should I return here. ??? */
+             cp += n;
+             return NSS_STATUS_UNAVAIL;
+           }
+         cp += n;
+         *alias_pointer++ = bp;
+         bp += strlen (bp) + 1;
+         result->n_addrtype = class == C_IN ? AF_INET : AF_UNSPEC;
+         ++have_answer;
+       }
+    }
+
+  if (have_answer)
+    {
+      char *tmp;
+      int len;
+      char *in, *cp, *rp, *wp;
+      int cnt, first_flag;
+
+      *alias_pointer = NULL;
+      switch (net_i)
+       {
+       case BYADDR:
+         result->n_name = result->n_aliases[0];
+         result->n_net = 0L;
+         break;
+       case BYNAME:
+         len = strlen (result->n_aliases[0]);
+         tmp = (char *) alloca (len + 1);
+         tmp[len] = 0;
+         wp = &tmp[len - 1];
+
+         rp = in = result->n_aliases[0];
+         result->n_name = ans;
+
+         first_flag = 1;
+         for (cnt = 0; cnt < 4; ++cnt)
+           {
+             char *startp;
+
+             startp = rp;
+             while (*rp != '.')
+               ++rp;
+             if (rp - startp > 1 || *startp != '0' || !first_flag)
+               {
+                 first_flag = 0;
+                 if (cnt > 0)
+                   *wp-- = '.';
+                 cp = rp;
+                 while (cp > startp)
+                   *wp-- = *--cp;
+               }
+             in = rp + 1;
+           }
+
+         result->n_net = inet_network (wp);
+         break;
+       }
+
+      ++result->n_aliases;
+      return NSS_STATUS_SUCCESS;
+    }
+
+  __set_h_errno (TRY_AGAIN);
+  return NSS_STATUS_TRYAGAIN;
+}
index ec7429c..4f4d45e 100644 (file)
@@ -33,7 +33,7 @@ routines      :=                                                            \
        tmpfile tmpnam tmpnam_r tempnam tempname                              \
        getline getw putw                                                     \
        remove rename                                                         \
-       lockfile
+       lockfile fcloseall
 
 aux    := errlist siglist
 distribute := _itoa.h printf-parse.h
diff --git a/stdio-common/fcloseall.c b/stdio-common/fcloseall.c
new file mode 100644 (file)
index 0000000..d056b90
--- /dev/null
@@ -0,0 +1,44 @@
+/* Close all streams but make sure this isn't done more than once.
+   This function is called in abort().
+   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 <libc-lock.h>
+#include <stdio.h>
+
+static int already_called;
+
+__libc_lock_define_initialized (static, lock);
+
+void
+__close_all_streams (void)
+{
+  /* We must be prepared for multi-threading on multiple calls.  */
+  if (! __libc_lock_trylock (lock) && already_called)
+    {
+      /* Signal that we already did this.  */
+      already_called = 1;
+
+      /* Do the real work.  */
+      fclose (NULL);
+
+      /* We don't release the lock so that the `trylock' immediately
+        fails.  */
+    }
+}
index 86a9821..8e3ea0a 100644 (file)
 #define NDEBUG 1
 #include <assert.h>
 
+#ifndef MAX
 #define MAX(a,b)       ({typeof(a) _a = (a); typeof(b) _b = (b);             \
                          _a > _b ? _a : _b; })
+#endif
+#ifndef MIN
 #define MIN(a,b)       ({typeof(a) _a = (a); typeof(b) _b = (b);             \
                          _a < _b ? _a : _b; })
+#endif
 
 struct printf_spec
   {
index 31ff999..fa18033 100644 (file)
@@ -98,7 +98,12 @@ ssize_t __wprintf_pad __P ((FILE *, wchar_t pad, size_t n));
     {                                                                        \
       /* Check file argument for consistence.  */                            \
       CHECK_FILE (S, -1);                                                    \
-      if (S->_flags & _IO_NO_WRITES || Format == NULL)                       \
+      if (S->_flags & _IO_NO_WRITES)                                         \
+       {                                                                     \
+         __set_errno (EBADF);                                                \
+         return -1;                                                          \
+       }                                                                     \
+      if (Format == NULL)                                                    \
        {                                                                     \
          MAYBE_SET_EINVAL;                                                   \
          return -1;                                                          \
@@ -113,7 +118,12 @@ ssize_t __wprintf_pad __P ((FILE *, wchar_t pad, size_t n));
   do                                                                         \
     {                                                                        \
       /* Check file argument for consistence.  */                            \
-      if (!__validfp(S) || !S->__mode.__write || Format == NULL)             \
+      if (!__validfp (S) || !S->__mode.__write)                                      \
+       {                                                                     \
+         __set_errno (EBADF);                                                \
+         return -1;                                                          \
+       }                                                                     \
+      if (Format == NULL)                                                    \
        {                                                                     \
          __set_errno (EINVAL);                                               \
          return -1;                                                          \
index 413d8f3..b8abe65 100644 (file)
@@ -1,20 +1,20 @@
 /* Copyright (C) 1991, 1995, 1996 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
+   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 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.
+   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.  */
+   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 <stddef.h>
 #include <stdio.h>
index 41e66fa..601fe4e 100644 (file)
@@ -1,20 +1,20 @@
 /* Copyright (C) 1991, 1996 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
+   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 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.
+   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.  */
+   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 <stdio.h>
index 8a3a0bc..6651035 100644 (file)
@@ -4,13 +4,14 @@
 int
 main(int argc, char *argv[])
 {
-  static const lens[16] = { 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4 };
+  static const size_t lens[] = { 0, 1, 0, 2, 0, 1, 0, 3,
+                                0, 1, 0, 2, 0, 1, 0, 4 };
   char buf[24];
-  int words;
+  size_t words;
 
   for (words = 0; words < 4; ++words)
     {
-      int last;
+      size_t last;
       memset (buf, 'a', words * 4);
 
       for (last = 0; last < 16; ++last)
index 8eb45b3..61b9937 100644 (file)
 #include <unistd.h>
 #include <signal.h>
 
+
+/* Function to close all streams and also make sure we don't loop by
+   calling abort while closing the streams.  */
+extern void __close_all_streams (void);
+
+
 /* Cause an abnormal program termination with core-dump.  */
 void
 abort (void)
 {
+  struct sigaction act;
   sigset_t sigs;
 
   if (__sigemptyset (&sigs) == 0 &&
       __sigaddset (&sigs, SIGABRT) == 0)
     __sigprocmask (SIG_UNBLOCK, &sigs, (sigset_t *) NULL);
 
+  /* If there is a user handler installed use it.  We don't close or
+     flush streams.  */
+  if (__sigaction (SIGABRT, NULL, &act) >= 0
+      && act.sa_handler != SIG_DFL)
+    {
+      /* Send signal to call user handler.  */
+      raise (SIGABRT);
+
+      /* It returns, so we are responsible for closing the streams.  */
+      __close_all_streams ();
+
+      /* There was a handler installed.  Now remove it.  */
+      memset (&act, '\0', sizeof (struct sigaction));
+      act.sa_handler = SIG_DFL;
+      __sigfillset (&act.sa_mask);
+      act.sa_flags = 0;
+      __sigaction (SIGABRT, &act, NULL);
+    }
+  else
+    /* No handler installed so the next `raise' will hopefully
+       terminate the process.  Therefore we must close the streams.  */
+    __close_all_streams ();
+
+  /* Try again.  */
+  raise (SIGABRT);
+
+  /* If we can't signal ourselves, exit.  */
+  _exit (127);
+
+  /* If even this fails make sure we never return.  */
   while (1)
-    if (raise (SIGABRT))
-      /* If we can't signal ourselves, exit.  */
-      _exit (127);
-  /* If we signal ourselves and are still alive,
-     or can't exit, loop forever.  */
+    /* For ever and ever.  */
+    ;
 }
index 23f6ed4..e2caa82 100644 (file)
@@ -53,6 +53,9 @@ typedef struct __libc_lock_opaque__ __libc_lock_t;
 /* Lock the named lock variable.  */
 #define __libc_lock_lock(NAME) __mutex_lock (&(NAME))
 
+/* Lock the named lock variable.  */
+#define __libc_lock_trylock(NAME) __mutex_trylock (&(NAME))
+
 /* Unlock the named lock variable.  */
 #define __libc_lock_unlock(NAME) __mutex_unlock (&(NAME))
 
index 572c0de..1a2c374 100644 (file)
@@ -1,20 +1,20 @@
 /* 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.  */
+   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 <stddef.h>
index 9539957..c069066 100644 (file)
 /* Copyright (C) 1991, 1995, 1996 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
+   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 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.
+   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.  */
+   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 <stddef.h>
 #include <unistd.h>
+#include <limits.h>
 #include <fcntl.h>
+#include <sys/statfs.h>
 
 /* Get file-specific information about PATH.  */
 long int
 __pathconf (const char *path, int name)
 {
-  int fd = open (path, 0);
-  if (fd >= 0)
+  if (path[0] == '\0')
     {
-      long int value = __fpathconf (fd, name);
-      int save = errno;
-      (void) close (fd);
-      __set_errno (save);
-      return value;
+      __set_errno (ENOENT);
+      return -1;
     }
-  return -1L;
+
+  switch (name)
+    {
+    default:
+      __set_errno (EINVAL);
+      return -1;
+
+    case _PC_LINK_MAX:
+#ifdef LINK_MAX
+      return LINK_MAX;
+#else
+      __set_errno (ENOSYS);
+      return -1;
+#endif
+
+    case _PC_MAX_CANON:
+#ifdef MAX_CANON
+      return MAX_CANON;
+#else
+      __set_errno (ENOSYS);
+      return -1;
+#endif
+
+    case _PC_MAX_INPUT:
+#ifdef MAX_INPUT
+      return MAX_INPUT;
+#else
+      __set_errno (ENOSYS);
+      return -1;
+#endif
+
+    case _PC_NAME_MAX:
+#ifdef NAME_MAX
+      {
+       struct statfs buf;
+
+       if (__statfs (path, &buf) < 0)
+         return errno == ENOSYS ? NAME_MAX : -1;
+       else
+         return buf.f_namelen;
+      }
+#else
+      __set_errno (ENOSYS);
+      return -1;
+#endif
+
+    case _PC_PATH_MAX:
+#ifdef PATH_MAX
+      return PATH_MAX;
+#else
+      __set_errno (ENOSYS);
+      return -1;
+#endif
+
+    case _PC_PIPE_BUF:
+#ifdef PIPE_BUF
+      return PIPE_BUF;
+#else
+      __set_errno (ENOSYS);
+      return -1;
+#endif
+
+    case _PC_CHOWN_RESTRICTED:
+#ifdef _POSIX_CHOWN_RESTRICTED
+      return _POSIX_CHOWN_RESTRICTED;
+#else
+      return -1;
+#endif
+
+    case _PC_NO_TRUNC:
+#ifdef _POSIX_NO_TRUNC
+      return _POSIX_NO_TRUNC;
+#else
+      return -1;
+#endif
+
+    case _PC_VDISABLE:
+#ifdef _POSIX_VDISABLE
+      return _POSIX_VDISABLE;
+#else
+      return -1;
+#endif
+
+    case _PC_SYNC_IO:
+#ifdef _POSIX_SYNC_IO
+      return _POSIX_SYNC_IO;
+#else
+      return -1;
+#endif
+
+    case _PC_ASYNC_IO:
+#ifdef _POSIX_ASYNC_IO
+      return _POSIX_ASYNC_IO;
+#else
+      return -1;
+#endif
+
+    case _PC_PRIO_IO:
+#ifdef _POSIX_PRIO_IO
+      return _POSIX_PRIO_IO;
+#else
+      return -1;
+#endif
+
+    case _PC_SOCK_MAXBUF:
+#ifdef SOCK_MAXBUF
+      return SOCK_MAXBUF;
+#else
+      __set_errno (ENOSYS);
+      return -1;
+#endif
+    }
+
+  __set_errno (ENOSYS);
+  return -1;
 }
 
 weak_alias (__pathconf, pathconf)
index d0a82fe..5eb698e 100644 (file)
@@ -49,7 +49,7 @@
 #define __libc_lock_lock(NAME)
 
 /* Try tp lock the named lock variable.  */
-#define __libc_lock_trylock(NAME)
+#define __libc_lock_trylock(NAME) 0
 
 /* Unlock the named lock variable.  */
 #define __libc_lock_unlock(NAME)
index bce3ada..5043651 100644 (file)
@@ -1,4 +1,4 @@
 inet
-nis
 resolv
 sunrpc
+nis
index ddf8663..4508848 100644 (file)
@@ -60,7 +60,7 @@ fi
 # Under Linux the LinuxThreads and crypt add-on should be available.
 case $add_ons in
   # Both are available.  Good.
-  *linuxthreads*des-crypt* | *des-crypt*linuxthreads*)
+  *linuxthreads*crypt* | *crypt*linuxthreads*)
     message=
     ;;
   *linuxthreads*)
@@ -68,14 +68,14 @@ case $add_ons in
 *** WARNING:
 *** Are you sure you do not want to use the \`crypt' add-on?"
     ;;
-  *des-crypt*)
+  *crypt*)
     message="\
 *** WARNING:
-*** Are you sure you do not want to use the \`LinuxThread' add-on?"
+*** Are you sure you do not want to use the \`linuxthread' add-on?"
     ;;
   *)
     message="\
-*** WARNING: Are you sure you do not want to use the \`LinuxThreads'
+*** WARNING: Are you sure you do not want to use the \`linuxthreads'
 *** and \`crypt' add-ons?"
     ;;
 esac
@@ -83,7 +83,7 @@ esac
 if test "$message"; then
   if test $enable_sanity = yes; then
     echo "\
-*** You should not compile the GNU libc without the \`LinuxThreads' and
+*** You should not compile the GNU libc without the \`linuxthreads' and
 *** \`crypt' add-on.  Not using them risks to be incompatible with the
 *** libraries of other systems.  Consider getting the add-ons and restart
 *** the configuration.
index fe499af..174eb32 100644 (file)
@@ -45,7 +45,7 @@ fi
 # Under Linux the LinuxThreads and crypt add-on should be available.
 case $add_ons in
   # Both are available.  Good.
-  *linuxthreads*des-crypt* | *des-crypt*linuxthreads*)
+  *linuxthreads*crypt* | *crypt*linuxthreads*)
     message=
     ;;
   *linuxthreads*)
@@ -53,14 +53,14 @@ case $add_ons in
 *** WARNING:
 *** Are you sure you do not want to use the \`crypt' add-on?"
     ;;
-  *des-crypt*)
+  *crypt*)
     message="\
 *** WARNING:
-*** Are you sure you do not want to use the \`LinuxThread' add-on?"
+*** Are you sure you do not want to use the \`linuxthread' add-on?"
     ;;
   *)
     message="\
-*** WARNING: Are you sure you do not want to use the \`LinuxThreads'
+*** WARNING: Are you sure you do not want to use the \`linuxthreads'
 *** and \`crypt' add-ons?"
     ;;
 esac
@@ -68,7 +68,7 @@ esac
 if test "$message"; then
   if test $enable_sanity = yes; then
     echo "\
-*** You should not compile the GNU libc without the \`LinuxThreads' and
+*** You should not compile the GNU libc without the \`linuxthreads' and
 *** \`crypt' add-on.  Not using them risks to be incompatible with the
 *** libraries of other systems.  Consider getting the add-ons and restart
 *** the configuration.
index f5629fc..53c4fc5 100644 (file)
@@ -48,8 +48,9 @@
 #define        _PATH_DEVDB     "/var/run/dev.db"
 #define        _PATH_DEVNULL   "/dev/null"
 #define        _PATH_DRUM      "/dev/drum"
+#define        _PATH_KLOG      "/proc/kmsg"
 #define        _PATH_KMEM      "/dev/kmem"
-#define _PATH_LASTLOG  "/var/log/lastlog"
+#define        _PATH_LASTLOG   "/var/log/lastlog"
 #define        _PATH_MAILDIR   "/var/spool/mail"
 #define        _PATH_MAN       "/usr/man"
 #define        _PATH_MEM       "/dev/mem"
index ce243e6..833d708 100644 (file)
@@ -41,7 +41,7 @@ __localtime_r (timer, tp)
      and in tzfile.c; the internal functions do no locking themselves.
      This lock is only taken here and in `tzset'.  */
   __libc_lock_define (extern, __tzset_lock)
-  extern int __tzset_run, __use_tzfile;
+  extern int __use_tzfile;
   extern int __tz_compute __P ((time_t timer, struct tm *tp));
   extern int __tzfile_compute __P ((time_t timer,
                                    long int *leap_correct, int *leap_hit));
@@ -57,8 +57,7 @@ __localtime_r (timer, tp)
   __libc_lock_lock (__tzset_lock);
 
   /* Make sure the database is initialized.  */
-  if (! __tzset_run)
-    __tzset ();
+  __tzset ();
 
   if (__use_tzfile)
     {
index 092739d..ddea024 100644 (file)
@@ -27,6 +27,8 @@
 # define HAVE_STRUCT_ERA_ENTRY 1
 # define HAVE_TM_GMTOFF 1
 # define HAVE_TM_ZONE 1
+# define HAVE_TZNAME 1
+# define HAVE_TZSET 1
 # define MULTIBYTE_IS_FORMAT_SAFE 1
 # define STDC_HEADERS 1
 # include <ansidecl.h>
@@ -79,7 +81,7 @@ extern char *tzname[];
 # include <stdlib.h>
 # include <string.h>
 #else
-# define memcpy(d, s, n) bcopy (s, d, n)
+# define memcpy(d, s, n) bcopy ((s), (d), (n))
 #endif
 
 #ifndef __P
@@ -125,6 +127,7 @@ extern char *tzname[];
 #ifdef _LIBC
 # define gmtime_r __gmtime_r
 # define localtime_r __localtime_r
+extern int __tz_compute __P ((time_t timer, const struct tm *tm));
 #else
 # if ! HAVE_LOCALTIME_R
 #  if ! HAVE_TM_GMTOFF
@@ -162,7 +165,28 @@ localtime_r (t, tp)
 #endif /* ! defined (_LIBC) */
 
 
+#if !defined (memset) && !defined (HAVE_MEMSET) && !defined (_LIBC)
+/* Some systems lack the `memset' function and we don't want to
+   introduce additional dependencies.  */
 static const char spaces[16] = "                ";
+
+# define memset_space(P, Len) \
+  do {                                                                       \
+    int _len = (Len);                                                        \
+                                                                             \
+    do                                                                       \
+      {                                                                              \
+       int _this = _len > 16 ? 16 : _len;                                    \
+       memcpy ((P), spaces, _this);                                          \
+       (P) += _this;                                                         \
+       _len -= _this;                                                        \
+      }                                                                              \
+    while (_len > 0);                                                        \
+  } while (0)
+#else
+# define memset_space(P, Len) memset ((P), ' ', (Len))
+#endif
+
 #define        add(n, f) \
   do                                                                         \
     {                                                                        \
@@ -174,13 +198,8 @@ static const char spaces[16] = "                ";
       else                                                                   \
        if (p)                                                                \
          {                                                                   \
-           while (_delta > 0)                                                \
-             {                                                               \
-               int _this = _delta > 16 ? 16 : _delta;                        \
-               memcpy (p, spaces, _this);                                    \
-               p += _this;                                                   \
-               _delta -= _this;                                              \
-             }                                                               \
+           if (_delta > 0)                                                   \
+             memset_space (p, _delta);                                       \
            f;                                                                \
            p += _n;                                                          \
          }                                                                   \
@@ -325,11 +344,26 @@ strftime (s, maxsize, format, tp)
   char *p = s;
   const char *f;
 
-  zone = 0;
-#if HAVE_TM_ZONE
+  zone = NULL;
+#if !defined _LIBC && HAVE_TM_ZONE
+  /* XXX We have some problems here.  First, the string pointed to by
+     tm_zone is dynamically allocated while loading the zone data.  But
+     when another zone is loaded since the information in TP were
+     computed this would be a stale pointer.
+     The second problem is the POSIX test suite which assumes setting
+     the environment variable TZ to a new value before calling strftime()
+     will influence the result (the %Z format) even if the information in
+     TP is computed with a totally different time zone.  --drepper@gnu  */
   zone = (const char *) tp->tm_zone;
 #endif
 #if HAVE_TZNAME
+  /* POSIX.1 8.1.1 requires that whenever strftime() is called, the
+     time zone names contained in the external variable `tzname' shall
+     be set as if the tzset() function had been called.  */
+# if HAVE_TZSET
+  tzset ();
+# endif
+
   if (!(zone && *zone) && tp->tm_isdst >= 0)
     zone = tzname[tp->tm_isdst];
 #endif
index 954cec2..6a9ebe1 100644 (file)
@@ -74,7 +74,7 @@ static tz_rule tz_rules[2];
 
 static int compute_change __P ((tz_rule *rule, int year));
 \f
-int __tzset_run = 0;
+static char *old_tz = NULL;
 
 /* Interpret the TZ envariable.  */
 void
@@ -85,6 +85,20 @@ __tzset ()
   unsigned short int hh, mm, ss;
   unsigned short int whichrule;
 
+  /* Examine the TZ environment variable.  */
+  tz = getenv ("TZ");
+
+  /* A leading colon means "implementation defined syntax".
+     We ignore the colon and always use the same algorithm:
+     try a data file, and if none exists parse the 1003.1 syntax.  */
+  if (tz && *tz == ':')
+    ++tz;
+
+  /* Check whether the value changes since the last run.  */
+  if (old_tz != NULL && tz != NULL && strcmp (tz, old_tz) == 0)
+    /* No change, simply return.  */
+    return;
+
   /* Free old storage.  */
   if (tz_rules[0].name != NULL && *tz_rules[0].name != '\0')
     {
@@ -98,22 +112,15 @@ __tzset ()
       tz_rules[1].name = NULL;
     }
 
-  /* Examine the TZ environment variable.  */
-  tz = getenv ("TZ");
-
-  /* A leading colon means "implementation defined syntax".
-     We ignore the colon and always use the same algorithm:
-     try a data file, and if none exists parse the 1003.1 syntax.  */
-  if (tz && *tz == ':')
-    ++tz;
+  /* Save the value of `tz'.  */
+  if (old_tz != NULL)
+    free (old_tz);
+  old_tz = tz ? __strdup (tz) : NULL;
 
   /* Try to read a data file.  */
   __tzfile_read (tz);
   if (__use_tzfile)
-    {
-      __tzset_run = 1;
-      return;
-    }
+    return;
 
   /* No data file found.  Default to UTC if nothing specified.  */
 
@@ -121,10 +128,10 @@ __tzset ()
     {
       static const char UTC[] = "UTC";
       size_t len = sizeof UTC;
-      tz_rules[0].name = (char *) malloc(len);
+      tz_rules[0].name = (char *) malloc (len);
       if (tz_rules[0].name == NULL)
        return;
-      tz_rules[1].name = (char *) malloc(len);
+      tz_rules[1].name = (char *) malloc (len);
       if (tz_rules[1].name == NULL)
        return;
       memcpy ((void *) tz_rules[0].name, UTC, len);
@@ -136,7 +143,6 @@ __tzset ()
       tz_rules[0].offset = tz_rules[1].offset = 0L;
       tz_rules[0].change = tz_rules[1].change = (time_t) -1;
       tz_rules[0].computed_for = tz_rules[1].computed_for = 0;
-      __tzset_run = 1;
       return;
     }
 
@@ -147,8 +153,12 @@ __tzset ()
   /* Get the standard timezone name.  */
   tz_rules[0].name = (char *) malloc (strlen (tz) + 1);
   if (tz_rules[0].name == NULL)
-    /* Don't set __tzset_run so we will try again.  */
-    return;
+    {
+      /* Clear the old tz name so we will try again.  */
+      free (old_tz);
+      old_tz = NULL;
+      return;
+    }
 
   if (sscanf(tz, "%[^0-9,+-]", tz_rules[0].name) != 1 ||
       (l = strlen(tz_rules[0].name)) < 3)
@@ -257,7 +267,8 @@ __tzset ()
                        tz_rules[0].offset, tz_rules[1].offset);
       if (__use_tzfile)
        {
-         __tzset_run = 1;
+         free (old_tz);
+         old_tz = NULL;
          return;
        }
     }
@@ -353,8 +364,6 @@ __tzset ()
 
       tzr->computed_for = -1;
     }
-
-  __tzset_run = 1;
 }
 \f
 /* Maximum length of a timezone name.  __tz_compute keeps this up to date
@@ -365,8 +374,7 @@ size_t __tzname_cur_max;
 long int
 __tzname_max ()
 {
-  if (! __tzset_run)
-    __tzset ();
+  __tzset ();
 
   return __tzname_cur_max;
 }
@@ -450,7 +458,7 @@ compute_change (rule, year)
   /* T is now the Epoch-relative time of 0:00:00 GMT on the day we want.
      Just add the time of day and local offset from GMT, and we're done.  */
 
-  rule->change = t + rule->offset + rule->secs;
+  rule->change = t - rule->offset + rule->secs;
   rule->computed_for = year;
   return 1;
 }
@@ -464,8 +472,7 @@ __tz_compute (timer, tm)
      time_t timer;
      const struct tm *tm;
 {
-  if (! __tzset_run)
-    __tzset ();
+  __tzset ();
 
   if (! compute_change (&tz_rules[0], 1900 + tm->tm_year) ||
       ! compute_change (&tz_rules[1], 1900 + tm->tm_year))
@@ -504,6 +511,12 @@ weak_function
 tzset (void)
 {
   __libc_lock_lock (__tzset_lock);
+
   __tzset ();
+
+  /* Set `tzname'.  */
+  __tzname[0] = (char *) tz_rules[0].name;
+  __tzname[1] = (char *) tz_rules[1].name;
+
   __libc_lock_unlock (__tzset_lock);
 }