about summary refs log tree commit diff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1997-03-19 05:47:56 +0000
committerUlrich Drepper <drepper@redhat.com>1997-03-19 05:47:56 +0000
commite61abf83986463e263de965d487fac5cb083839a (patch)
treefa0a23e631c0c3e7f7b38c609e7fa808b1275933
parent6465cfc9cf96f06a34227b557332f002f109f0ec (diff)
downloadglibc-e61abf83986463e263de965d487fac5cb083839a.tar.gz
glibc-e61abf83986463e263de965d487fac5cb083839a.tar.xz
glibc-e61abf83986463e263de965d487fac5cb083839a.zip
1997-03-19 01:40  Ulrich Drepper  <drepper@cygnus.com>

	* sysdeps/unix/sysv/sco3.2.4/Dist: New file.

	* sysdeps/unix/sysv/sysv4/Dist: Add __getpgid.c and __setpgid.c.

	* sysdeps/unix/bsd/Dist: Add bsdstat.h, setrgid.c, and setruid.c.

	* sysdeps/unix/sysv/Dist: Add direct.h.

	* sysdeps/unix/sysv/linux/Dist: Add netinet/tcp.h.

	* Make-dist ($(tardir).tar): Prefer writing temporary file to
	$TMPDIR is available.  The default is /tmp.

	* sysdeps/generic/ip.h: Move to...
	* sysdeps/generic/netinet/ip.h: ...here.

	* Makefile (tests): Quote $(CC) argument to isomac program.
	Patch by H.J. Lu <hjl@gnu.ai.mit.edu>.

	* sysdeps/i386/setjmp.S (__setjmp): Fix fatal bug where 0 argument
	is placed in wrong place on the stack.
	Reported by Marc Lehmann <mlehmann@hildesheim.sgh-net.de>.
	* sysdeps/tst-setjmp.c: Add new test for above problem.

	* sysdeps/libm-i387/e_pow.S: Compute PIC addres early.
	* sysdeps/libm-i387/e_powf.S: Likewise.
	* sysdeps/libm-i387/e_powl.S: Likewise.

1997-03-18 23:18  Ulrich Drepper  <drepper@cygnus.com>

	* time/offtime.c (__offtime): Change type of `yg' to long int.
	Reported by a sun <asun@zoology.washington.edu>.

1997-03-18 23:08  a sun  <asun@zoology.washington.edu>

	* sysdeps/unix/sysv/linux/net/if_ppp.h (PPP_VERSION): Define to
	2.2.0 to prevent version mismatch.

1997-03-17 19:26  Andreas Jaeger  <aj@arthur.pfalz.de>

	* stdio-common/printf_fphex.c (MIN): Only define MIN if not
	already defined.

1997-03-14 23:34  Geoff Keating  <geoffk@ozemail.com.au>

	* sysdeps/unix/sysv/linux/powerpc/termbits.h: Leave ioctl numbers
	in ioctls.h.

	* elf/rtld.c (_dl_start): Call elf_machine_runtime_setup when the
	loader first relocates itself.
	* sysdeps/powerpc/elf/start.c (__start1): Fix bug for static objects.
	* sysdeps/powerpc/dl-machine.h (elf_machine_rela): Fix bugs in
	jump slot relocation. Prefer relative branches (some PowerPC chips
	don't predict absolute branches).
	(elf_machine_runtime_setup): Simplify and correct expressions.
	(RTLD_START): Fix bug changing _dl_starting_up.
	* sysdeps/unix/sysv/linux/powerpc/dl-sysdep.c: Added. Deal with
	strange Linux/PPC padding of initial stack.

1997-03-11 04:14  Geoff Keating  <geoffk@ozemail.com.au>

	* sysdeps/unix/sysv/linux/powerpc/termbits.h: Increase NCCS to 39,
	for future expansion.
	* sysdeps/unix/sysv/linux/powerpc/sys/kernel_termios.h: Added.
	* sysdeps/powerpc/dl-machine.h (elf_machine_rela): Explain why it
	can't have a switch statement.
	* sysdeps/powerpc/elf/start.c (__start1): Explain why it can't be
	static.

	* sysdeps/powerpc/elf/start.c (_start): Use .previous to avoid
	confusing gcc's idea of the current section.
	* sysdeps/powerpc/dl-machine.h (ELF_MACHINE_RUNTIME_TRAMPOLINE,
	RTLD_START): Likewise.

1997-03-08 09:10  Geoff Keating  <geoffk@ozemail.com.au>

	* sysdeps/powerpc/dl-machine.h (elf_machine_rela,
	elf_machine_runtime_setup): Flush data & instruction caches when
	necessary, for 603/604 support. Add better support for large PLTs.
	(elf_machine_rela): Remove relocations that wouldn't work if
	anyone ever used them. Use memcpy for copy reloc, it'll be safe.
	Never target branch relocations at a PLT entry.

	* sysdeps/powerpc/bsd-setjmp.S: Make jump to PLT entry if we are
	generating PIC.
	* sysdeps/powerpc/bsd-_setjmp.S: Likewise.
	* sysdeps/powerpc/setjmp.S: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/clone.S: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/socket.S: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/syscall.S: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/sysdep.h: Likewise.

	* sysdeps/powerpc/elf/start.c: Clean up.

	* sysdeps/powerpc/__longjmp.S: Return 'value' as result from
	setjmp call.

	* sysdeps/unix/sysv/linux/powerpc/statbuf.h: New file.

1997-03-09 12:36  H.J. Lu  <hjl@gnu.ai.mit.edu>

	* Make-dist (srcs): Add $(test-srcs).
	* MakeTAGS (all-sources): Likewise.
	* Makerules (depfiles, common-mostlyclean): Likewise.
	* Rules (tests): Likewise.

1997-03-18 05:28  Roland McGrath  <roland@frob.com>

	* elf/dl-reloc.c (RESOLVE): Don't try to resolve ocal symbols.

1997-03-17 21:39  Philip Blundell  <phil@london.uk.eu.org>

	* nis/nss_nis/nis-service.c (_nss_nis_getservbyname_r): Allow
	protocol=NULL to match any protocol rather than returning an
	error.

1997-03-17 19:00  Philip Blundell  <phil@london.uk.eu.org>

	* nss/nss_files/files-service.c (servbyname): Match any protocol
	if proto==NULL.

1997-03-18 05:17  Ulrich Drepper  <drepper@cygnus.com>

	* sysdeps/unix/sysv/linux/alpha/fcntlbits.h: Don't define O_NORW.
	* sysdeps/unix/sysv/linux/fcntlbits.h: Likewise.
	Proposed by Thomas Bushnell, n/BSG.

1997-03-18 07:53  H.J. Lu  <hjl@gnu.ai.mit.edu>

	* sysdeps/generic/setenv.c (setenv): Don't copy name when we reuse
	the buffer for replacement.

1997-03-16 19:30  H.J. Lu  <hjl@gnu.ai.mit.edu>

	* sysdeps/unix/sysv/linux/syscalls.list: Add sys_fstat,
	sys_lstat and sys_stat.

1997-03-17 12:43  Thorsten Kukuk  <kukuk@vt.uni-paderborn.de>

	Add NIS+ functions
	* shlib-versions: Add libnss_nisplus.
	* nis/Makefile: Add NIS+ source files.
	* nis/nis_call.c: New file.
	* nis/nis_clone.c: New file.
	* nis/nis_error.c: New file.
	* nis/nis_file.c: New file.
	* nis/nis_free.c: New file.
	* nis/nis_intern.c: New file.
	* nis/nis_intern.h: New file.
	* nis/nis_local_names.c: New file.
	* nis/nis_names.c: New file.
	* nis/nis_print.c: New file.
	* nis/nis_server.c: New file.
	* nis/nis_subr.c: New file.
	* nis/nis_table.c: New file.
	* nis/nis_xdr.c: New file.
	* nis/nss-nisplus.h: New file.
	* nis/nss_nisplus/nisplus-alias.c: New file.
	* nis/nss_nisplus/nisplus-ethers.c: New file.
	* nis/nss_nisplus/nisplus-grp.c: New file.
	* nis/nss_nisplus/nisplus-hosts.c: New file.
	* nis/nss_nisplus/nisplus-netgrp.c: New file.
	* nis/nss_nisplus/nisplus-network.c: New file.
	* nis/nss_nisplus/nisplus-proto.c: New file.
	* nis/nss_nisplus/nisplus-publickey.c: New file.
	* nis/nss_nisplus/nisplus-pwd.c: New file.
	* nis/nss_nisplus/nisplus-rpc.c: New file.
	* nis/nss_nisplus/nisplus-service.c: New file.
	* nis/nss_nisplus/nisplus-spwd.c: New file.
	* nis/rpcsvc/nis.h: New file.
	* nis/rpcsvc/nis.x: New file.
	* nis/rpcsvc/nis_object.x: New file.
	* nis/rpcsvc/nis_tags.h: New file.
	* nis/rpcsvc/nislib.h: New file.

1997-03-17 12:52  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>

	* mach/devstream.c (output/write_some): Don't try and write more
	than IO_INBAND_MAX in a single call to device_write_inband.

	* sysdeps/libm-ieee754/w_atan2.c: Don't ignore exception if library
	* sysdeps/libm-ieee754/w_atan2f.c: Likewise.
	* sysdeps/libm-ieee754/w_atan2l.c: Likewise.
	* sysdeps/unix/sysv/linux/sys/mman.h (msync): Add description for
	* stdlib/atoll.c: Undefine atoll, not atol.
-rw-r--r--.cvsignore2
-rw-r--r--ChangeLog192
-rw-r--r--Make-dist8
-rw-r--r--MakeTAGS4
-rw-r--r--Makefile2
-rw-r--r--Makerules7
-rw-r--r--NEWS16
-rw-r--r--Rules8
-rw-r--r--csu/.cvsignore1
-rw-r--r--elf/dl-reloc.c5
-rw-r--r--elf/rtld.c1
-rw-r--r--mach/devstream.c8
-rw-r--r--nis/Banner2
-rw-r--r--nis/Makefile40
-rw-r--r--nis/TODO40
-rw-r--r--nis/nis_call.c220
-rw-r--r--nis/nis_clone.c551
-rw-r--r--nis/nis_error.c124
-rw-r--r--nis/nis_file.c108
-rw-r--r--nis/nis_free.c334
-rw-r--r--nis/nis_intern.c169
-rw-r--r--nis/nis_intern.h39
-rw-r--r--nis/nis_local_names.c184
-rw-r--r--nis/nis_names.c238
-rw-r--r--nis/nis_print.c308
-rw-r--r--nis/nis_server.c143
-rw-r--r--nis/nis_subr.c310
-rw-r--r--nis/nis_table.c417
-rw-r--r--nis/nis_xdr.c572
-rw-r--r--nis/nss-nisplus.h90
-rw-r--r--nis/nss_nis/nis-service.c4
-rw-r--r--nis/nss_nisplus/nisplus-alias.c251
-rw-r--r--nis/nss_nisplus/nisplus-ethers.c278
-rw-r--r--nis/nss_nisplus/nisplus-grp.c387
-rw-r--r--nis/nss_nisplus/nisplus-hosts.c412
-rw-r--r--nis/nss_nisplus/nisplus-netgrp.c141
-rw-r--r--nis/nss_nisplus/nisplus-network.c340
-rw-r--r--nis/nss_nisplus/nisplus-proto.c284
-rw-r--r--nis/nss_nisplus/nisplus-publickey.c347
-rw-r--r--nis/nss_nisplus/nisplus-pwd.c293
-rw-r--r--nis/nss_nisplus/nisplus-rpc.c284
-rw-r--r--nis/nss_nisplus/nisplus-service.c308
-rw-r--r--nis/nss_nisplus/nisplus-spwd.c262
-rw-r--r--nis/rpcsvc/nis.h1008
-rw-r--r--nis/rpcsvc/nis.x446
-rw-r--r--nis/rpcsvc/nis_object.x287
-rw-r--r--nis/rpcsvc/nis_tags.h95
-rw-r--r--nis/rpcsvc/nislib.h165
-rw-r--r--nss/nss_files/files-service.c4
-rw-r--r--setjmp/tst-setjmp.c23
-rw-r--r--shlib-versions4
-rw-r--r--sysdeps/generic/setenv.c4
-rw-r--r--sysdeps/i386/setjmp.S30
-rw-r--r--sysdeps/libm-i387/e_pow.S13
-rw-r--r--sysdeps/libm-i387/e_powf.S13
-rw-r--r--sysdeps/libm-i387/e_powl.S13
-rw-r--r--sysdeps/powerpc/__longjmp.S1
-rw-r--r--sysdeps/powerpc/bsd-_setjmp.S6
-rw-r--r--sysdeps/powerpc/bsd-setjmp.S33
-rw-r--r--sysdeps/powerpc/dl-machine.h396
-rw-r--r--sysdeps/powerpc/elf/start.c77
-rw-r--r--sysdeps/powerpc/setjmp.S4
-rw-r--r--sysdeps/unix/bsd/Dist5
-rw-r--r--sysdeps/unix/sysv/Dist1
-rw-r--r--sysdeps/unix/sysv/linux/Dist1
-rw-r--r--sysdeps/unix/sysv/linux/alpha/fcntlbits.h1
-rw-r--r--sysdeps/unix/sysv/linux/fcntlbits.h1
-rw-r--r--sysdeps/unix/sysv/linux/net/if_ppp.h2
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/clone.S4
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/dl-sysdep.c237
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/kernel_termios.h25
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/socket.S4
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/statbuf.h79
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/syscall.S4
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/sysdep.h12
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/termbits.h82
-rw-r--r--sysdeps/unix/sysv/linux/readv.c71
-rw-r--r--sysdeps/unix/sysv/linux/syscalls.list5
-rw-r--r--sysdeps/unix/sysv/linux/writev.c68
-rw-r--r--sysdeps/unix/sysv/sco3.2.4/Dist1
-rw-r--r--sysdeps/unix/sysv/sysv4/Dist2
-rw-r--r--time/offtime.c2
82 files changed, 10596 insertions, 367 deletions
diff --git a/.cvsignore b/.cvsignore
index 606e7270bd..2cb16cdb10 100644
--- a/.cvsignore
+++ b/.cvsignore
@@ -1,4 +1,4 @@
-*.d *.o *.so *.po *.go stamp.* *.stamp *.ustamp *.udeps
+*.d *.o *.so *.po *.go *.bo stamp.* *.stamp *.ustamp *.udeps
 *.gz *.Z *.tar *.tgz
 =*
 TODO COPYING* AUTHORS copyr-* copying.*
diff --git a/ChangeLog b/ChangeLog
index 721962522c..3346ffbf2f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,11 +1,193 @@
+1997-03-19 01:40  Ulrich Drepper  <drepper@cygnus.com>
+
+	* sysdeps/unix/sysv/sco3.2.4/Dist: New file.
+
+	* sysdeps/unix/sysv/sysv4/Dist: Add __getpgid.c and __setpgid.c.
+
+	* sysdeps/unix/bsd/Dist: Add bsdstat.h, setrgid.c, and setruid.c.
+
+	* sysdeps/unix/sysv/Dist: Add direct.h.
+
+	* sysdeps/unix/sysv/linux/Dist: Add netinet/tcp.h.
+
+	* Make-dist ($(tardir).tar): Prefer writing temporary file to
+	$TMPDIR is available.  The default is /tmp.
+
+	* sysdeps/generic/ip.h: Move to...
+	* sysdeps/generic/netinet/ip.h: ...here.
+
+	* Makefile (tests): Quote $(CC) argument to isomac program.
+	Patch by H.J. Lu <hjl@gnu.ai.mit.edu>.
+
+	* sysdeps/i386/setjmp.S (__setjmp): Fix fatal bug where 0 argument
+	is placed in wrong place on the stack.
+	Reported by Marc Lehmann <mlehmann@hildesheim.sgh-net.de>.
+	* sysdeps/tst-setjmp.c: Add new test for above problem.
+
+	* sysdeps/libm-i387/e_pow.S: Compute PIC addres early.
+	* sysdeps/libm-i387/e_powf.S: Likewise.
+	* sysdeps/libm-i387/e_powl.S: Likewise.
+
+1997-03-18 23:18  Ulrich Drepper  <drepper@cygnus.com>
+
+	* time/offtime.c (__offtime): Change type of `yg' to long int.
+	Reported by a sun <asun@zoology.washington.edu>.
+
+1997-03-18 23:08  a sun  <asun@zoology.washington.edu>
+
+	* sysdeps/unix/sysv/linux/net/if_ppp.h (PPP_VERSION): Define to
+	2.2.0 to prevent version mismatch.
+
+1997-03-17 19:26  Andreas Jaeger  <aj@arthur.pfalz.de>
+
+	* stdio-common/printf_fphex.c (MIN): Only define MIN if not
+	already defined.
+
+1997-03-14 23:34  Geoff Keating  <geoffk@ozemail.com.au>
+
+	* sysdeps/unix/sysv/linux/powerpc/termbits.h: Leave ioctl numbers
+	in ioctls.h.
+
+	* elf/rtld.c (_dl_start): Call elf_machine_runtime_setup when the
+	loader first relocates itself.
+	* sysdeps/powerpc/elf/start.c (__start1): Fix bug for static objects.
+	* sysdeps/powerpc/dl-machine.h (elf_machine_rela): Fix bugs in
+	jump slot relocation. Prefer relative branches (some PowerPC chips
+	don't predict absolute branches).
+	(elf_machine_runtime_setup): Simplify and correct expressions.
+	(RTLD_START): Fix bug changing _dl_starting_up.
+	* sysdeps/unix/sysv/linux/powerpc/dl-sysdep.c: Added. Deal with
+	strange Linux/PPC padding of initial stack.
+
+1997-03-11 04:14  Geoff Keating  <geoffk@ozemail.com.au>
+
+	* sysdeps/unix/sysv/linux/powerpc/termbits.h: Increase NCCS to 39,
+	for future expansion.
+	* sysdeps/unix/sysv/linux/powerpc/sys/kernel_termios.h: Added.
+	* sysdeps/powerpc/dl-machine.h (elf_machine_rela): Explain why it
+	can't have a switch statement.
+	* sysdeps/powerpc/elf/start.c (__start1): Explain why it can't be
+	static.
+
+	* sysdeps/powerpc/elf/start.c (_start): Use .previous to avoid
+	confusing gcc's idea of the current section.
+	* sysdeps/powerpc/dl-machine.h (ELF_MACHINE_RUNTIME_TRAMPOLINE,
+	RTLD_START): Likewise.
+
+1997-03-08 09:10  Geoff Keating  <geoffk@ozemail.com.au>
+
+	* sysdeps/powerpc/dl-machine.h (elf_machine_rela,
+	elf_machine_runtime_setup): Flush data & instruction caches when
+	necessary, for 603/604 support. Add better support for large PLTs.
+	(elf_machine_rela): Remove relocations that wouldn't work if
+	anyone ever used them. Use memcpy for copy reloc, it'll be safe.
+	Never target branch relocations at a PLT entry.
+
+	* sysdeps/powerpc/bsd-setjmp.S: Make jump to PLT entry if we are
+	generating PIC.
+	* sysdeps/powerpc/bsd-_setjmp.S: Likewise.
+	* sysdeps/powerpc/setjmp.S: Likewise.
+	* sysdeps/unix/sysv/linux/powerpc/clone.S: Likewise.
+	* sysdeps/unix/sysv/linux/powerpc/socket.S: Likewise.
+	* sysdeps/unix/sysv/linux/powerpc/syscall.S: Likewise.
+	* sysdeps/unix/sysv/linux/powerpc/sysdep.h: Likewise.
+
+	* sysdeps/powerpc/elf/start.c: Clean up.
+
+	* sysdeps/powerpc/__longjmp.S: Return 'value' as result from
+	setjmp call.
+
+	* sysdeps/unix/sysv/linux/powerpc/statbuf.h: New file.
+
+1997-03-09 12:36  H.J. Lu  <hjl@gnu.ai.mit.edu>
+
+	* Make-dist (srcs): Add $(test-srcs).
+	* MakeTAGS (all-sources): Likewise.
+	* Makerules (depfiles, common-mostlyclean): Likewise.
+	* Rules (tests): Likewise.
+
+1997-03-18 05:28  Roland McGrath  <roland@frob.com>
+
+	* elf/dl-reloc.c (RESOLVE): Don't try to resolve ocal symbols.
+
+1997-03-17 21:39  Philip Blundell  <phil@london.uk.eu.org>
+
+	* nis/nss_nis/nis-service.c (_nss_nis_getservbyname_r): Allow
+	protocol=NULL to match any protocol rather than returning an
+	error.
+
+1997-03-17 19:00  Philip Blundell  <phil@london.uk.eu.org>
+
+	* nss/nss_files/files-service.c (servbyname): Match any protocol
+	if proto==NULL.
+
+1997-03-18 05:17  Ulrich Drepper  <drepper@cygnus.com>
+
+	* sysdeps/unix/sysv/linux/alpha/fcntlbits.h: Don't define O_NORW.
+	* sysdeps/unix/sysv/linux/fcntlbits.h: Likewise.
+	Proposed by Thomas Bushnell, n/BSG.
+
+1997-03-18 07:53  H.J. Lu  <hjl@gnu.ai.mit.edu>
+
+	* sysdeps/generic/setenv.c (setenv): Don't copy name when we reuse
+	the buffer for replacement.
+
+1997-03-16 19:30  H.J. Lu  <hjl@gnu.ai.mit.edu>
+
+	* sysdeps/unix/sysv/linux/syscalls.list: Add sys_fstat,
+	sys_lstat and sys_stat.
+
+1997-03-17 12:43  Thorsten Kukuk  <kukuk@vt.uni-paderborn.de>
+
+	Add NIS+ functions
+	* shlib-versions: Add libnss_nisplus.
+	* nis/Makefile: Add NIS+ source files.
+	* nis/nis_call.c: New file.
+	* nis/nis_clone.c: New file.
+	* nis/nis_error.c: New file.
+	* nis/nis_file.c: New file.
+	* nis/nis_free.c: New file.
+	* nis/nis_intern.c: New file.
+	* nis/nis_intern.h: New file.
+	* nis/nis_local_names.c: New file.
+	* nis/nis_names.c: New file.
+	* nis/nis_print.c: New file.
+	* nis/nis_server.c: New file.
+	* nis/nis_subr.c: New file.
+	* nis/nis_table.c: New file.
+	* nis/nis_xdr.c: New file.
+	* nis/nss-nisplus.h: New file.
+	* nis/nss_nisplus/nisplus-alias.c: New file.
+	* nis/nss_nisplus/nisplus-ethers.c: New file.
+	* nis/nss_nisplus/nisplus-grp.c: New file.
+	* nis/nss_nisplus/nisplus-hosts.c: New file.
+	* nis/nss_nisplus/nisplus-netgrp.c: New file.
+	* nis/nss_nisplus/nisplus-network.c: New file.
+	* nis/nss_nisplus/nisplus-proto.c: New file.
+	* nis/nss_nisplus/nisplus-publickey.c: New file.
+	* nis/nss_nisplus/nisplus-pwd.c: New file.
+	* nis/nss_nisplus/nisplus-rpc.c: New file.
+	* nis/nss_nisplus/nisplus-service.c: New file.
+	* nis/nss_nisplus/nisplus-spwd.c: New file.
+	* nis/rpcsvc/nis.h: New file.
+	* nis/rpcsvc/nis.x: New file.
+	* nis/rpcsvc/nis_object.x: New file.
+	* nis/rpcsvc/nis_tags.h: New file.
+	* nis/rpcsvc/nislib.h: New file.
+
+1997-03-17 12:52  Thomas Bushnell, n/BSG  <thomas@gnu.ai.mit.edu>
+
+	* mach/devstream.c (output/write_some): Don't try and write more
+	than IO_INBAND_MAX in a single call to device_write_inband.
+
 1997-03-17 04:00  Ulrich Drepper  <drepper@cygnus.com>
 
-	* sysdeps/libmieee754/w_atan2.c: Don't ignore exception if library
+	* sysdeps/libm-ieee754/w_atan2.c: Don't ignore exception if library
 	type is SVID.
-	* sysdeps/libmieee754/w_atan2f.c: Likewise.
-	* sysdeps/libmieee754/w_atan2l.c: Likewise.
+	* sysdeps/libm-ieee754/w_atan2f.c: Likewise.
+	* sysdeps/libm-ieee754/w_atan2l.c: Likewise.
 
-	* sysdeps/unix/sysv/linux/sys/mman.h (msync): Add descrption for
+	* sysdeps/unix/sysv/linux/sys/mman.h (msync): Add description for
 	FLAGS parameter.
 
 1997-03-16 20:28  Philip Blundell  <phil@london.uk.eu.org>
@@ -2099,7 +2281,7 @@
 
 1997-02-11 14:49  Andreas Jaeger  <jaeger@informatik.uni-kl.de>
 
-	* stdlib/atoll.c: Undefined atoll, not atol.
+	* stdlib/atoll.c: Undefine atoll, not atol.
 
 1997-02-08 09:36  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
 
diff --git a/Make-dist b/Make-dist
index 64b99b7f0c..afc7bb48a9 100644
--- a/Make-dist
+++ b/Make-dist
@@ -142,10 +142,10 @@ ifdef	   subdir
 
 foo:=$(shell echo subdir foo >&2)
 
-+tsrcs := Makefile $(+tsrcs)				\
-	  $(addsuffix .c,$(others) $(tests))		\
-	  $(wildcard $(addsuffix .input,$(tests))	\
-	  $(addsuffix .args,$(tests)))
++tsrcs := Makefile $(+tsrcs)					\
+	  $(addsuffix .c,$(others) $(tests) $(test-srcs))	\
+	  $(wildcard $(addsuffix .input,$(tests) $(test-srcs))	\
+	  $(addsuffix .args,$(tests) $(test-srcs)))
 +tardeps := $(strip $(+tsrcs))
 
 verbose = v
diff --git a/MakeTAGS b/MakeTAGS
index f9e073b43c..2fe78c123b 100644
--- a/MakeTAGS
+++ b/MakeTAGS
@@ -87,8 +87,8 @@ sources += $(foreach lib,$(extra-libs),$($(lib)-routines:=.c))
 # Files that are found in the current directory cannot occur in
 # sysdep directories, so don't bother searching them.
 sysdep-sources := $(filter-out $(wildcard $(sources)), $(sources))
-all-sources = $(wildcard $(sort $(sources) $(sources:.c=.S) $(sources:.c=.s) \
-				$(others:=.c) $(tests:=.c))) \
+all-sources = $(wildcard $(sort $(sources) $(sources:.c=.S) $(sources:.c=.s)  \
+				$(others:=.c) $(tests:=.c) $(test-srcs:=.c))) \
 	      $(foreach dir,$(all-dirs),\
 			$(wildcard \
 			   $(addprefix $(dir)/,\
diff --git a/Makefile b/Makefile
index 353281b84e..cf97c3019d 100644
--- a/Makefile
+++ b/Makefile
@@ -282,7 +282,7 @@ parent_echo-distinfo:
 
 # Run a test on the header files we use.
 tests: $(objpfx)isomac
-	$(objpfx)./isomac $(CC) '$(+sysdep-includes)' \
+	$(objpfx)./isomac '$(CC)' '$(+sysdep-includes)' \
 			  >$(common-objpfx)isomac.out
 
 $(objpfx)isomac: isomac.c
diff --git a/Makerules b/Makerules
index 26e272e3aa..10cbd972e4 100644
--- a/Makerules
+++ b/Makerules
@@ -857,9 +857,10 @@ mostlyclean: common-mostlyclean
 
 # Remove the object files.
 common-mostlyclean:
-	-rm -f $(addprefix $(objpfx),$(tests) $(others) \
-				     $(addsuffix .o,$(tests) $(others)) \
-				     $(addsuffix .out,$(tests)))
+	-rm -f $(addprefix $(objpfx),$(tests) $(test-srcs) $(others) \
+				     $(addsuffix .o,$(tests) $(test-srcs) \
+						    $(others)) \
+				     $(addsuffix .out,$(tests) $(test-srcs)))
 	-rm -f $(addprefix $(objpfx),$(extra-objs) $(install-lib))
 	-rm -f core $(common-objpfx)stub-$(subdir)
 	$(rmobjs)
diff --git a/NEWS b/NEWS
index 860f8ffa14..dfd3cd7ecc 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-GNU C Library NEWS -- history of user-visible changes.  1997-02-13
+GNU C Library NEWS -- history of user-visible changes.  1997-03-18
 
 Copyright (C) 1992, 93, 94, 95, 96, 97 Free Software Foundation, Inc.
 See the end for copying conditions.
@@ -24,6 +24,18 @@ Version 2.1
   numbers
 
 * scanf recognizes the %A format for scanning floating point numbers
+
+* the new header <inttypes.h> from ISO C 9X provides information and
+  interfaces for the available integer types
+
+* the new header <complex.h> contains definitions of the complex math
+  functions from ISO C 9X
+
+* Thorsten Kukuk provided an implementation for NIS+, securelevel 0 and 1.
+  The implementation for securelevel 2 will follow as soon as the Diffie-
+  Hellman patent expired.
+
+* Andreas Jaeger provided a test suite for the math library
 
 Version 2.0.2
 
@@ -32,6 +44,8 @@ Version 2.0.2
 * add atoll function
 
 * fix complex problems in Berkeley DB code
+
+* fix math functions
 
 Version 2.0.1
 
diff --git a/Rules b/Rules
index 32b1753f44..45417e0142 100644
--- a/Rules
+++ b/Rules
@@ -83,19 +83,19 @@ common-generated := $(common-generated) dummy.o dummy.c empty.c empty.o
 .PHONY: others tests
 others: $(addprefix $(objpfx),$(others) $(extra-objs))
 ifeq ($(cross-compiling),yes)
-tests: $(addprefix $(objpfx),$(tests))
+tests: $(addprefix $(objpfx),$(tests) $(test-srcs))
 else
 tests: $(tests:%=$(objpfx)%.out)
 endif
 
-ifneq "$(strip $(others) $(tests))" ""
-$(addprefix $(objpfx),$(others) $(tests)): %: %.o \
+ifneq "$(strip $(others) $(tests) $(test-srcs))" ""
+$(addprefix $(objpfx),$(others) $(tests) $(test-srcs)): %: %.o \
   $(sort $(filter $(common-objpfx)libc%,$(link-libc))) \
   $(addprefix $(csu-objpfx),start.o) $(+preinit) $(+postinit)
 	$(+link)
 endif
 
-ifneq "$(strip $(tests))" ""
+ifneq "$(strip $(tests) $(test-srcs))" ""
 # These are the implicit rules for making test outputs
 # from the test programs and whatever input files are present.
 $(objpfx)%.out: %.args $(objpfx)% %.input
diff --git a/csu/.cvsignore b/csu/.cvsignore
index 3fc9f4cdf1..da6e41b953 100644
--- a/csu/.cvsignore
+++ b/csu/.cvsignore
@@ -4,3 +4,4 @@
 TODO COPYING* AUTHORS copyr-* copying.*
 glibc-*
 distinfo
+specs
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
index f1c43ea174..d2122a8bdf 100644
--- a/elf/dl-reloc.c
+++ b/elf/dl-reloc.c
@@ -58,7 +58,10 @@ _dl_relocate_object (struct link_map *l, struct link_map *scope[], int lazy)
 
     /* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code.  */
 #define RESOLVE(ref, version, flags) \
-    ((version) != NULL && (version)->hash != 0				      \
+    ((*ref)->st_shndx != SHN_UNDEF &&					      \
+     ELFW(ST_BIND) ((*ref)->st_info) == STB_LOCAL	      		      \
+     ? l->l_addr :			      				      \
+     (version) != NULL && (version)->hash != 0				      \
      ? _dl_lookup_versioned_symbol (strtab + (*ref)->st_name, (ref), scope,   \
 				    l->l_name, (version), (flags))	      \
      : _dl_lookup_symbol (strtab + (*ref)->st_name, (ref), scope,	      \
diff --git a/elf/rtld.c b/elf/rtld.c
index 15df75fe8b..84ab37942b 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -106,6 +106,7 @@ _dl_start (void *arg)
 
   ELF_DYNAMIC_RELOCATE (&bootstrap_map, 0);
 
+  elf_machine_runtime_setup (&bootstrap_map, 0);
 
   /* Now life is sane; we can call functions and access global data.
      Set up to use the operating system facilities, and find out from
diff --git a/mach/devstream.c b/mach/devstream.c
index db48307856..b54dcff60d 100644
--- a/mach/devstream.c
+++ b/mach/devstream.c
@@ -147,10 +147,16 @@ output (FILE *f, int c)
     {
       kern_return_t err;
       int wrote;
+      int thiswrite;
+
       while (to_write > 0)
 	{
+	  thiswrite = to_write;
+	  if (thiswrite > IO_INBAND_MAX)
+	    thiswrite = IO_INBAND_MAX;
+
 	  if (err = device_write_inband ((device_t) f->__cookie, 0,
-					 f->__target, p, to_write, &wrote))
+					 f->__target, p, thiswrite, &wrote))
 	    {
 	      errno = err;
 	      f->__error = 1;
diff --git a/nis/Banner b/nis/Banner
index 9ef1ded2d2..f03f4ea3f5 100644
--- a/nis/Banner
+++ b/nis/Banner
@@ -1 +1 @@
-NIS(YP) NSS modules 0.9 by Thorsten Kukuk
+NIS(YP)/NIS+ NSS modules 0.10 by Thorsten Kukuk
diff --git a/nis/Makefile b/nis/Makefile
index 98ef4090a2..31fda25a45 100644
--- a/nis/Makefile
+++ b/nis/Makefile
@@ -22,15 +22,15 @@
 subdir	:= nis
 
 headers			:= $(wildcard rpcsvc/*.[hx])
-distribute		:= nss-nis.h
+distribute		:= nss-nis.h nss-nisplus.h
 
 # These are the databases available for the nis (and perhaps later nisplus)
 # service.  This must be a superset of the services in nss.
 databases		= proto service hosts network grp pwd rpc ethers \
 			  spwd netgrp alias
 
-# Specify rules for the nss_* modules.  Later we may have nisplus as well.
-services		:= nis compat
+# Specify rules for the nss_* modules.
+services		:= nis compat nisplus
 
 extra-libs		= libnsl $(services:%=libnss_%)
 # These libraries will be built in the `others' pass rather than
@@ -41,7 +41,10 @@ extra-libs-others	= $(extra-libs)
 subdir-dirs = $(services:%=nss_%)
 vpath %.c $(subdir-dirs)
 
-libnsl-routines = yp_xdr ypclnt ypupdate_xdr
+libnsl-routines = yp_xdr ypclnt ypupdate_xdr \
+                  nis_subr nis_local_names nis_free nis_file \
+                  nis_print nis_error nis_call nis_names nis_clone\
+                  nis_table nis_xdr nis_intern nis_server
 
 libnss_compat-routines	:= $(addprefix compat-,grp pwd spwd)
 libnss_compat-inhibit-o	= $(filter-out .so,$(object-suffixes))
@@ -49,6 +52,8 @@ libnss_compat-inhibit-o	= $(filter-out .so,$(object-suffixes))
 libnss_nis-routines	:= $(addprefix nis-,$(databases))
 libnss_nis-inhibit-o	= $(filter-out .so,$(object-suffixes))
 
+libnss_nisplus-routines	:= $(addprefix nisplus-,$(databases))
+libnss_nisplus-inhibit-o = $(filter-out .so,$(object-suffixes))
 
 # Sun's header files are not too clean.
 CFLAGS-compat-pwd.c = -Wno-strict-prototypes
@@ -69,6 +74,32 @@ CFLAGS-nis-spwd.c = -Wno-strict-prototypes
 CFLAGS-ypclnt.c = -Wno-strict-prototypes -Wno-write-strings -Irpcsvc
 CFLAGS-yp_xdr.c = -Wno-strict-prototypes -Irpcsvc
 CFLAGS-ypupdate_xdr.c = -Wno-strict-prototypes -Irpcsvc
+# For the NIS+ Code
+CFLAGS-nis_call.c = -DNO_DES_RPC -Wno-strict-prototypes
+CFLAGS-nis_subr.c = -Wno-strict-prototypes
+CFLAGS-nis_local_names.c = -Wno-strict-prototypes
+CFLAGS-nis_free.c = -Wno-strict-prototypes
+CFLAGS-nis_file.c = -Wno-strict-prototypes
+CFLAGS-nis_print.c = -Wno-strict-prototypes
+CFLAGS-nis_error.c = -Wno-strict-prototypes
+CFLAGS-nis_names.c = -Wno-strict-prototypes
+CFLAGS-nis_clone.c = -Wno-strict-prototypes
+CFLAGS-nis_table.c = -Wno-strict-prototypes
+CFLAGS-nis_server.c = -Wno-strict-prototypes
+CFLAGS-nis_xdr.c = -Wno-strict-prototypes
+CFLAGS-nis_intern.c = -Wno-strict-prototypes
+CFLAGS-nisplus-alias.c = -Wno-strict-prototypes
+CFLAGS-nisplus-ethers.c = -Wno-strict-prototypes
+CFLAGS-nisplus-grp.c = -Wno-strict-prototypes
+CFLAGS-nisplus-hosts.c = -Wno-strict-prototypes
+CFLAGS-nisplus-netgrp.c = -Wno-strict-prototypes
+CFLAGS-nisplus-network.c = -Wno-strict-prototypes
+CFLAGS-nisplus-proto.c = -Wno-strict-prototypes
+CFLAGS-nisplus-publickey.c = -Wno-strict-prototypes
+CFLAGS-nisplus-pwd.c = -Wno-strict-prototypes
+CFLAGS-nisplus-rpc.c = -Wno-strict-prototypes
+CFLAGS-nisplus-service.c = -Wno-strict-prototypes
+CFLAGS-nisplus-spwd.c = -Wno-strict-prototypes
 
 include ../Rules
 
@@ -77,6 +108,7 @@ $(objpfx)libnss_compat.so: $(objpfx)libnsl.so$(libnsl.so-version) \
 			   $(common-objpfx)nss/libnss_files.so
 $(objpfx)libnss_nis.so: $(objpfx)libnsl.so$(libnsl.so-version) \
 			$(common-objpfx)nss/libnss_files.so
+$(objpfx)libnss_nisplus.so: $(objpfx)libnsl.so$(libnsl.so-version)
 
 # Depend on libc.so so a DT_NEEDED is generated in the shared objects.
 # This ensures they will load libc.so for needed symbols if loaded by
diff --git a/nis/TODO b/nis/TODO
new file mode 100644
index 0000000000..9b675dfbc6
--- /dev/null
+++ b/nis/TODO
@@ -0,0 +1,40 @@
+
+ * nss_nisplus: When using parser form nss_files, rewrite parser
+ 
+ * compat could use data from nisplus, too. Implement this
+
+ * nis_server: implement nis_getservlist, nis_stats, nis_servstate
+
+ * nis_groups: implement it
+
+ * nis_ping: implement it
+
+ * __start_clock(), __stop_clock(): Test the interface and
+                                    implement it
+ 
+ * What does nis_list give back, if rpc.nisd is not running or
+   if /var/nis/NIS_START_FILE does not exist ?
+
+ * nis_table.c: nis_list(): 
+	Missing flags: FOLLOW_PATH, ALL_RESULTS
+	callback: Don't simulate it, use server callback thread
+
+ * Possible flags:
+	- FOLLOW_LINKS	(nis_list, nis_lookup)
+	- FOLLOW_PATH	(nis_list, not supported)
+	- HARD_LOOKUP	(__do_niscall, not supported)
+	- ALL_RESULTS	(nis_list, not supported, needs server callback)
+	- NO_CACHE	(__do_niscall, cache not supported yet)
+	- MASTER_ONLY	(__do_niscall, not supported)
+	- EXPAND_NAME	(nis_lookup, nis_list)
+	- RETURN_RESULT (nis_table.c)
+	- ADD_OVERWRITE	(nis_table.c)
+	- REM_MULTIPLE	(nis_table.c)
+	- MOD_SAMEOBJ 	(nis_table.c)
+	- ADD_RESERVED	(nis_table.c)
+	- REM_RESERVED	(nis_table.c)
+	- MOD_EXCLUSIVE	(nis_table.c)
+	- USE_DGRAM	(__do_niscall)
+	- NO_AUTHINFO 	(__do_niscall)
+	
+	
diff --git a/nis/nis_call.c b/nis/nis_call.c
new file mode 100644
index 0000000000..cd1b6170d4
--- /dev/null
+++ b/nis/nis_call.c
@@ -0,0 +1,220 @@
+/* Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
+
+   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 <string.h>
+#include <rpc/rpc.h>
+#include <rpc/auth.h>
+#include <rpcsvc/nis.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include "nis_intern.h"
+
+static struct timeval TIMEOUT = {25, 0};
+static int const MAXTRIES = 3;
+
+static unsigned long
+inetstr2int (const char *str)
+{
+  char buffer[strlen (str) + 3];
+  size_t buflen;
+  size_t i, j;
+
+  buflen = stpcpy (buffer, str) - buffer;
+
+  j = 0;
+  for (i = 0; i < buflen; ++i)
+    if (buffer[i] == '.')
+      {
+	++j;
+	if (j == 4)
+	  {
+	    buffer[i] = '\0';
+	    break;
+	  }
+      }
+
+  return inet_addr (buffer);
+}
+
+static CLIENT *
+__nis_dobind (const nis_server *server, u_long flags)
+{
+  struct sockaddr_in clnt_saddr;
+  int clnt_sock;
+  size_t i;
+  CLIENT *client = NULL;
+  /* XXX What is this variable for?  */
+  void *out = NULL;
+
+  for (i = 0; i < server->ep.ep_len; i++)
+    {
+      memset (&clnt_saddr, '\0', sizeof clnt_saddr);
+      clnt_saddr.sin_family = AF_INET;
+      if (strcmp (server->ep.ep_val[i].family,"loopback") == 0)
+	{
+	  if (server->ep.ep_val[i].uaddr[i] == '-')
+	    clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+	  else
+	    if (strcmp (server->ep.ep_val[i].proto,"udp") == 0)
+	      {
+		if ((flags & USE_DGRAM) == USE_DGRAM)
+		  clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+		else
+		  continue;
+	      }
+	  else
+	    if (strcmp (server->ep.ep_val[i].proto,"tcp") == 0)
+	      {
+		if ((flags & USE_DGRAM) == USE_DGRAM)
+		  continue;
+		else
+		  clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+	      }
+	}
+      else
+	if (strcmp (server->ep.ep_val[i].family,"inet") == 0)
+	  {
+	    if (server->ep.ep_val[i].uaddr[i] == '-')
+	      clnt_saddr.sin_addr.s_addr =
+		inetstr2int (server->ep.ep_val[i].uaddr);
+	    else
+	      if (strcmp (server->ep.ep_val[i].proto,"udp") == 0)
+		{
+		  if ((flags & USE_DGRAM) == USE_DGRAM)
+		    clnt_saddr.sin_addr.s_addr =
+		      inetstr2int (server->ep.ep_val[i].uaddr);
+		  else
+		    continue;
+		}
+	      else
+		if (strcmp (server->ep.ep_val[i].proto,"tcp") == 0)
+		  {
+		    if ((flags & USE_DGRAM) == USE_DGRAM)
+		      continue;
+		    else
+		      clnt_saddr.sin_addr.s_addr =
+			inetstr2int (server->ep.ep_val[i].uaddr);
+		  }
+	  }
+	else
+	  continue;
+
+      clnt_sock = RPC_ANYSOCK;
+      if ((flags & USE_DGRAM) == USE_DGRAM)
+	client = clntudp_create (&clnt_saddr, NIS_PROG, NIS_VERSION,
+				 TIMEOUT, &clnt_sock);
+      else
+	client = clnttcp_create (&clnt_saddr, NIS_PROG, NIS_VERSION,
+				 &clnt_sock, 0, 0);
+
+      if (client == NULL)
+	continue;
+#if 1
+      if (clnt_call (client, 0, (xdrproc_t) xdr_void, NULL,
+		     (xdrproc_t) xdr_void, out, TIMEOUT) != RPC_SUCCESS)
+	{
+	  clnt_destroy (client);
+	  continue;
+	}
+#endif
+      if ((flags & NO_AUTHINFO) != NO_AUTHINFO)
+	  {
+#if !defined(NO_DES_RPC)
+	    if (server->key_type == NIS_PK_DH)
+	      {
+		char netname[MAXNETNAMELEN+1];
+		char *p;
+
+		strcpy (netname, "unix.");
+		strncat (netname, server->name,MAXNETNAMELEN-5);
+		netname[MAXNETNAMELEN-5] = '\0';
+		p = strchr (netname, '.');
+		*p = '@';
+		client->cl_auth =
+		  authdes_pk_create (netname, &server->pkey, 300, NULL, NULL);
+		if (!client->cl_auth)
+		  client->cl_auth = authunix_create_default ();
+	      }
+	    else
+#endif
+	      client->cl_auth = authunix_create_default ();
+	  }
+      return client;
+    }
+
+  return NULL;
+}
+
+nis_error
+__do_niscall (const nis_server *serv, int serv_len, u_long prog,
+	      xdrproc_t xargs, caddr_t req, xdrproc_t xres, caddr_t resp,
+	      u_long flags)
+{
+  CLIENT *clnt;
+  directory_obj *dir = NULL;
+  const nis_server *server;
+  int try, result, server_len;
+
+  if (serv == NULL || serv_len == 0)
+    {
+      dir = readColdStartFile ();
+      if (dir == NULL)
+	return NIS_UNAVAIL;
+      server = dir->do_servers.do_servers_val;
+      server_len = dir->do_servers.do_servers_len;
+    }
+  else
+    {
+      server = serv;
+      server_len = serv_len;
+    }
+
+  try = 0;
+  result = NIS_NAMEUNREACHABLE;
+
+  while (try < MAXTRIES && result != RPC_SUCCESS)
+    {
+      unsigned int i;
+
+      ++try;
+      for (i = 0; i < server_len; i++)
+	{
+	  if ((clnt = __nis_dobind (&server[i], flags)) == NULL)
+	    continue;
+
+	  result = clnt_call (clnt, prog, xargs, req, xres, resp, TIMEOUT);
+
+	  if (result != RPC_SUCCESS)
+	    {
+	      /* XXX Grrr.  The cast is needed for now since Sun code does
+		 note know about `const'.  */
+	      clnt_perror (clnt, (char *) "do_niscall: clnt_call");
+	      clnt_destroy (clnt);
+	      result = NIS_RPCERROR;
+	    }
+	  else
+	    clnt_destroy (clnt);
+	}
+    }
+
+  if (dir != NULL)
+    nis_free_directory (dir);
+  return result;
+}
diff --git a/nis/nis_clone.c b/nis/nis_clone.c
new file mode 100644
index 0000000000..860abb386c
--- /dev/null
+++ b/nis/nis_clone.c
@@ -0,0 +1,551 @@
+/* Copyright (c) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
+
+   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 <string.h>
+#include <rpcsvc/nis.h>
+#include <rpcsvc/nislib.h>
+
+directory_obj *
+nis_clone_directory (const directory_obj *src, directory_obj *dest)
+{
+  directory_obj *res;
+
+  if (src == NULL)
+    return NULL;
+
+  if (dest == NULL)
+    {
+      res = calloc (1, sizeof (directory_obj));
+      if (res == NULL)
+	return NULL;
+    }
+  else
+    res = dest;
+
+  if (src->do_name)
+    res->do_name = strdup (src->do_name);
+  else
+    res->do_name = NULL;
+  res->do_type = src->do_type;
+  if (src->do_servers.do_servers_len > 0)
+    {
+      size_t i;
+
+      res->do_servers.do_servers_len = src->do_servers.do_servers_len;
+      if ((res->do_servers.do_servers_val =
+	   malloc (src->do_servers.do_servers_len * sizeof (nis_server)))
+	  == NULL)
+	return NULL;
+
+      for (i = 0; i < src->do_servers.do_servers_len; ++i)
+	{
+	  if (src->do_servers.do_servers_val[i].name != NULL)
+	    res->do_servers.do_servers_val[i].name =
+	      strdup (src->do_servers.do_servers_val[i].name);
+	  else
+	    res->do_servers.do_servers_val[i].name = NULL;
+
+	  res->do_servers.do_servers_val[i].ep.ep_len =
+	    src->do_servers.do_servers_val[i].ep.ep_len;
+	  if (res->do_servers.do_servers_val[i].ep.ep_len > 0)
+	    {
+	      size_t j;
+
+	      res->do_servers.do_servers_val[i].ep.ep_val =
+		malloc (src->do_servers.do_servers_val[i].ep.ep_len *
+			sizeof (endpoint));
+	      for (j = 0; j < res->do_servers.do_servers_val[i].ep.ep_len; ++j)
+		{
+		  if (src->do_servers.do_servers_val[i].ep.ep_val[j].uaddr)
+		    res->do_servers.do_servers_val[i].ep.ep_val[j].uaddr
+		      = strdup (src->do_servers.do_servers_val[i].ep.ep_val[j].uaddr);
+		  else
+		    res->do_servers.do_servers_val[i].ep.ep_val[j].uaddr = NULL;
+
+		  if (src->do_servers.do_servers_val[i].ep.ep_val[j].family)
+		    res->do_servers.do_servers_val[i].ep.ep_val[j].family
+		      = strdup (src->do_servers.do_servers_val[i].ep.ep_val[j].family);
+		  else
+		    res->do_servers.do_servers_val[i].ep.ep_val[j].family = NULL;
+
+		  if (src->do_servers.do_servers_val[i].ep.ep_val[j].proto)
+		    res->do_servers.do_servers_val[i].ep.ep_val[j].proto
+		      = strdup (src->do_servers.do_servers_val[i].ep.ep_val[j].proto);
+		  else
+		    res->do_servers.do_servers_val[i].ep.ep_val[j].proto = NULL;
+		}
+	    }
+	  else
+	    {
+	      res->do_servers.do_servers_val[i].ep.ep_val = NULL;
+	    }
+	  res->do_servers.do_servers_val[i].key_type =
+	    src->do_servers.do_servers_val[i].key_type;
+	  res->do_servers.do_servers_val[i].pkey.n_len =
+	    src->do_servers.do_servers_val[i].pkey.n_len;
+	  if (res->do_servers.do_servers_val[i].pkey.n_len > 0)
+	    {
+	      res->do_servers.do_servers_val[i].pkey.n_bytes =
+		malloc (src->do_servers.do_servers_val[i].pkey.n_len);
+	      if (res->do_servers.do_servers_val[i].pkey.n_bytes == NULL)
+		return NULL;
+	      memcpy (res->do_servers.do_servers_val[i].pkey.n_bytes,
+		      src->do_servers.do_servers_val[i].pkey.n_bytes,
+		      src->do_servers.do_servers_val[i].pkey.n_len);
+	    }
+	  else
+	    res->do_servers.do_servers_val[i].pkey.n_bytes = NULL;
+	}
+    }
+  else
+    {
+      res->do_servers.do_servers_len = 0;
+      res->do_servers.do_servers_val = NULL;
+    }
+  res->do_ttl  = src->do_ttl;
+  res->do_armask.do_armask_len = src->do_armask.do_armask_len;
+  if (res->do_armask.do_armask_len > 0)
+    {
+      if ((res->do_armask.do_armask_val =
+	   malloc (src->do_armask.do_armask_len * sizeof (oar_mask))) == NULL)
+	return NULL;
+      memcpy (res->do_armask.do_armask_val, src->do_armask.do_armask_val,
+	      src->do_armask.do_armask_len * sizeof (oar_mask));
+    }
+  else
+    {
+      res->do_armask.do_armask_val = NULL;
+    }
+
+  return res;
+}
+
+group_obj *
+nis_clone_group (const group_obj *src, group_obj *dest)
+{
+  size_t i;
+  group_obj *res = NULL;
+
+  if (src == NULL)
+    return NULL;
+
+  if (dest == NULL)
+    {
+      res = calloc (1, sizeof (group_obj));
+      if (res == NULL)
+	return NULL;
+    }
+  else
+    res = dest;
+
+  res->gr_flags = src->gr_flags;
+
+  res->gr_members.gr_members_len = src->gr_members.gr_members_len;
+  if (res->gr_members.gr_members_len > 0)
+    {
+      if (res->gr_members.gr_members_val == NULL)
+	{
+	  res->gr_members.gr_members_val =
+	    malloc (res->gr_members.gr_members_len * sizeof (nis_name));
+	  if (res->gr_members.gr_members_val == NULL)
+	    return NULL;
+	}
+      for (i = 0; i < res->gr_members.gr_members_len; ++i)
+	if (src->gr_members.gr_members_val[i] != NULL)
+	  res->gr_members.gr_members_val[i] =
+	    strdup (src->gr_members.gr_members_val[i]);
+	else
+	  res->gr_members.gr_members_val[i] = NULL;
+    }
+
+  return res;
+}
+
+table_obj *
+nis_clone_table (const table_obj *src, table_obj *dest)
+{
+  size_t i;
+  table_obj *res = NULL;
+
+  if (src == NULL)
+    return NULL;
+
+  if (dest == NULL)
+    {
+      res = calloc (1, sizeof (table_obj));
+      if (res == NULL)
+	return res;
+    }
+  else
+    res = dest;
+
+  if (src->ta_type != NULL)
+    {
+      if ((res->ta_type = strdup (src->ta_type)) == NULL)
+	return NULL;
+    }
+  else
+    res->ta_type = NULL;
+
+  res->ta_maxcol = src->ta_maxcol;
+  res->ta_sep = src->ta_sep;
+  res->ta_cols.ta_cols_len = src->ta_cols.ta_cols_len;
+  if (res->ta_cols.ta_cols_val == NULL)
+    {
+      res->ta_cols.ta_cols_val =
+	malloc (src->ta_cols.ta_cols_len * sizeof (table_col));
+      if (res->ta_cols.ta_cols_val == NULL)
+	return NULL;
+    }
+  for (i = 0; i < res->ta_cols.ta_cols_len; i++)
+    {
+      if (src->ta_cols.ta_cols_val[i].tc_name == NULL)
+	res->ta_cols.ta_cols_val[i].tc_name = NULL;
+      else
+	res->ta_cols.ta_cols_val[i].tc_name =
+	  strdup (src->ta_cols.ta_cols_val[i].tc_name);
+      res->ta_cols.ta_cols_val[i].tc_flags =
+	src->ta_cols.ta_cols_val[i].tc_flags;
+      res->ta_cols.ta_cols_val[i].tc_rights =
+	src->ta_cols.ta_cols_val[i].tc_rights;
+    }
+
+  if (src->ta_path != NULL)
+    {
+      if ((res->ta_path = strdup (src->ta_path)) == NULL)
+	return NULL;
+    }
+  else
+    res->ta_path = NULL;
+
+  return res;
+}
+
+entry_obj *
+nis_clone_entry (const entry_obj *src, entry_obj *dest)
+{
+  size_t i;
+  entry_obj *res = NULL;
+
+  if (src == NULL)
+    return NULL;
+
+  if (dest == NULL)
+    {
+      res = calloc (1, sizeof (entry_obj));
+      if (res == NULL)
+	return NULL;
+    }
+  else
+    res = dest;
+
+  if (src->en_type)
+    res->en_type = strdup (src->en_type);
+  else
+    res->en_type = NULL;
+
+  res->en_cols.en_cols_len = src->en_cols.en_cols_len;
+  if (res->en_cols.en_cols_val == NULL && src->en_cols.en_cols_len > 0)
+    {
+      res->en_cols.en_cols_val =
+	malloc (src->en_cols.en_cols_len * sizeof (entry_col));
+      if (res->en_cols.en_cols_val == NULL)
+	return NULL;
+    }
+  for (i = 0; i < res->en_cols.en_cols_len; ++i)
+    {
+      res->en_cols.en_cols_val[i].ec_flags =
+	src->en_cols.en_cols_val[i].ec_flags;
+      res->en_cols.en_cols_val[i].ec_value.ec_value_len =
+	src->en_cols.en_cols_val[i].ec_value.ec_value_len;
+      if (res->en_cols.en_cols_val[i].ec_value.ec_value_val == NULL &&
+	  src->en_cols.en_cols_val[i].ec_value.ec_value_len > 0)
+	res->en_cols.en_cols_val[i].ec_value.ec_value_val =
+	  malloc (src->en_cols.en_cols_val[i].ec_value.ec_value_len);
+      memcpy (res->en_cols.en_cols_val[i].ec_value.ec_value_val,
+	      src->en_cols.en_cols_val[i].ec_value.ec_value_val,
+	      res->en_cols.en_cols_val[i].ec_value.ec_value_len);
+    }
+
+  return res;
+}
+
+nis_attr *
+nis_clone_nis_attr (const nis_attr *src, nis_attr *dest)
+{
+  nis_attr *res = NULL;
+
+  if (src == NULL)
+    return NULL;
+
+  if (dest == NULL)
+    {
+      res = calloc (1, sizeof (nis_attr));
+      if (res == NULL)
+	return NULL;
+    }
+  else
+    res = dest;
+
+  if (src->zattr_ndx != NULL)
+    {
+      if ((res->zattr_ndx = strdup (src->zattr_ndx)) == NULL)
+        return NULL;
+    }
+  else
+    res->zattr_ndx = NULL;
+
+  res->zattr_val.zattr_val_len = src->zattr_val.zattr_val_len;
+  if (res->zattr_val.zattr_val_val == NULL)
+    {
+      res->zattr_val.zattr_val_val =
+	malloc (src->zattr_val.zattr_val_len);
+      if (res->zattr_val.zattr_val_val == NULL)
+	return NULL;
+    }
+  memcpy (res->zattr_val.zattr_val_val, src->zattr_val.zattr_val_val,
+	  src->zattr_val.zattr_val_len);
+
+  return res;
+}
+
+static nis_attr *
+__nis_clone_attrs (const nis_attr *src, nis_attr *dest, u_int len)
+{
+  unsigned int i;
+  nis_attr *res;
+
+  if (len == 0)
+    return dest;
+
+  if (dest == NULL)
+    {
+      res = calloc (len, sizeof (nis_attr));
+      if (res == NULL)
+	return NULL;
+    }
+  else
+    res = dest;
+
+  for (i = 0; i < len; i++)
+    nis_clone_nis_attr(&src[i], &res[i]);
+
+  return res;
+}
+
+link_obj *
+nis_clone_link (const link_obj *src, link_obj *dest)
+{
+  link_obj *res = NULL;
+
+  if (src == NULL)
+    return NULL;
+
+  if (dest == NULL)
+    {
+      res = calloc (1, sizeof (link_obj));
+      if (res == NULL)
+	return NULL;
+    }
+  else
+    res = dest;
+
+  res->li_rtype = src->li_rtype;
+
+  res->li_attrs.li_attrs_len = src->li_attrs.li_attrs_len;
+  res->li_attrs.li_attrs_val =
+    __nis_clone_attrs (src->li_attrs.li_attrs_val,
+		       res->li_attrs.li_attrs_val,
+		       src->li_attrs.li_attrs_len);
+
+  if ((res->li_name = strdup (src->li_name)) == NULL)
+    return NULL;
+
+  return res;
+}
+
+objdata *
+nis_clone_objdata (const objdata *src, objdata *dest)
+{
+  objdata *res = NULL;
+
+  if (src == NULL)
+    return NULL;
+
+  if (dest == NULL)
+    {
+      res = calloc (1, sizeof (objdata));
+      if (res == NULL)
+	return res;
+    }
+  else
+    res = dest;
+
+  res->zo_type = src->zo_type;
+
+  switch (src->zo_type)
+    {
+    case BOGUS_OBJ:
+      break;
+    case NO_OBJ:
+      break;
+    case DIRECTORY_OBJ:
+      if (nis_clone_directory (&src->objdata_u.di_data,
+			       &res->objdata_u.di_data) == NULL)
+	return NULL;
+      break;
+    case GROUP_OBJ:
+      if (nis_clone_group (&src->objdata_u.gr_data,
+			   &res->objdata_u.gr_data) == NULL)
+	return NULL;
+      break;
+    case TABLE_OBJ:
+      if (nis_clone_table (&src->objdata_u.ta_data,
+			   &res->objdata_u.ta_data) == NULL)
+	return NULL;
+      break;
+    case ENTRY_OBJ:
+      if (nis_clone_entry (&src->objdata_u.en_data,
+			   &res->objdata_u.en_data) == NULL)
+	return NULL;
+      break;
+    case LINK_OBJ:
+      if (nis_clone_link (&src->objdata_u.li_data,
+			  &res->objdata_u.li_data) == NULL)
+	return NULL;
+      break;
+    case PRIVATE_OBJ:
+      res->objdata_u.po_data.po_data_len =
+	src->objdata_u.po_data.po_data_len;
+      if (src->objdata_u.po_data.po_data_val)
+        {
+	  res->objdata_u.po_data.po_data_val =
+	    malloc (res->objdata_u.po_data.po_data_len);
+	  if (res->objdata_u.po_data.po_data_val == NULL)
+	    return NULL;
+	  memcpy (res->objdata_u.po_data.po_data_val,
+		  src->objdata_u.po_data.po_data_val,
+		  src->objdata_u.po_data.po_data_len);
+	  if (res->objdata_u.po_data.po_data_val == NULL)
+	    return NULL;
+        }
+      else
+        {
+	  res->objdata_u.po_data.po_data_val = NULL;
+	  res->objdata_u.po_data.po_data_len = 0;
+        }
+      break;
+    default:
+      return NULL;
+    }
+
+  return res;
+}
+
+nis_object *
+nis_clone_object (const nis_object *src, nis_object *dest)
+{
+  nis_object *res = NULL;
+
+  if (src == NULL)
+    return NULL;
+
+  if (dest == NULL)
+    {
+      res = calloc (1, sizeof (nis_object));
+      if (res == NULL)
+	return NULL;
+    }
+  else
+    res = dest;
+
+  res->zo_oid = src->zo_oid;
+
+  if ((res->zo_name = strdup (src->zo_name)) == NULL)
+    return NULL;
+  if ((res->zo_owner = strdup (src->zo_owner)) == NULL)
+    return NULL;
+  if ((res->zo_group = strdup (src->zo_group)) == NULL)
+    return NULL;
+  if ((res->zo_domain = strdup (src->zo_domain)) == NULL)
+    return NULL;
+
+  res->zo_access = src->zo_access;
+  res->zo_ttl = src->zo_ttl;
+
+  if (nis_clone_objdata (&src->zo_data, &res->zo_data) == NULL)
+    return NULL;
+
+  return res;
+}
+
+static nis_object *
+__nis_clone_objects (const nis_object *src, nis_object *dest, u_int len)
+{
+  unsigned int i;
+  nis_object *res;
+
+  if (len == 0)
+    return dest;
+
+  if (dest == NULL)
+    {
+      res = calloc (len, sizeof (nis_object));
+      if (res == NULL)
+	return NULL;
+    }
+  else
+    res = dest;
+
+  for (i = 0; i < len; ++i)
+    nis_clone_object(&src[i], &res[i]);
+
+  return res;
+}
+
+nis_result *
+nis_clone_result (const nis_result *src, nis_result *dest)
+{
+  nis_result *res = NULL;
+
+  if (src == NULL)
+    return NULL;
+
+  if (dest == NULL)
+    {
+      res = calloc (1, sizeof (nis_result));
+      if (res == NULL)
+	return NULL;
+    }
+  else
+    res = dest;
+
+  res->status = src->status;
+  res->objects.objects_len = src->objects.objects_len;
+  res->objects.objects_val =
+    __nis_clone_objects (src->objects.objects_val,
+			 res->objects.objects_val,
+			 src->objects.objects_len);
+  res->zticks = src->zticks;
+  res->dticks = src->dticks;
+  res->aticks = src->aticks;
+  res->cticks = src->cticks;
+
+  return res;
+}
diff --git a/nis/nis_error.c b/nis/nis_error.c
new file mode 100644
index 0000000000..760dc518ab
--- /dev/null
+++ b/nis/nis_error.c
@@ -0,0 +1,124 @@
+/* Copyright (c) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
+
+   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 <syslog.h>
+#include <rpcsvc/nis.h>
+#include <rpcsvc/nislib.h>
+
+
+static const char *nis_errlist[] =
+{
+  N_("Success"),
+  N_("Probable success"),
+  N_("Not found"),
+  N_("Probably not found"),
+  N_("Cache expired"),
+  N_("NIS+ servers unreachable"),
+  N_("Unknown object"),
+  N_("Server busy, try again"),
+  N_("Generic system error"),
+  N_("First/Next chain broken"),
+  N_("Permission denied"),
+  N_("Not owner"),
+  N_("Name not served by this server"),
+  N_("Server out of memory"),
+  N_("Object with same name exists"),
+  N_("Not master server for this domain"),
+  N_("Invalid Object for operation"),
+  N_("Malformed Name, or illegal name"),
+  N_("Unable to create callback"),
+  N_("Results Sent to callback proc"),
+  N_("Not Found, no such name"),
+  N_("Name/entry isn't unique"),
+  N_("Modification failed"),
+  N_("Database for table does not exist"),
+  N_("Entry/Table type mismatch"),
+  N_("Link Points to illegal name"),
+  N_("Partial Success"),
+  N_("Too Many Attributes"),
+  N_("Error in RPC subsystem"),
+  N_("Missing or malformed attribute"),
+  N_("Named object is not searchable"),
+  N_("Error while talking to callback proc"),
+  N_("Non NIS+ namespace encountered"),
+  N_("Illegal object type for operation"),
+  N_("Passed object is not the same object on server"),
+  N_("Modify operation failed"),
+  N_("Query illegal for named table"),
+  N_("Attempt to remove a non-empty table"),
+  N_("Error in accessing NIS+ cold start file.  Is NIS+ installed?"),
+  N_("Full resync required for directory"),
+  N_("NIS+ operation failed"),
+  N_("NIS+ service is unavailable or not installed"),
+  N_("Yes, 42 is the meaning of life"),
+  N_("Unable to authenticate NIS+ server"),
+  N_("Unable to authenticate NIS+ client"),
+  N_("No file space on server"),
+  N_("Unable to create process on server"),
+  N_("Master server busy, full dump rescheduled.")
+};
+
+const char *
+nis_sperrno (const nis_error status)
+{
+  if (status >= (sizeof (nis_errlist) / sizeof (nis_errlist[0])))
+    return "???";
+  else
+    return gettext (nis_errlist[status]);
+}
+
+void
+nis_perror (const nis_error status, const char *label)
+{
+  fprintf (stderr, "%s: %s\n", label, nis_sperrno (status));
+}
+
+void
+nis_lerror (const nis_error status, const char *label)
+{
+  syslog (LOG_ERR, "%s: %s", label, nis_sperrno (status));
+}
+
+char *
+nis_sperror_r (const nis_error status, const char *label,
+	       char *buffer, size_t buflen)
+{
+  const char *cptr;
+
+  cptr = nis_sperrno (status);
+
+  if ((strlen (cptr) + strlen (label) + 3) > buflen)
+    {
+      errno = ERANGE;
+      return NULL;
+    }
+
+    sprintf (buffer, "%s: %s", label, cptr);
+
+    return buffer;
+}
+
+char *
+nis_sperror (const nis_error status, const char *label)
+{
+  static char buffer[NIS_MAXNAMELEN +1];
+
+  return nis_sperror_r (status, label, buffer, sizeof (buffer));
+}
diff --git a/nis/nis_file.c b/nis/nis_file.c
new file mode 100644
index 0000000000..002e72ed20
--- /dev/null
+++ b/nis/nis_file.c
@@ -0,0 +1,108 @@
+/* Copyright (c) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
+
+   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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <rpcsvc/nis.h>
+#include <rpcsvc/nislib.h>
+
+directory_obj *
+readColdStartFile (void)
+{
+  XDR xdrs;
+  FILE *in;
+  directory_obj obj;
+
+  in = fopen ("/var/nis/NIS_COLD_START", "rb");
+  if (in == NULL)
+    {
+      fputs (_("Error: Could not open /var/nis/NIS_COLD_START!\n"), stdout);
+      return NULL;
+    }
+  memset (&obj, '\0', sizeof (obj));
+  xdrstdio_create (&xdrs, in, XDR_DECODE);
+  if (!xdr_directory_obj (&xdrs, &obj))
+    {
+      fputs (("Error while reading /var/nis/NIS_COLD_START!\n"), stdout);
+      return NULL;
+    }
+
+  return nis_clone_directory (&obj, NULL);
+}
+
+bool_t
+writeColdStartFile (const directory_obj *obj)
+{
+  XDR xdrs;
+  FILE *out;
+
+  out = fopen ("/var/nis/NIS_COLD_START", "wb");
+  if (out == NULL)
+    return FALSE;
+
+  xdrstdio_create (&xdrs, out, XDR_ENCODE);
+  /* XXX The following cast is bad!  Shouldn't the XDR functions take
+     pointers to const objects?  */
+  if (!xdr_directory_obj (&xdrs, (directory_obj *) obj))
+    {
+      fputs (_("Error while reading /var/nis/NIS_COLD_START!\n"), stdout);
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+nis_object *
+nis_read_obj (const char *name)
+{
+  XDR xdrs;
+  FILE *in;
+  nis_object obj;
+
+  in = fopen (name, "rb");
+  if (in == NULL)
+    return NULL;
+
+  memset (&obj, '\0', sizeof (obj));
+  xdrstdio_create (&xdrs, in, XDR_DECODE);
+  if (!xdr_nis_object (&xdrs, &obj))
+    return NULL;
+
+  return nis_clone_object (&obj, NULL);
+}
+
+bool_t
+nis_write_obj (const char *name, const nis_object *obj)
+{
+  XDR xdrs;
+  FILE *out;
+
+  out = fopen (name, "wb");
+  if (out == NULL)
+    return FALSE;
+
+  xdrstdio_create (&xdrs, out, XDR_ENCODE);
+  /* XXX The following cast is bad!  Shouldn't the XDR functions take
+     pointers to const objects?  */
+  if (!xdr_nis_object (&xdrs, (nis_object *) obj))
+    return FALSE;
+
+  return TRUE;
+}
diff --git a/nis/nis_free.c b/nis/nis_free.c
new file mode 100644
index 0000000000..35b7331372
--- /dev/null
+++ b/nis/nis_free.c
@@ -0,0 +1,334 @@
+/* Copyright (c) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
+
+   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 <rpcsvc/nis.h>
+#include <rpcsvc/nislib.h>
+
+void
+nis_free_attr (nis_attr *obj)
+{
+  if (obj == NULL)
+    return;
+
+  if (obj->zattr_ndx)
+    {
+      free (obj->zattr_ndx);
+      obj->zattr_ndx = NULL;
+    }
+
+  if (obj->zattr_val.zattr_val_val)
+    {
+      free (obj->zattr_val.zattr_val_val);
+      obj->zattr_val.zattr_val_val = NULL;
+      obj->zattr_val.zattr_val_len = 0;
+    }
+}
+
+void
+nis_free_request (ib_request *ibreq)
+{
+  unsigned int i;
+
+  for (i = 0; i < ibreq->ibr_srch.ibr_srch_len; ++i)
+    {
+      nis_free_attr (&(ibreq->ibr_srch.ibr_srch_val)[i]);
+      ibreq->ibr_srch.ibr_srch_val = NULL;
+      ibreq->ibr_srch.ibr_srch_len = 0;
+    }
+
+  if (ibreq->ibr_name)
+    {
+      free (ibreq->ibr_name);
+      ibreq->ibr_name = NULL;
+    }
+
+  if (ibreq->ibr_cookie.n_bytes)
+    {
+      free (ibreq->ibr_cookie.n_bytes);
+      ibreq->ibr_cookie.n_bytes = NULL;
+      ibreq->ibr_cookie.n_len = 0;
+    }
+}
+
+void
+nis_free_endpoints (endpoint *ep, int len)
+{
+  int i;
+
+  if (ep == NULL)
+    return;
+
+  for (i = 0; i < len; ++i)
+    {
+      if (ep[i].uaddr)
+	{
+	  free (ep[i].uaddr);
+	  ep[i].uaddr = NULL;
+	}
+      if (ep[i].family)
+	{
+	  free (ep[i].family);
+	  ep[i].family = NULL;
+	}
+      if (ep[i].proto)
+	{
+	  free (ep[i].proto);
+	  ep[i].proto = NULL;
+	}
+    }
+}
+
+void
+nis_free_servers (nis_server *obj, int len)
+{
+  int i;
+
+  if (obj == NULL)
+    return;
+
+  for (i = 0; i < len; i++)
+    {
+      if (obj[i].name)
+	{
+	  free (obj[i].name);
+	  obj[i].name = NULL;
+	}
+      if (obj[i].ep.ep_len > 0)
+	{
+	  nis_free_endpoints (obj[i].ep.ep_val, obj[i].ep.ep_len);
+	  free (obj[i].ep.ep_val);
+	  obj[i].ep.ep_val = NULL;
+	  obj[i].ep.ep_len = 0;
+	}
+      if (obj[i].pkey.n_bytes && obj[i].pkey.n_len > 0)
+	{
+	  free (obj[i].pkey.n_bytes);
+	  obj[i].pkey.n_bytes = NULL;
+	  obj[i].pkey.n_len = 0;
+	}
+    }
+}
+
+void
+nis_free_directory (directory_obj *obj)
+{
+  if (obj == NULL)
+    return;
+  if (obj->do_name)
+    {
+      free (obj->do_name);
+      obj->do_name = NULL;
+    }
+  if (obj->do_servers.do_servers_len > 0)
+    {
+      nis_free_servers (obj->do_servers.do_servers_val,
+			obj->do_servers.do_servers_len);
+      free (obj->do_servers.do_servers_val);
+      obj->do_servers.do_servers_val = NULL;
+      obj->do_servers.do_servers_len = 0;
+    }
+  if (obj->do_armask.do_armask_len > 0)
+    {
+      free (obj->do_armask.do_armask_val);
+      obj->do_armask.do_armask_val = NULL;
+      obj->do_armask.do_armask_len = 0;
+    }
+}
+
+void
+nis_free_group (group_obj *obj)
+{
+  unsigned int i;
+
+  if (obj->gr_members.gr_members_len > 0)
+    {
+      for (i = 0; i < obj->gr_members.gr_members_len; ++i)
+	if (obj->gr_members.gr_members_val[i])
+	  free (obj->gr_members.gr_members_val[i]);
+      free (obj->gr_members.gr_members_val);
+      obj->gr_members.gr_members_val = NULL;
+      obj->gr_members.gr_members_len = 0;
+    }
+}
+
+void
+nis_free_table (table_obj *obj)
+{
+  if (obj == NULL)
+    return;
+
+  if (obj->ta_type)
+    {
+      free (obj->ta_type);
+      obj->ta_type = NULL;
+    }
+
+  if (obj->ta_cols.ta_cols_val)
+    {
+      unsigned int i;
+
+      for (i = 0; i < obj->ta_cols.ta_cols_len; ++i)
+	if (obj->ta_cols.ta_cols_val[i].tc_name)
+	  free (obj->ta_cols.ta_cols_val[i].tc_name);
+      free (obj->ta_cols.ta_cols_val);
+      obj->ta_cols.ta_cols_val = NULL;
+      obj->ta_cols.ta_cols_len = 0;
+    }
+
+  if (obj->ta_path)
+    {
+      free (obj->ta_path);
+      obj->ta_path = NULL;
+    }
+}
+
+void
+nis_free_entry (entry_obj *obj)
+{
+  if (obj == NULL)
+    return;
+
+  if (obj->en_type)
+    {
+      free (obj->en_type);
+      obj->en_type = 0;
+    }
+
+  if (obj->en_cols.en_cols_val)
+    {
+      unsigned int i;
+
+      for (i = 0; i < obj->en_cols.en_cols_len; ++i)
+	if (obj->en_cols.en_cols_val[i].ec_value.ec_value_val)
+	  free (obj->en_cols.en_cols_val[i].ec_value.ec_value_val);
+      free (obj->en_cols.en_cols_val);
+      obj->en_cols.en_cols_val = NULL;
+      obj->en_cols.en_cols_len = 0;
+    }
+}
+
+void
+nis_free_link (link_obj *obj)
+{
+  if (obj == NULL)
+    return;
+
+  if (obj->li_attrs.li_attrs_val)
+    {
+      unsigned int i;
+
+      for (i = 0; i < obj->li_attrs.li_attrs_len; ++i)
+	{
+	  if (obj->li_attrs.li_attrs_val[i].zattr_ndx)
+	    free (obj->li_attrs.li_attrs_val[i].zattr_ndx);
+	  if (obj->li_attrs.li_attrs_val[i].zattr_val.zattr_val_val)
+	    free (obj->li_attrs.li_attrs_val[i].zattr_val.zattr_val_val);
+	}
+      free (obj->li_attrs.li_attrs_val);
+      obj->li_attrs.li_attrs_val = NULL;
+      obj->li_attrs.li_attrs_len = 0;
+    }
+
+  if (obj->li_name)
+    {
+      free (obj->li_name);
+      obj->li_name = NULL;
+    }
+}
+
+void
+nis_free_object (nis_object *obj)
+{
+
+  if (obj == NULL)
+    return;
+
+  if (obj->zo_name)
+    {
+      free (obj->zo_name);
+      obj->zo_name = NULL;
+    }
+  if (obj->zo_owner)
+    {
+      free (obj->zo_owner);
+      obj->zo_owner = NULL;
+    }
+  if (obj->zo_group)
+    {
+      free (obj->zo_group);
+      obj->zo_group = NULL;
+    }
+  if (obj->zo_domain)
+    {
+      free (obj->zo_domain);
+      obj->zo_domain = NULL;
+    }
+  switch (obj->zo_data.zo_type)
+    {
+    case BOGUS_OBJ:
+      break;
+    case NO_OBJ:
+      break;
+    case DIRECTORY_OBJ:
+      nis_free_directory (&obj->zo_data.objdata_u.di_data);
+      break;
+    case GROUP_OBJ:
+      nis_free_group (&obj->zo_data.objdata_u.gr_data);
+      break;
+    case TABLE_OBJ:
+      nis_free_table (&obj->zo_data.objdata_u.ta_data);
+      break;
+    case ENTRY_OBJ:
+      nis_free_entry (&obj->zo_data.objdata_u.en_data);
+      break;
+    case LINK_OBJ:
+      nis_free_link (&obj->zo_data.objdata_u.li_data);
+      break;
+    case PRIVATE_OBJ:
+      if (obj->zo_data.objdata_u.po_data.po_data_val)
+	{
+	  free (obj->zo_data.objdata_u.po_data.po_data_val);
+	  obj->zo_data.objdata_u.po_data.po_data_val = NULL;
+	}
+      break;
+    default:
+      break;
+    }
+  obj->zo_data.zo_type = NO_OBJ;
+}
+
+void
+nis_freeresult (nis_result *res)
+{
+  unsigned int i;
+
+  if (res == NULL)
+    return;
+
+  for (i = 0; i < res->objects.objects_len; i++)
+    nis_free_object (&(res->objects.objects_val)[i]);
+
+  if (res->objects.objects_val != NULL)
+    free (res->objects.objects_val);
+
+  if (res->cookie.n_bytes != NULL && res->cookie.n_len > 0)
+    free (res->cookie.n_bytes);
+
+  free (res);
+}
diff --git a/nis/nis_intern.c b/nis/nis_intern.c
new file mode 100644
index 0000000000..57019b3cfa
--- /dev/null
+++ b/nis/nis_intern.c
@@ -0,0 +1,169 @@
+/* Copyright (c) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
+
+   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 <string.h>
+#include <rpcsvc/nis.h>
+#include <rpcsvc/nislib.h>
+#include "nis_intern.h"
+
+/* Nearly the same as nis_getnames, but nis_getnames stopped
+   when 2 points left */
+nis_name *
+__nis_expandname (const nis_name name)
+{
+  nis_name *getnames = NULL;
+  char local_domain[NIS_MAXNAMELEN + 1];
+  char *path, *cp;
+  int count, pos;
+
+  strncpy (local_domain, nis_local_directory (), NIS_MAXNAMELEN);
+  local_domain[NIS_MAXNAMELEN] = '\0';
+
+  count = 1;
+  if ((getnames = malloc ((count + 1) * sizeof (char *))) == NULL)
+    return NULL;
+
+  /* Do we have a fully qualified NIS+ name ? If yes, give it back */
+  if (name[strlen (name) - 1] == '.')
+    {
+      if ((getnames[0] = strdup (name)) == NULL)
+	{
+	  free (getnames);
+	  return NULL;
+	}
+      getnames[1] = NULL;
+
+      return getnames;
+    }
+
+  /* Get the search path, where we have to search "name" */
+  path = getenv ("NIS_PATH");
+  if (path == NULL)
+    path = strdupa ("$");
+  else
+    path = strdupa (path);
+
+  pos = 0;
+
+  cp = strtok (path, ":");
+  while (cp)
+    {
+      if (strcmp (cp, "$") == 0)
+	{
+	  char *cptr = local_domain;
+	  char *tmp;
+
+	  while (*cptr != '\0')
+	    {
+	      if (pos >= count)
+		{
+		  count += 5;
+		  getnames = realloc (getnames, (count + 1) * sizeof (char *));
+		}
+	      tmp = malloc (strlen (cptr) + strlen (local_domain) +
+			    strlen (name) + 2);
+	      if (tmp == NULL)
+		return NULL;
+
+	      getnames[pos] = tmp;
+	      tmp = stpcpy (tmp, name);
+	      if (*cptr != '.')
+		*tmp++ = '.';
+	      stpcpy (tmp, cptr);
+
+	      ++pos;
+
+	      ++cptr;
+	      while ((*cptr != '\0') && (*cptr != '.'))
+		++cptr;
+
+	      if ((*cptr == '.') && (cptr[1] != '\0'))
+		++cptr;
+	    }
+	}
+      else
+	{
+	  char *tmp;
+
+	  if (cp[strlen (cp) - 1] == '$')
+	    {
+	      tmp = malloc (strlen (cp) + strlen (local_domain) +
+			    strlen (name) + 2);
+	      if (tmp == NULL)
+		return NULL;
+
+	      getnames[pos] = tmp;
+	      tmp = stpcpy (tmp, name);
+	      *tmp++ = '.';
+	      tmp = stpcpy (tmp, cp);
+	      --tmp;
+	      if (tmp[- 1] != '.')
+		*tmp++ = '.';
+	      stpcpy (tmp, local_domain);
+	    }
+	  else
+	    {
+	      tmp = malloc (strlen (cp) + strlen (name) + 2);
+	      if (tmp == NULL)
+		return NULL;
+
+	      tmp = stpcpy (tmp, name);
+	      *tmp++ = '.';
+	      stpcpy (tmp, cp);
+	    }
+
+	  if (pos > count)
+	    {
+	      count += 5;
+	      getnames = realloc (getnames, (count + 1) * sizeof (char *));
+	    }
+	  getnames[pos] = tmp;
+	  pos++;
+	}
+      cp = strtok (NULL, ":");
+    }
+
+  getnames[pos] = NULL;
+
+  return getnames;
+}
+
+fd_result *
+__nis_finddirectoy (nis_name dir_name)
+{
+  fd_args args;
+  nis_error status;
+  fd_result *res;
+
+  args.dir_name = dir_name;
+  args.requester = nis_local_principal ();
+
+  res = calloc (1, sizeof (fd_result));
+  if (res == NULL)
+    return NULL;
+
+  if ((status = __do_niscall (NULL, 0, NIS_FINDDIRECTORY,
+			      (xdrproc_t) xdr_fd_args,
+			      (caddr_t) & args,
+			      (xdrproc_t) xdr_fd_result,
+			      (caddr_t) res, 0)) != RPC_SUCCESS)
+    res->status = status;
+
+  return res;
+}
diff --git a/nis/nis_intern.h b/nis/nis_intern.h
new file mode 100644
index 0000000000..b5fb605506
--- /dev/null
+++ b/nis/nis_intern.h
@@ -0,0 +1,39 @@
+/* Copyright (c) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
+
+   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 __NIS_INTERN_H
+
+#define __NIS_INTERN_H
+#include <features.h>
+
+__BEGIN_DECLS
+
+extern nis_error __do_niscall (__const nis_server *server, int server_len,
+			       u_long prog, xdrproc_t xargs, caddr_t req,
+			       xdrproc_t xres, caddr_t resp, u_long flags);
+#if !defined(NO_DES_RPC)
+extern AUTH *authdes_pk_create (char *, netobj *, u_int,
+				struct sockaddr *, des_block *);
+#endif
+
+extern nis_name *__nis_expandname (__const nis_name);
+
+__END_DECLS
+
+#endif
diff --git a/nis/nis_local_names.c b/nis/nis_local_names.c
new file mode 100644
index 0000000000..50120a6f73
--- /dev/null
+++ b/nis/nis_local_names.c
@@ -0,0 +1,184 @@
+/* Copyright (c) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <rpcsvc/nis.h>
+#include <rpcsvc/nislib.h>
+
+nis_name
+nis_local_group (void)
+{
+  static char __nisgroup[NIS_MAXNAMELEN + 1];
+
+  if (__nisgroup[0] == '\0')
+    {
+      char *cptr;
+
+      if ((cptr = getenv ("NIS_GROUP")) == NULL)
+	return __nisgroup;
+
+      if (strlen (cptr) >= NIS_MAXNAMELEN)
+	return __nisgroup;
+
+      strcpy (__nisgroup, cptr);
+
+      if (__nisgroup[strlen (__nisgroup) - 1] != '.')
+	{
+	  cptr = nis_local_directory ();
+	  if (strlen (__nisgroup) + strlen (cptr) + 1 < NIS_MAXNAMELEN)
+	    {
+	      strcat (__nisgroup, ".");
+	      strcat (__nisgroup, cptr);
+	    }
+	  else
+	    {
+	      __nisgroup[0] = '\0';
+	      return __nisgroup;
+	    }
+	}
+    }
+
+  return __nisgroup;
+}
+
+
+nis_name
+nis_local_directory (void)
+{
+  static char __nisdomainname[NIS_MAXNAMELEN + 1];
+  int len;
+
+  if (__nisdomainname[0] == '\0')
+    {
+      if (getdomainname (__nisdomainname, NIS_MAXNAMELEN) < 0)
+	strcpy (__nisdomainname, "\0");
+      else
+	{
+	  len = strlen (__nisdomainname);
+
+	  /* Missing trailing dot? */
+	  if (__nisdomainname[len - 1] != '.')
+	    {
+	      __nisdomainname[len] = '.';
+	      __nisdomainname[len + 1] = '\0';
+	    }
+	}
+    }
+
+  return __nisdomainname;
+}
+
+nis_name
+nis_local_principal (void)
+{
+  static char __principal[NIS_MAXNAMELEN + 1];
+
+  if (__principal[0] == '\0')
+    {
+      char buf[NIS_MAXNAMELEN + 1];
+      nis_result *res;
+      uid_t uid = geteuid ();
+
+      if (uid != 0)
+	{
+	  snprintf (buf, NIS_MAXNAMELEN - 1,
+		    "[auth_name=%d,auth_type=LOCAL],cred.org_dir.%s",
+		    uid, nis_local_directory ());
+
+	  if (buf[strlen (buf) - 1] != '.')
+	    strcat (buf, ".");
+
+	  res = nis_list (buf, USE_DGRAM + NO_AUTHINFO + FOLLOW_LINKS +
+			  FOLLOW_PATH, NULL, NULL);
+
+	  if (res == NULL)
+	    {
+	      strcpy (__principal, "nobody");
+	      return __principal;
+	    }
+
+	  if (res->status == NIS_SUCCESS)
+	    {
+	      if (res->objects.objects_len > 1)
+		{
+		  /* More than one principal with same uid?  something
+		     wrong with cred table. Should be unique Warn user
+		     and continue.  */
+		  printf (_("\
+LOCAL entry for UID %d in directory %s not unique\n"),
+			  uid, nis_local_directory ());
+		}
+	      strcpy (__principal, ENTRY_VAL (res->objects.objects_val, 0));
+	      nis_freeresult (res);
+	      return __principal;
+	    }
+	  else
+	    {
+	      nis_freeresult (res);
+	      strcpy (__principal, "nobody");
+	      return __principal;
+	    }
+	}
+      else
+	{
+	  strcpy (__principal, nis_local_host ());
+	  return __principal;
+	}
+
+      /* Should be never reached */
+      strcpy (__principal, "nobody");
+      return __principal;
+    }
+  return __principal;
+}
+
+nis_name
+nis_local_host (void)
+{
+  static char __nishostname[NIS_MAXNAMELEN + 1];
+  int len;
+
+  if (__nishostname[0] == '\0')
+    {
+      char *cp = __nishostname;
+
+      if (gethostname (__nishostname, NIS_MAXNAMELEN) < 0)
+	cp = stpcpy (cp, "\0");
+
+      len = cp - __nishostname;
+
+      /* Hostname already fully qualified? */
+      if (__nishostname[len - 1] == '.')
+	return __nishostname;
+
+      if (strlen (__nishostname + strlen (nis_local_directory ()) + 1) >
+	  NIS_MAXNAMELEN)
+	{
+	  __nishostname[0] = '\0';
+	  return __nishostname;
+	}
+
+      *cp++ = '.';
+      stpcpy (cp, nis_local_directory ());
+    }
+
+  return __nishostname;
+}
diff --git a/nis/nis_names.c b/nis/nis_names.c
new file mode 100644
index 0000000000..92f8040b3d
--- /dev/null
+++ b/nis/nis_names.c
@@ -0,0 +1,238 @@
+/* Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@uni-paderborn.de>, 1997.
+
+   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 <string.h>
+#include <rpc/rpc.h>
+#include <rpcsvc/nis.h>
+#include <rpcsvc/nislib.h>
+
+#include "nis_intern.h"
+
+nis_result *
+nis_lookup (const nis_name name, const u_long flags)
+{
+  nis_result *res;
+  struct ns_request req;
+  nis_name *names;
+  nis_error status;
+  int is_link = 1;	 /* We should go at least once in the while loop */
+  int count_links = 0;	 /* We will follow only 16 links in the deep */
+  int i;
+
+  res = calloc (1, sizeof (nis_result));
+
+  if (flags & EXPAND_NAME)
+    {
+      names = __nis_expandname (name);
+      if (names == NULL)
+	{
+	  res->status = NIS_NAMEUNREACHABLE;
+	  return res;
+	}
+
+      i = 0;
+      while (names[i] != NULL && (i == 0 || res->status > 1))
+	{
+	  req.ns_name = names[i];
+
+	  while (is_link)
+	    {
+	      req.ns_object.ns_object_len = 0;
+	      req.ns_object.ns_object_val = NULL;
+	      memset (res, '\0', sizeof (nis_result));
+
+	      if ((status = __do_niscall (NULL, 0, NIS_LOOKUP,
+					  (xdrproc_t) xdr_ns_request,
+					  (caddr_t) & req,
+					  (xdrproc_t) xdr_nis_result,
+				      (caddr_t) res, flags)) != RPC_SUCCESS)
+		{
+		  res->status = status;
+		  nis_freenames (names);
+		  return res;
+		}
+
+	      if ((res->status == NIS_SUCCESS || res->status == NIS_S_SUCCESS)
+		  && (res->objects.objects_len > 0 &&
+		      res->objects.objects_val->zo_data.zo_type == LINK_OBJ))
+		is_link = 1;
+	      else
+		is_link = 0;
+
+	      if (is_link)
+		{
+		  if ((flags & FOLLOW_LINKS) == FOLLOW_LINKS)
+		    {
+		      if (count_links == 16)
+			{
+			  res->status = NIS_LINKNAMEERROR;
+			  return res;
+			}
+		      else
+			++count_links;
+
+		      req.ns_name = res->objects.objects_val->LI_data.li_name;
+		    }
+		  else
+		    {
+		      res->status = NIS_NOTSEARCHABLE;
+		      return res;
+		    }
+		}
+	    }
+
+	  ++i;
+	  if (res->status == NIS_NOT_ME)
+	    res->status = NIS_NOSUCHNAME;
+	}
+
+      nis_freenames (names);
+    }
+  else
+    {
+      req.ns_name = name;
+
+      while (is_link)
+	{
+	  req.ns_object.ns_object_len = 0;
+	  req.ns_object.ns_object_val = NULL;
+	  memset (res, '\0', sizeof (nis_result));
+
+	  if ((status = __do_niscall (NULL, 0, NIS_LOOKUP,
+				      (xdrproc_t) xdr_ns_request,
+				      (caddr_t) & req,
+				      (xdrproc_t) xdr_nis_result,
+				      (caddr_t) res, flags)) != RPC_SUCCESS)
+	    {
+	      res->status = status;
+	      return res;
+	    }
+
+	  if ((res->status == NIS_SUCCESS || res->status == NIS_S_SUCCESS) &&
+	      (res->objects.objects_len > 0 &&
+	       res->objects.objects_val->zo_data.zo_type == LINK_OBJ))
+	    is_link = 1;
+	  else
+	    is_link = 0;
+
+	  if (is_link)
+	    {
+	      if ((flags & FOLLOW_LINKS) == FOLLOW_LINKS)
+		{
+		  if (count_links == 16)
+		    {
+		      res->status = NIS_LINKNAMEERROR;
+		      return res;
+		    }
+		  else
+		    ++count_links;
+
+		  req.ns_name = res->objects.objects_val->LI_data.li_name;
+		}
+	      else
+		{
+		  res->status = NIS_NOTSEARCHABLE;
+		  return res;
+		}
+	    }
+	}
+    }
+
+  return res;
+}
+
+nis_result *
+nis_add (const nis_name name, const nis_object *obj)
+{
+  nis_result *res;
+  nis_error status;
+  struct ns_request req;
+
+  res = calloc (1, sizeof (nis_result));
+
+  req.ns_name = name;
+
+  req.ns_object.ns_object_len = 1;
+  req.ns_object.ns_object_val = nis_clone_object (obj, NULL);
+
+  if ((status = __do_niscall (NULL, 0, NIS_ADD, (xdrproc_t) xdr_ns_request,
+			      (caddr_t) & req, (xdrproc_t) xdr_nis_result,
+			      (caddr_t) res, 0)) != RPC_SUCCESS)
+    res->status = status;
+
+  nis_destroy_object (req.ns_object.ns_object_val);
+
+  return res;
+}
+
+nis_result *
+nis_remove (const nis_name name, const nis_object *obj)
+{
+  nis_result *res;
+  nis_error status;
+  struct ns_request req;
+
+  res = calloc (1, sizeof (nis_result));
+
+  req.ns_name = name;
+
+  if (obj != NULL)
+    {
+      req.ns_object.ns_object_len = 1;
+      req.ns_object.ns_object_val = nis_clone_object (obj, NULL);
+    }
+  else
+    {
+      req.ns_object.ns_object_len = 0;
+      req.ns_object.ns_object_val = NULL;
+    }
+
+  if ((status = __do_niscall (NULL, 0, NIS_REMOVE, (xdrproc_t) xdr_ns_request,
+			      (caddr_t) & req, (xdrproc_t) xdr_nis_result,
+			      (caddr_t) res, 0)) != RPC_SUCCESS)
+    res->status = status;
+
+  nis_destroy_object (req.ns_object.ns_object_val);
+
+  return res;
+}
+
+nis_result *
+nis_modify (const nis_name name, const nis_object *obj)
+{
+  nis_result *res;
+  nis_error status;
+  struct ns_request req;
+
+  res = calloc (1, sizeof (nis_result));
+
+  req.ns_name = name;
+
+  req.ns_object.ns_object_len = 1;
+  req.ns_object.ns_object_val = nis_clone_object (obj, NULL);
+
+  if ((status = __do_niscall (NULL, 0, NIS_REMOVE, (xdrproc_t) xdr_ns_request,
+			      (caddr_t) & req, (xdrproc_t) xdr_nis_result,
+			      (caddr_t) res, 0)) != RPC_SUCCESS)
+    res->status = status;
+
+  nis_destroy_object (req.ns_object.ns_object_val);
+
+  return res;
+}
diff --git a/nis/nis_print.c b/nis/nis_print.c
new file mode 100644
index 0000000000..e6eb264ae7
--- /dev/null
+++ b/nis/nis_print.c
@@ -0,0 +1,308 @@
+/* Copyright (c) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <time.h>
+#include <rpcsvc/nis.h>
+#include <rpcsvc/nislib.h>
+
+static const char *
+nis_nstype2str (const nstype type)
+{
+  switch (type)
+    {
+    case NIS:
+      return N_("NIS");
+    case SUNYP:
+      return N_("SUNYP");
+    case IVY:
+      return N_("IVY");
+    case DNS:
+      return N_("DNS");
+    case X500:
+      return N_("X500");
+    case DNANS:
+      return N_("DNANS");
+    case XCHS:
+      return N_("XCHS");
+    case CDS:
+      return N_("CDS");
+    default:
+      return N_("UNKNOWN");
+    }
+}
+
+static char *
+nis_ttl2str (const u_long ttl)
+{
+  static char buf[64];
+  unsigned long int time, s, m, h;
+
+  time = ttl;
+
+  h = time / (60 * 60);
+  time %= (60 * 60);
+  m = time / 60;
+  time %= 60;
+  s = time;
+  snprintf (buf, 63, "%lu:%02lu:%02lu", h, m, s);
+
+  return buf;
+}
+
+static char *
+nis_flags2str (const u_long flags)
+{
+  static char buf[1024];
+
+  snprintf (buf, 1023, "%lu", flags);
+
+  return buf;
+}
+
+void
+nis_print_rights (const u_long access)
+{
+  char result[17];
+  u_long acc;
+  int i;
+
+  acc = access;			/* Parameter is const ! */
+  result[i = 16] = '\0';
+  while (i > 0)
+    {
+      i -= 4;
+      result[i + 0] = (acc & NIS_READ_ACC) ? 'r' : '-';
+      result[i + 1] = (acc & NIS_MODIFY_ACC) ? 'm' : '-';
+      result[i + 2] = (acc & NIS_CREATE_ACC) ? 'c' : '-';
+      result[i + 3] = (acc & NIS_DESTROY_ACC) ? 'd' : '-';
+
+      acc >>= 8;
+    }
+  printf ("%s", result);
+}
+
+void
+nis_print_directory (const directory_obj *dir)
+{
+  nis_server *sptr;
+  unsigned int i;
+
+  printf (_("Name : '%s'\n"), dir->do_name);
+  printf (_("Type : %s\n"), gettext (nis_nstype2str (dir->do_type)));
+  sptr = dir->do_servers.do_servers_val;
+  for (i = 0; i < dir->do_servers.do_servers_len; i++)
+    {
+      if (i == 0)
+	fputs (_("Master Server :\n"), stdout);
+      else
+	fputs (_("Replicate :\n"), stdout);
+      printf (_("\tName       : %s\n"), sptr->name);
+      fputs (_("\tPublic Key : "), stdout);
+      switch (sptr->key_type)
+	{
+	case NIS_PK_NONE:
+	  fputs (_("None.\n"), stdout);
+	  break;
+	case NIS_PK_DH:
+	  fputs (_("DH.\n"), stdout);
+	  break;
+	case NIS_PK_RSA:
+	  fputs (_("RSA.\n"), stdout);
+	  break;
+	case NIS_PK_KERB:
+	  fputs (_("Kerberous.\n"), stdout);
+	  break;
+	default:
+	  fputs (_("Unknown.\n"), stdout);
+	  break;
+	}
+
+      if (sptr->ep.ep_len != 0)
+	{
+	  unsigned int j;
+
+	  endpoint *ptr;
+	  ptr = sptr->ep.ep_val;
+	  printf (_("\tUniversal addresses (%u)\n"), sptr->ep.ep_len);
+	  for (j = 0; j < sptr->ep.ep_len; j++)
+	    {
+	      printf ("\t[%d] - ", j + 1);
+	      if (ptr->proto != NULL && strlen (ptr->proto) > 0)
+		printf ("%s, ", ptr->proto);
+	      else
+		printf ("-, ");
+	      if (ptr->family != NULL && strlen (ptr->family) > 0)
+		printf ("%s, ", ptr->family);
+	      else
+		printf ("-, ");
+	      if (ptr->uaddr != NULL && strlen (ptr->uaddr) > 0)
+		printf ("%s\n", ptr->uaddr);
+	      else
+		printf ("-\n");
+	      ptr++;
+	    }
+	}
+      sptr++;
+    }
+
+  printf (_("Time to live : %s\n"), nis_ttl2str (dir->do_ttl));
+  if (dir->do_armask.do_armask_len != 0)
+    {
+      oar_mask *ptr;
+
+      ptr = dir->do_armask.do_armask_val;
+      for (i = 0; i < dir->do_armask.do_armask_len; i++)
+	{
+	  fputs (_("Default Access rights: "), stdout);
+	  nis_print_rights (ptr->oa_rights);
+	  printf (_("\nDirect Type : %d\n"), ptr->oa_otype);
+	  ptr++;
+	}
+    }
+}
+
+void
+nis_print_group (const group_obj *obj)
+{
+  unsigned int i;
+
+  fputs (_("Group Flags :"), stdout);
+  if (obj->gr_flags)
+    printf ("0x%08lX", obj->gr_flags);
+  fputs (_("\nGroup Members :\n"), stdout);
+
+  for (i = 0; i < obj->gr_members.gr_members_len; i++)
+    printf ("\t%s\n", obj->gr_members.gr_members_val[i]);
+}
+
+void
+nis_print_table (const table_obj *obj)
+{
+  unsigned int i;
+
+  printf (_("Table Type          : %s\n"), obj->ta_type);
+  printf (_("Number of Columns   : %d\n"), obj->ta_maxcol);
+  printf (_("Character Separator : %c\n"), obj->ta_sep);
+  printf (_("Search Path         : %s\n"), obj->ta_path);
+  fputs (_("Columns             :\n"), stdout);
+  for (i = 0; i < obj->ta_cols.ta_cols_len; i++)
+    {
+      printf (_("\t[%d]\tName          : %s\n"), i,
+	      obj->ta_cols.ta_cols_val[i].tc_name);
+      printf (_("\t\tAttributes    : %s\n"),
+	      nis_flags2str (obj->ta_cols.ta_cols_val[i].tc_flags));
+      fputs (_("\t\tAccess Rights : "), stdout);
+      nis_print_rights (obj->ta_cols.ta_cols_val[i].tc_rights);
+      fputc ('\n', stdout);
+    }
+}
+
+void
+nis_print_link (const link_obj *obj)
+{
+  printf (_("Type : %d\n"), obj->li_rtype);
+  printf (_("Name : %s\n"), obj->li_name);
+  printf (_("Attributes : %d\n"), obj->li_attrs.li_attrs_len);
+}
+
+void
+nis_print_entry (const entry_obj *obj)
+{
+  unsigned int i;
+
+  printf (_("\tEntry data of type %s\n"), obj->en_type);
+  for (i = 0; i < obj->en_cols.en_cols_len; i++)
+    {
+      printf (_("\t[%u] - [%u bytes] "), i,
+	      obj->en_cols.en_cols_val[i].ec_value.ec_value_len);
+      if ((obj->en_cols.en_cols_val[i].ec_flags & EN_CRYPT) == EN_CRYPT)
+	fputs (_("Encrypted data\n"), stdout);
+      else if ((obj->en_cols.en_cols_val[i].ec_flags & EN_BINARY) == EN_BINARY)
+	fputs (_("Binary data\n"), stdout);
+      else
+	printf ("%s\n", obj->en_cols.en_cols_val[i].ec_value.ec_value_val);
+    }
+}
+
+void
+nis_print_object (const nis_object * obj)
+{
+  printf (_("Object Name   : %s\n"), obj->zo_name);
+  printf (_("Directory     : %s\n"), obj->zo_domain);
+  printf (_("Owner         : %s\n"), obj->zo_owner);
+  printf (_("Group         : %s\n"), obj->zo_group);
+  fputs (_("Access Rights : "), stdout);
+  nis_print_rights (obj->zo_access);
+  printf (_("\nTime to Live  : %lu (seconds)\n"), obj->zo_ttl);
+  printf (_("Creation Time : %s"), ctime (&obj->zo_oid.ctime));
+  printf (_("Mod. Time     : %s"), ctime (&obj->zo_oid.mtime));
+  fputs (_("Object Type   : "), stdout);
+  switch (obj->zo_data.zo_type)
+    {
+    case BOGUS_OBJ:
+      fputs (_("BOGUS OBJECT\n"), stdout);
+      break;
+    case NO_OBJ:
+      fputs (_("NO OBJECT\n"), stdout);
+      break;
+    case DIRECTORY_OBJ:
+      fputs (_("DIRECTORY\n"), stdout);
+      nis_print_directory (&obj->zo_data.objdata_u.di_data);
+      break;
+    case GROUP_OBJ:
+      fputs (_("GROUP\n"), stdout);
+      nis_print_group (&obj->zo_data.objdata_u.gr_data);
+      break;
+    case TABLE_OBJ:
+      fputs (_("TABLE\n"), stdout);
+      nis_print_table (&obj->zo_data.objdata_u.ta_data);
+      break;
+    case ENTRY_OBJ:
+      fputs (_("ENTRY\n"), stdout);
+      nis_print_entry (&obj->zo_data.objdata_u.en_data);
+      break;
+    case LINK_OBJ:
+      fputs (_("LINK\n"), stdout);
+      nis_print_link (&obj->zo_data.objdata_u.li_data);
+      break;
+    case PRIVATE_OBJ:
+      fputs (_("PRIVATE\n"), stdout);
+      printf (_("    Data Length = %u\n"),
+	      obj->zo_data.objdata_u.po_data.po_data_len);
+      break;
+    default:
+      fputs (_("(Unknown object)\n"), stdout);
+      break;
+    }
+}
+
+void
+nis_print_result (const nis_result *res)
+{
+  unsigned int i;
+
+  printf (_("Status            : %s\n"), nis_sperrno (res->status));
+  printf (_("Number of objects : %u\n"), res->objects.objects_len);
+
+  for (i = 0; i < res->objects.objects_len; i++)
+    {
+      printf (_("Object #%d:\n"), i);
+      nis_print_object (&res->objects.objects_val[i]);
+    }
+}
diff --git a/nis/nis_server.c b/nis/nis_server.c
new file mode 100644
index 0000000000..48d2144c78
--- /dev/null
+++ b/nis/nis_server.c
@@ -0,0 +1,143 @@
+/* Copyright (c) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
+
+   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 <rpcsvc/nis.h>
+#include <rpcsvc/nislib.h>
+#include "nis_intern.h"
+
+nis_error
+nis_mkdir (const nis_name dir, const nis_server *server)
+{
+  nis_error res;
+
+  if (server == NULL)
+    {
+      int result;
+      if ((result = __do_niscall (NULL, 0, NIS_MKDIR, (xdrproc_t) xdr_nis_name,
+				  (caddr_t) dir, (xdrproc_t) xdr_nis_error,
+				  (caddr_t) & res, 0)) != RPC_SUCCESS)
+	{
+	  fprintf (stderr, _("__do_niscall: Error #%d\n"), result);
+	  return NIS_RPCERROR;
+	}
+    }
+  else
+    {
+      int result;
+      if ((result = __do_niscall (server, 1, NIS_MKDIR,
+				  (xdrproc_t) xdr_nis_name,
+				  (caddr_t) dir, (xdrproc_t) xdr_nis_error,
+				  (caddr_t) & res, 0)) != RPC_SUCCESS)
+	{
+	  fprintf (stderr, _("__do_niscall: Error #%d\n"), result);
+	  return NIS_RPCERROR;
+	}
+    }
+
+  return res;
+}
+
+nis_error
+nis_rmdir (const nis_name dir, const nis_server *server)
+{
+  nis_error res;
+
+  if (server == NULL)
+    {
+      int result;
+      if ((result = __do_niscall (NULL, 0, NIS_RMDIR, (xdrproc_t) xdr_nis_name,
+				  (caddr_t) dir, (xdrproc_t) xdr_nis_error,
+				  (caddr_t) & res, 0)) != RPC_SUCCESS)
+	{
+	  fprintf (stderr, _("__do_niscall: Error #%d\n"), result);
+	  return NIS_RPCERROR;
+	}
+    }
+  else
+    {
+      int result;
+      if ((result = __do_niscall (server, 1, NIS_RMDIR,
+				  (xdrproc_t) xdr_nis_name,
+				  (caddr_t) dir, (xdrproc_t) xdr_nis_error,
+				  (caddr_t) & res, 0)) != RPC_SUCCESS)
+	{
+	  fprintf (stderr, _("__do_niscall: Error #%d\n"), result);
+	  return NIS_RPCERROR;
+	}
+    }
+
+  return res;
+}
+
+nis_error
+nis_servstate (const nis_server *serv, const nis_tag *tags,
+	       const int numtags, nis_tag **result)
+{
+  *result = NULL;
+  return NIS_FAIL;
+}
+stub_warning (nis_servstate)
+
+nis_error
+nis_stats (const nis_server *serv, const nis_tag *tags,
+	   const int numtags, nis_tag **result)
+{
+  result = malloc (sizeof (nis_tag *));
+  if (result != NULL)
+    result[0] = NULL;
+  return NIS_FAIL;
+}
+stub_warning (nis_stats);
+
+void
+nis_freetags (nis_tag *tags, const int numtags)
+{
+  int i;
+
+  for (i = 0; i < numtags; ++i)
+    free (tags->tag_val);
+  free (tags);
+}
+
+nis_server **
+nis_getservlist (const nis_name dir)
+{
+  nis_server **serv;
+
+  serv = malloc (sizeof (nis_server *));
+  if (serv != NULL)
+    serv[0] = NULL;
+
+  return serv;
+}
+stub_warning (nis_getservlist);
+
+void
+nis_freeservlist (nis_server **serv)
+{
+  int i;
+
+  if (serv == NULL)
+    return;
+
+  i = 0;
+  while (serv[i] != NULL)
+    nis_free_servers (serv[i], 1);
+  free (serv);
+}
diff --git a/nis/nis_subr.c b/nis/nis_subr.c
new file mode 100644
index 0000000000..74eb0b5c77
--- /dev/null
+++ b/nis/nis_subr.c
@@ -0,0 +1,310 @@
+/* Copyright (c) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <errno.h>
+#include <string.h>
+#include <rpcsvc/nis.h>
+#include <rpcsvc/nislib.h>
+
+nis_name
+nis_leaf_of (const nis_name name)
+{
+  static char result[NIS_MAXNAMELEN + 1];
+
+  return nis_leaf_of_r (name, result, NIS_MAXNAMELEN);
+}
+
+nis_name
+nis_leaf_of_r (const nis_name name, char *buffer, size_t buflen)
+{
+  size_t i = 0;
+
+  buffer[0] = '\0';
+
+  while (name[i] != '.' && name[i] != '\0')
+    i++;
+
+  if (i > buflen - 1)
+    {
+      errno = ERANGE;
+      return NULL;
+    }
+
+  if (i > 1)
+    strncpy (buffer, name, i - 1);
+
+  return buffer;
+}
+
+nis_name
+nis_name_of (const nis_name name)
+{
+  static char result[NIS_MAXNAMELEN + 1];
+
+  return nis_name_of_r (name, result, NIS_MAXNAMELEN);
+}
+
+nis_name
+nis_name_of_r (const nis_name name, char *buffer, size_t buflen)
+{
+  char *local_domain;
+  int diff;
+
+  local_domain = nis_local_directory ();
+
+  diff = strlen (name) - strlen (local_domain);
+  if (diff <= 0)
+    return NULL;
+
+  if (strcmp (&name[diff], local_domain) != 0)
+    return NULL;
+
+  if ((size_t) diff >= buflen)
+    {
+      errno = ERANGE;
+      return NULL;
+    }
+  memcpy (buffer, name, diff - 1);
+  buffer[diff - 1] = '\0';
+
+  if (diff - 1 == 0)
+    return NULL;
+
+  return buffer;
+}
+
+nis_name
+nis_domain_of (const nis_name name)
+{
+  static char result[NIS_MAXNAMELEN + 1];
+
+  return nis_domain_of_r (name, result, NIS_MAXNAMELEN);
+}
+
+nis_name
+nis_domain_of_r (const nis_name name, char *buffer, size_t buflen)
+{
+  char *cptr;
+  size_t cptr_len;
+
+  cptr = strchr (name, '.');	/* XXX What happens if the NIS name
+				   does not contain a `.'?  */
+  ++cptr;
+  cptr_len = strlen (cptr);
+
+  if (cptr_len == 0)
+    strcpy (buffer, ".");
+  else if (cptr_len >= buflen)
+    {
+      errno = ERANGE;
+      return NULL;
+    }
+  else
+    memcpy (buffer, cptr, cptr_len + 1);
+
+  return buffer;
+}
+
+static int
+count_dots (const nis_name str)
+{
+  int count = 0;
+  size_t i;
+
+  for (i = 0; i < strlen (str); ++i)
+    if (str[i] == '.')
+      ++count;
+
+  return count;
+}
+
+nis_name *
+nis_getnames (const nis_name name)
+{
+  nis_name *getnames = NULL;
+  char local_domain[NIS_MAXNAMELEN + 1];
+  char *path, *cp;
+  int count, pos;
+
+
+  strncpy (local_domain, nis_local_directory (), NIS_MAXNAMELEN);
+  local_domain[NIS_MAXNAMELEN] = '\0';
+
+  count = 1;
+  if ((getnames = malloc ((count + 1) * sizeof (char *))) == NULL)
+      return NULL;
+
+  /* Do we have a fully qualified NIS+ name ? If yes, give it back */
+  if (name[strlen (name) - 1] == '.')
+    {
+      if ((getnames[0] = strdup (name)) == NULL)
+	{
+	  free (getnames);
+	  return NULL;
+	}
+      getnames[1] = NULL;
+
+      return getnames;
+    }
+
+  /* Get the search path, where we have to search "name" */
+  path = getenv ("NIS_PATH");
+  if (path == NULL)
+    path = strdupa ("$");
+  else
+    path = strdupa (path);
+
+  pos = 0;
+
+  cp = strtok (path, ":");
+  while (cp)
+    {
+      if (strcmp (cp, "$") == 0)
+	{
+	  char *cptr = local_domain;
+	  char *tmp;
+
+	  while (count_dots (cptr) >= 2)
+	    {
+	      if (pos >= count)
+		{
+		  count += 5;
+		  getnames = realloc (getnames, (count + 1) * sizeof (char *));
+		}
+	      tmp = malloc (strlen (cptr) + strlen (local_domain) +
+			    strlen (name) + 2);
+	      if (tmp == NULL)
+		return NULL;
+
+	      getnames[pos] = tmp;
+	      tmp = stpcpy (tmp, name);
+	      *tmp++ = '.';
+	      stpcpy (tmp, cptr);
+
+	      ++pos;
+
+	      while (*cptr != '.')
+		++cptr;
+	      ++cptr;
+	    }
+	}
+      else
+	{
+	  char *tmp;
+
+	  if (cp[strlen (cp) - 1] == '$')
+	    {
+	      tmp = malloc (strlen (cp) + strlen (local_domain) +
+			    strlen (name) + 2);
+	      if (tmp == NULL)
+		return NULL;
+
+	      tmp = stpcpy (tmp, name);
+	      *tmp++ = '.';
+	      tmp = stpcpy (tmp, cp);
+	      --tmp;
+	      if (tmp[-1] != '.')
+		*tmp++ = '.';
+	      stpcpy (tmp, local_domain);
+	    }
+	  else
+	    {
+	      tmp = malloc (strlen (cp) + strlen (name) + 2);
+	      if (tmp == NULL)
+		return NULL;
+
+	      tmp = stpcpy (tmp, name);
+	      *tmp++ = '.';
+	      stpcpy (tmp, cp);
+	    }
+
+	  if (pos > count)
+	    {
+	      count += 5;
+	      getnames = realloc (getnames, (count + 1) * sizeof (char *));
+	      if (getnames == NULL)
+		return NULL;
+	    }
+	  getnames[pos] = tmp;
+	  ++pos;
+	}
+      cp = strtok (NULL, ":");
+    }
+
+  getnames[pos] = NULL;
+
+  return getnames;
+}
+
+void
+nis_freenames (nis_name *names)
+{
+  int i = 0;
+
+  while (names[i] != NULL)
+    {
+      free (names[i]);
+      ++i;
+    }
+
+  free (names);
+}
+
+name_pos
+nis_dir_cmp (const nis_name n1, const nis_name n2)
+{
+  int len1, len2;
+
+  len1 = strlen (n1);
+  len2 = strlen (n2);
+
+  if (len1 == len2)
+    {
+      if (strcmp (n1, n2) == 0)
+	return SAME_NAME;
+      else
+	return NOT_SEQUENTIAL;
+    }
+
+  if (len1 < len2)
+    {
+      if (n2[len2 - len1 - 1] != '.')
+	return NOT_SEQUENTIAL;
+      else if (strcmp (&n2[len2 - len1], n1) == 0)
+	return HIGHER_NAME;
+      else
+	return NOT_SEQUENTIAL;
+    }
+  else
+    {
+      if (n1[len1 - len2 - 1] != '.')
+	return NOT_SEQUENTIAL;
+      else if (strcmp (&n1[len1 - len2], n2) == 0)
+	return LOWER_NAME;
+      else
+	return NOT_SEQUENTIAL;
+
+    }
+}
+
+void
+nis_destroy_object (nis_object *obj)
+{
+  nis_free_object (obj);
+}
diff --git a/nis/nis_table.c b/nis/nis_table.c
new file mode 100644
index 0000000000..a3061e1d94
--- /dev/null
+++ b/nis/nis_table.c
@@ -0,0 +1,417 @@
+/* Copyright (c) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
+
+   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 <string.h>
+#include <rpcsvc/nis.h>
+#include <rpcsvc/nislib.h>
+#include "nis_intern.h"
+
+static void
+splitname (const nis_name name, nis_name *ibr_name, int *srch_len,
+	   nis_attr **srch_val)
+{
+  char *cptr, *key, *val, *next;
+  int size;
+
+  if (name == NULL)
+    return;
+
+  cptr = strdup (name);
+  if (srch_len)
+    *srch_len = 0;
+  if (srch_val)
+    *srch_val = NULL;
+  size = 0;
+
+  /* Not of "[key=value,key=value,...],foo.." format? */
+  if (cptr[0] != '[')
+    {
+      *ibr_name = cptr;
+      return;
+    }
+
+  *ibr_name = strchr (cptr, ']');
+  if (*ibr_name == NULL || (*ibr_name)[1] != ',')
+    {
+      free (cptr);
+      *ibr_name = NULL;
+      return;
+    }
+
+  *ibr_name[0] = '\0';
+  *ibr_name += 2;
+  *ibr_name = strdup (*ibr_name);
+
+  if (srch_len == NULL || srch_val == NULL)
+    {
+      free (cptr);
+      return;
+    }
+
+  key = (cptr) + 1;
+  do
+    {
+      next = strchr (key, ',');
+      if (next)
+	{
+	  next[0] = '\0';
+	  ++next;
+	}
+
+      val = strchr (key, '=');
+      if (!val)
+	{
+	  free (cptr);
+	  *srch_val = malloc (sizeof (char *));
+	  if (*srch_val == NULL)
+	    {
+	      free (cptr);
+	      free (*ibr_name);
+	      *ibr_name = NULL;
+	      return;
+	    }
+	  (*srch_val)[*srch_len].zattr_val.zattr_val_len = 0;
+	  (*srch_val)[*srch_len].zattr_val.zattr_val_val = NULL;
+	  return;
+	}
+
+      val[0] = '\0';
+      ++val;
+
+      if ((*srch_len) + 1 >= size)
+	{
+	  size += 10;
+	  if (size == 10)
+	    *srch_val = malloc (size * sizeof (char *));
+	  else
+	    *srch_val = realloc (val, size * sizeof (char *));
+	  if (*srch_val == NULL)
+	    {
+	      free (cptr);
+	      free (*ibr_name);
+	      *ibr_name = NULL;
+	      return;
+	    }
+	}
+
+      (*srch_val)[*srch_len].zattr_ndx = strdup (key);
+      if (((*srch_val)[*srch_len].zattr_ndx) == NULL)
+	{
+	  free (cptr);
+	  free (*ibr_name);
+	  *ibr_name = NULL;
+	  return;
+	}
+      (*srch_val)[*srch_len].zattr_val.zattr_val_len = strlen (val) + 1;
+      (*srch_val)[*srch_len].zattr_val.zattr_val_val = strdup (val);
+      if ((*srch_val)[*srch_len].zattr_val.zattr_val_val == NULL)
+	{
+	  free (cptr);
+	  free (*ibr_name);
+	  *ibr_name = NULL;
+	  return;
+	}
+      ++(*srch_len);
+
+      key = next;
+
+    }
+  while (next);
+
+  free (cptr);
+}
+
+static struct ib_request *
+__create_ib_request (const nis_name name, struct ib_request *ibreq,
+		     u_long flags)
+{
+  splitname (name, &ibreq->ibr_name, &ibreq->ibr_srch.ibr_srch_len,
+	     &ibreq->ibr_srch.ibr_srch_val);
+  if (ibreq->ibr_name == NULL)
+    return NULL;
+  if ((flags & EXPAND_NAME) == EXPAND_NAME)
+    {
+      nis_name *names;
+
+      names = __nis_expandname (ibreq->ibr_name);
+      free (ibreq->ibr_name);
+      ibreq->ibr_name = NULL;
+      if (names == NULL)
+	return NULL;
+      ibreq->ibr_name = strdup (names[0]);
+      nis_freenames (names);
+    }
+
+  ibreq->ibr_flags = (flags & (RETURN_RESULT | ADD_OVERWRITE | REM_MULTIPLE |
+			       MOD_SAMEOBJ | ADD_RESERVED | REM_RESERVED |
+			       MOD_EXCLUSIVE));
+  ibreq->ibr_obj.ibr_obj_len = 0;
+  ibreq->ibr_obj.ibr_obj_val = NULL;
+  ibreq->ibr_cbhost.ibr_cbhost_len = 0;
+  ibreq->ibr_cbhost.ibr_cbhost_val = NULL;
+  ibreq->ibr_bufsize = 0;
+  ibreq->ibr_cookie.n_len = 0;
+  ibreq->ibr_cookie.n_bytes = NULL;
+
+  return ibreq;
+}
+
+nis_result *
+nis_list (const nis_name name, const u_long flags,
+	  int (*callback) (const nis_name name,
+			   const nis_object *object,
+			   const void *userdata),
+	  const void *userdata)
+{
+  nis_result *res = NULL;
+  struct ib_request ibreq;
+  int result;
+  int count_links = 0;		/* We will only follow 16 links! */
+  int is_link = 1;		/* We should go at least once in the while loop */
+
+  res = calloc (1, sizeof (nis_result));
+
+  if (__create_ib_request (name, &ibreq, flags) == NULL)
+    {
+      res->status = NIS_BADNAME;
+      return res;
+    }
+
+  while (is_link)
+    {
+      memset (res, '\0', sizeof (nis_result));
+
+      if ((result = __do_niscall (NULL, 0, NIS_IBLIST,
+				  (xdrproc_t) xdr_ib_request,
+			      (caddr_t) & ibreq, (xdrproc_t) xdr_nis_result,
+				  (caddr_t) res, flags)) != RPC_SUCCESS)
+	{
+	  res->status = result;
+	  nis_free_request (&ibreq);
+	  return res;
+	}
+
+      nis_free_request (&ibreq);
+
+      if ((res->status == NIS_SUCCESS || res->status == NIS_S_SUCCESS) &&
+	  (res->objects.objects_len > 0 &&
+	   res->objects.objects_val->zo_data.zo_type == LINK_OBJ))
+	is_link = 1;
+      else
+	is_link = 0;
+
+      if (is_link)
+	{
+	  if ((flags & FOLLOW_LINKS) == FOLLOW_LINKS)
+	    {
+	      if (count_links == 16)
+		{
+		  res->status = NIS_LINKNAMEERROR;
+		  return res;
+		}
+	      else
+		++count_links;
+
+	      if (__create_ib_request (res->objects.objects_val->LI_data.li_name,
+				       &ibreq, flags) == NULL)
+		{
+		  res->status = NIS_BADNAME;
+		  return res;
+		}
+	    }
+	  else
+	    {
+	      res->status = NIS_NOTSEARCHABLE;
+	      return res;
+	    }
+	}
+    }
+
+  if (callback != NULL &&
+      (res->status == NIS_SUCCESS || res->status == NIS_S_SUCCESS))
+    {
+      unsigned int i;
+
+      for (i = 0; i < res->objects.objects_len; ++i)
+	if ((*callback) (name, &(res->objects.objects_val)[i], userdata) != 0)
+	  break;
+    }
+
+  return res;
+}
+
+nis_result *
+nis_add_entry (const nis_name name, const nis_object *obj,
+	       const u_long flags)
+{
+  nis_result *res;
+  struct ib_request ibreq;
+  nis_error status;
+
+  res = calloc (1, sizeof (nis_result));
+
+  if (__create_ib_request (name, &ibreq, flags) == NULL)
+    {
+      res->status = NIS_BADNAME;
+      return res;
+    }
+
+  ibreq.ibr_flags = flags;
+  ibreq.ibr_obj.ibr_obj_val = nis_clone_object (obj, NULL);
+  ibreq.ibr_obj.ibr_obj_len = 1;
+
+  if ((status = __do_niscall (NULL, 0, NIS_IBADD,
+			      (xdrproc_t) xdr_ib_request,
+			      (caddr_t) & ibreq,
+			      (xdrproc_t) xdr_nis_result,
+			      (caddr_t) res, 0)) != RPC_SUCCESS)
+    res->status = status;
+
+  nis_free_request (&ibreq);
+
+  return res;
+}
+
+nis_result *
+nis_modify_entry (const nis_name name, const nis_object *obj,
+		  const u_long flags)
+{
+  nis_result *res;
+  struct ib_request ibreq;
+  nis_error status;
+
+  res = calloc (1, sizeof (nis_result));
+
+  if (__create_ib_request (name, &ibreq, flags) == NULL)
+    {
+      res->status = NIS_BADNAME;
+      return res;
+    }
+
+  ibreq.ibr_flags = flags;
+  ibreq.ibr_obj.ibr_obj_val = nis_clone_object (obj, NULL);
+  ibreq.ibr_obj.ibr_obj_len = 1;
+
+  if ((status = __do_niscall (NULL, 0, NIS_IBMODIFY,
+			      (xdrproc_t) xdr_ib_request,
+			      (caddr_t) & ibreq, (xdrproc_t) xdr_nis_result,
+			      (caddr_t) res, 0)) != RPC_SUCCESS)
+    res->status = status;
+
+  nis_free_request (&ibreq);
+
+  return res;
+}
+
+nis_result *
+nis_remove_entry (const nis_name name, const nis_object *obj,
+		  const u_long flags)
+{
+  nis_result *res;
+  struct ib_request ibreq;
+  nis_error status;
+
+  res = calloc (1, sizeof (nis_result));
+
+  if (__create_ib_request (name, &ibreq, flags) == NULL)
+    {
+      res->status = NIS_BADNAME;
+      return res;
+    }
+
+  ibreq.ibr_flags = flags;
+  if (obj != NULL)
+    {
+      ibreq.ibr_obj.ibr_obj_val = nis_clone_object (obj, NULL);
+      ibreq.ibr_obj.ibr_obj_len = 1;
+    }
+
+  if ((status = __do_niscall (NULL, 0, NIS_IBREMOVE,
+			      (xdrproc_t) xdr_ib_request,
+			      (caddr_t) & ibreq, (xdrproc_t) xdr_nis_result,
+			      (caddr_t) res, 0)) != RPC_SUCCESS)
+    res->status = status;
+
+  nis_free_request (&ibreq);
+
+  return res;
+}
+
+nis_result *
+nis_first_entry (const nis_name name)
+{
+  nis_result *res;
+  struct ib_request ibreq;
+  nis_error status;
+
+  res = calloc (1, sizeof (nis_result));
+
+  if (__create_ib_request (name, &ibreq, 0) == NULL)
+    {
+      res->status = NIS_BADNAME;
+      return res;
+    }
+
+  if ((status = __do_niscall (NULL, 0, NIS_IBFIRST, (xdrproc_t) xdr_ib_request,
+			      (caddr_t) & ibreq, (xdrproc_t) xdr_nis_result,
+			      (caddr_t) res, 0)) != RPC_SUCCESS)
+    res->status = status;
+
+  nis_free_request (&ibreq);
+
+  return res;
+}
+
+nis_result *
+nis_next_entry (const nis_name name, const netobj *cookie)
+{
+  nis_result *res;
+  struct ib_request ibreq;
+  nis_error status;
+
+  res = calloc (1, sizeof (nis_result));
+
+  if (__create_ib_request (name, &ibreq, 0) == NULL)
+    {
+      res->status = NIS_BADNAME;
+      return res;
+    }
+
+  if (cookie != NULL)
+    {
+      ibreq.ibr_cookie.n_bytes = malloc (cookie->n_len);
+      if (ibreq.ibr_cookie.n_bytes == NULL)
+	{
+	  res->status = NIS_NOMEMORY;
+	  free (res);
+	  return NULL;
+	}
+      memcpy (ibreq.ibr_cookie.n_bytes, cookie->n_bytes, cookie->n_len);
+      ibreq.ibr_cookie.n_len = cookie->n_len;
+    }
+
+  if ((status = __do_niscall (NULL, 0, NIS_IBNEXT, (xdrproc_t) xdr_ib_request,
+			      (caddr_t) & ibreq, (xdrproc_t) xdr_nis_result,
+			      (caddr_t) res, 0)) != RPC_SUCCESS)
+    res->status = status;
+
+  nis_free_request (&ibreq);
+
+  return res;
+}
diff --git a/nis/nis_xdr.c b/nis/nis_xdr.c
new file mode 100644
index 0000000000..82df04e449
--- /dev/null
+++ b/nis/nis_xdr.c
@@ -0,0 +1,572 @@
+/* Copyright (c) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
+
+   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 <rpcsvc/nis.h>
+
+bool_t
+xdr_nis_attr (XDR *xdrs, nis_attr *objp)
+{
+  if (!xdr_string (xdrs, &objp->zattr_ndx, ~0))
+    return FALSE;
+  if (!xdr_bytes (xdrs, (char **) &objp->zattr_val.zattr_val_val,
+		  (u_int *) & objp->zattr_val.zattr_val_len, ~0))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_nis_name (XDR *xdrs, nis_name *objp)
+{
+  if (!xdr_string (xdrs, objp, ~0))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_zotypes (XDR *xdrs, zotypes *objp)
+{
+  if (!xdr_enum (xdrs, (enum_t *) objp))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_nstype (XDR *xdrs, nstype *objp)
+{
+  if (!xdr_enum (xdrs, (enum_t *) objp))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_oar_mask (XDR *xdrs, oar_mask *objp)
+{
+  if (!xdr_u_long (xdrs, &objp->oa_rights))
+    return FALSE;
+  if (!xdr_zotypes (xdrs, &objp->oa_otype))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_endpoint (XDR *xdrs, endpoint *objp)
+{
+  if (!xdr_string (xdrs, &objp->uaddr, ~0))
+    return FALSE;
+  if (!xdr_string (xdrs, &objp->family, ~0))
+    return FALSE;
+  if (!xdr_string (xdrs, &objp->proto, ~0))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_nis_server (XDR *xdrs, nis_server *objp)
+{
+  if (!xdr_nis_name (xdrs, &objp->name))
+    return FALSE;
+  if (!xdr_array (xdrs, (char **) &objp->ep.ep_val, (u_int *) &objp->ep.ep_len,
+		  ~0, sizeof (endpoint), (xdrproc_t) xdr_endpoint))
+    return FALSE;
+  if (!xdr_u_long (xdrs, &objp->key_type))
+    return FALSE;
+  if (!xdr_netobj (xdrs, &objp->pkey))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_directory_obj (XDR *xdrs, directory_obj *objp)
+{
+  if (!xdr_nis_name (xdrs, &objp->do_name))
+    return FALSE;
+  if (!xdr_nstype (xdrs, &objp->do_type))
+    return FALSE;
+  if (!xdr_array (xdrs, (char **) &objp->do_servers.do_servers_val,
+		  (u_int *) & objp->do_servers.do_servers_len, ~0,
+		  sizeof (nis_server), (xdrproc_t) xdr_nis_server))
+    return FALSE;
+
+  if (!xdr_u_long (xdrs, &objp->do_ttl))
+    return FALSE;
+  if (!xdr_array (xdrs, (char **) &objp->do_armask.do_armask_val,
+		  (u_int *) & objp->do_armask.do_armask_len, ~0,
+		  sizeof (oar_mask), (xdrproc_t) xdr_oar_mask))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_entry_col (XDR *xdrs, entry_col *objp)
+{
+  if (!xdr_u_long (xdrs, &objp->ec_flags))
+    return FALSE;
+  if (!xdr_bytes (xdrs, (char **) &objp->ec_value.ec_value_val,
+		  (u_int *) &objp->ec_value.ec_value_len, ~0))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_entry_obj (XDR *xdrs, entry_obj *objp)
+{
+  if (!xdr_string (xdrs, &objp->en_type, ~0))
+    return FALSE;
+  if (!xdr_array (xdrs, (char **) &objp->en_cols.en_cols_val,
+		  (u_int *) &objp->en_cols.en_cols_len, ~0,
+		  sizeof (entry_col), (xdrproc_t) xdr_entry_col))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_group_obj (XDR *xdrs, group_obj *objp)
+{
+  if (!xdr_u_long (xdrs, &objp->gr_flags))
+    return FALSE;
+  if (!xdr_array (xdrs, (char **) &objp->gr_members.gr_members_val,
+		  (u_int *) &objp->gr_members.gr_members_len, ~0,
+		  sizeof (nis_name), (xdrproc_t) xdr_nis_name))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_link_obj (XDR *xdrs, link_obj *objp)
+{
+  if (!xdr_zotypes (xdrs, &objp->li_rtype))
+    return FALSE;
+  if (!xdr_array (xdrs, (char **) &objp->li_attrs.li_attrs_val,
+		  (u_int *) &objp->li_attrs.li_attrs_len, ~0,
+		  sizeof (nis_attr), (xdrproc_t) xdr_nis_attr))
+    return FALSE;
+  if (!xdr_nis_name (xdrs, &objp->li_name))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_table_col (XDR *xdrs, table_col *objp)
+{
+  if (!xdr_string (xdrs, &objp->tc_name, 64))
+    return FALSE;
+  if (!xdr_u_long (xdrs, &objp->tc_flags))
+    return FALSE;
+  if (!xdr_u_long (xdrs, &objp->tc_rights))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_table_obj (XDR *xdrs, table_obj *objp)
+{
+  if (!xdr_string (xdrs, &objp->ta_type, 64))
+    return FALSE;
+  if (!xdr_int (xdrs, &objp->ta_maxcol))
+    return FALSE;
+  if (!xdr_u_char (xdrs, &objp->ta_sep))
+    return FALSE;
+  if (!xdr_array (xdrs, (char **) &objp->ta_cols.ta_cols_val,
+		  (u_int *) &objp->ta_cols.ta_cols_len, ~0,
+		  sizeof (table_col), (xdrproc_t) xdr_table_col))
+    return FALSE;
+  if (!xdr_string (xdrs, &objp->ta_path, ~0))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_objdata (XDR *xdrs, objdata *objp)
+{
+  if (!xdr_zotypes (xdrs, &objp->zo_type))
+    return FALSE;
+  switch (objp->zo_type)
+    {
+    case DIRECTORY_OBJ:
+      if (!xdr_directory_obj (xdrs, &objp->objdata_u.di_data))
+	return FALSE;
+      break;
+    case GROUP_OBJ:
+      if (!xdr_group_obj (xdrs, &objp->objdata_u.gr_data))
+	return FALSE;
+      break;
+    case TABLE_OBJ:
+      if (!xdr_table_obj (xdrs, &objp->objdata_u.ta_data))
+	return FALSE;
+      break;
+    case ENTRY_OBJ:
+      if (!xdr_entry_obj (xdrs, &objp->objdata_u.en_data))
+	return FALSE;
+      break;
+    case LINK_OBJ:
+      if (!xdr_link_obj (xdrs, &objp->objdata_u.li_data))
+	return FALSE;
+      break;
+    case PRIVATE_OBJ:
+      if (!xdr_bytes (xdrs, (char **) &objp->objdata_u.po_data.po_data_val,
+		      (u_int *) & objp->objdata_u.po_data.po_data_len, ~0))
+	return FALSE;
+      break;
+    case NO_OBJ:
+      break;
+    case BOGUS_OBJ:
+      break;
+    default:
+      break;
+    }
+  return TRUE;
+}
+
+bool_t
+xdr_nis_oid (XDR *xdrs, nis_oid *objp)
+{
+  if (!xdr_u_long (xdrs, &objp->ctime))
+    return FALSE;
+  if (!xdr_u_long (xdrs, &objp->mtime))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_nis_object (XDR *xdrs, nis_object *objp)
+{
+  if (!xdr_nis_oid (xdrs, &objp->zo_oid))
+    return FALSE;
+  if (!xdr_nis_name (xdrs, &objp->zo_name))
+    return FALSE;
+  if (!xdr_nis_name (xdrs, &objp->zo_owner))
+    return FALSE;
+  if (!xdr_nis_name (xdrs, &objp->zo_group))
+    return FALSE;
+  if (!xdr_nis_name (xdrs, &objp->zo_domain))
+    return FALSE;
+  if (!xdr_u_long (xdrs, &objp->zo_access))
+    return FALSE;
+  if (!xdr_u_long (xdrs, &objp->zo_ttl))
+    return FALSE;
+  if (!xdr_objdata (xdrs, &objp->zo_data))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_nis_error (XDR *xdrs, nis_error *objp)
+{
+  if (!xdr_enum (xdrs, (enum_t *) objp))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_nis_result (XDR *xdrs, nis_result *objp)
+{
+  register long *buf;
+
+  if (xdrs->x_op == XDR_ENCODE)
+    {
+      if (!xdr_nis_error (xdrs, &objp->status))
+	return FALSE;
+      if (!xdr_array (xdrs, (char **) &objp->objects.objects_val,
+		      (u_int *) &objp->objects.objects_len, ~0,
+		      sizeof (nis_object), (xdrproc_t) xdr_nis_object))
+	return FALSE;
+      if (!xdr_netobj (xdrs, &objp->cookie))
+	return FALSE;
+      buf = XDR_INLINE (xdrs, 4 * BYTES_PER_XDR_UNIT);
+      if (buf == NULL)
+	{
+	  if (!xdr_u_long (xdrs, &objp->zticks))
+	    {
+	      return FALSE;
+	    }
+	  if (!xdr_u_long (xdrs, &objp->dticks))
+	    {
+	      return FALSE;
+	    }
+	  if (!xdr_u_long (xdrs, &objp->aticks))
+	    {
+	      return FALSE;
+	    }
+	  if (!xdr_u_long (xdrs, &objp->cticks))
+	    {
+	      return FALSE;
+	    }
+
+	}
+      else
+	{
+	  IXDR_PUT_U_LONG (buf, objp->zticks);
+	  IXDR_PUT_U_LONG (buf, objp->dticks);
+	  IXDR_PUT_U_LONG (buf, objp->aticks);
+	  IXDR_PUT_U_LONG (buf, objp->cticks);
+	}
+
+      return TRUE;
+    }
+  else if (xdrs->x_op == XDR_DECODE)
+    {
+      if (!xdr_nis_error (xdrs, &objp->status))
+	{
+	  return FALSE;
+	}
+      if (!xdr_array (xdrs, (char **) &objp->objects.objects_val,
+		      (u_int *) &objp->objects.objects_len, ~0,
+		      sizeof (nis_object), (xdrproc_t) xdr_nis_object))
+	{
+	  return FALSE;
+	}
+      if (!xdr_netobj (xdrs, &objp->cookie))
+	{
+	  return FALSE;
+	}
+      buf = XDR_INLINE (xdrs, 4 * BYTES_PER_XDR_UNIT);
+      if (buf == NULL)
+	{
+	  if (!xdr_u_long (xdrs, &objp->zticks))
+	    {
+	      return FALSE;
+	    }
+	  if (!xdr_u_long (xdrs, &objp->dticks))
+	    {
+	      return FALSE;
+	    }
+	  if (!xdr_u_long (xdrs, &objp->aticks))
+	    {
+	      return FALSE;
+	    }
+	  if (!xdr_u_long (xdrs, &objp->cticks))
+	    {
+	      return FALSE;
+	    }
+
+	}
+      else
+	{
+	  objp->zticks = IXDR_GET_U_LONG (buf);
+	  objp->dticks = IXDR_GET_U_LONG (buf);
+	  objp->aticks = IXDR_GET_U_LONG (buf);
+	  objp->cticks = IXDR_GET_U_LONG (buf);
+	}
+      return TRUE;
+    }
+
+  if (!xdr_nis_error (xdrs, &objp->status))
+    {
+      return FALSE;
+    }
+  if (!xdr_array (xdrs, (char **) &objp->objects.objects_val,
+		  (u_int *) &objp->objects.objects_len, ~0,
+		  sizeof (nis_object), (xdrproc_t) xdr_nis_object))
+    {
+      return FALSE;
+    }
+  if (!xdr_netobj (xdrs, &objp->cookie))
+    {
+      return FALSE;
+    }
+  if (!xdr_u_long (xdrs, &objp->zticks))
+    {
+      return FALSE;
+    }
+  if (!xdr_u_long (xdrs, &objp->dticks))
+    {
+      return FALSE;
+    }
+  if (!xdr_u_long (xdrs, &objp->aticks))
+    {
+      return FALSE;
+    }
+  if (!xdr_u_long (xdrs, &objp->cticks))
+    {
+      return FALSE;
+    }
+  return TRUE;
+}
+
+bool_t
+xdr_ns_request (XDR *xdrs, ns_request *objp)
+{
+  if (!xdr_nis_name (xdrs, &objp->ns_name))
+    return FALSE;
+  if (!xdr_array (xdrs, (char **) &objp->ns_object.ns_object_val,
+		  (u_int *) &objp->ns_object.ns_object_len, 1,
+		  sizeof (nis_object), (xdrproc_t) xdr_nis_object))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_ib_request (XDR *xdrs, ib_request *objp)
+{
+  if (!xdr_nis_name (xdrs, &objp->ibr_name))
+    return FALSE;
+  if (!xdr_array (xdrs, (char **) &objp->ibr_srch.ibr_srch_val,
+		  (u_int *) &objp->ibr_srch.ibr_srch_len, ~0,
+		  sizeof (nis_attr), (xdrproc_t) xdr_nis_attr))
+    return FALSE;
+  if (!xdr_u_long (xdrs, &objp->ibr_flags))
+    return FALSE;
+  if (!xdr_array (xdrs, (char **) &objp->ibr_obj.ibr_obj_val,
+		  (u_int *) &objp->ibr_obj.ibr_obj_len, 1,
+		  sizeof (nis_object), (xdrproc_t) xdr_nis_object))
+    return FALSE;
+  if (!xdr_array (xdrs, (char **) &objp->ibr_cbhost.ibr_cbhost_val,
+		  (u_int *) &objp->ibr_cbhost.ibr_cbhost_len, 1,
+		  sizeof (nis_server), (xdrproc_t) xdr_nis_server))
+    return FALSE;
+  if (!xdr_u_long (xdrs, &objp->ibr_bufsize))
+    return FALSE;
+  if (!xdr_netobj (xdrs, &objp->ibr_cookie))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_ping_args (XDR *xdrs, ping_args *objp)
+{
+  if (!xdr_nis_name (xdrs, &objp->dir))
+    return FALSE;
+  if (!xdr_u_long (xdrs, &objp->stamp))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_log_entry_t (XDR *xdrs, log_entry_t *objp)
+{
+  if (!xdr_enum (xdrs, (enum_t *) objp))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_log_entry (XDR *xdrs, log_entry *objp)
+{
+  if (!xdr_u_long (xdrs, &objp->le_time))
+    return FALSE;
+  if (!xdr_log_entry_t (xdrs, &objp->le_type))
+    return FALSE;
+  if (!xdr_nis_name (xdrs, &objp->le_princp))
+    return FALSE;
+  if (!xdr_nis_name (xdrs, &objp->le_name))
+    return FALSE;
+  if (!xdr_array (xdrs, (char **) &objp->le_attrs.le_attrs_val,
+		  (u_int *) &objp->le_attrs.le_attrs_len, ~0,
+		  sizeof (nis_attr), (xdrproc_t) xdr_nis_attr))
+    return FALSE;
+  if (!xdr_nis_object (xdrs, &objp->le_object))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_log_result (XDR *xdrs, log_result *objp)
+{
+  if (!xdr_nis_error (xdrs, &objp->lr_status))
+    {
+      return FALSE;
+    }
+  if (!xdr_netobj (xdrs, &objp->lr_cookie))
+    {
+      return FALSE;
+    }
+  if (!xdr_array (xdrs, (char **) &objp->lr_entries.lr_entries_val,
+		  (u_int *) &objp->lr_entries.lr_entries_len, ~0,
+		  sizeof (log_entry), (xdrproc_t) xdr_log_entry))
+    {
+      return FALSE;
+    }
+  return TRUE;
+}
+
+bool_t
+xdr_cp_result (XDR *xdrs, cp_result *objp)
+{
+  if (!xdr_nis_error (xdrs, &objp->cp_status))
+    return FALSE;
+  if (!xdr_u_long (xdrs, &objp->cp_zticks))
+    return FALSE;
+  if (!xdr_u_long (xdrs, &objp->cp_dticks))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_nis_tag (XDR *xdrs, nis_tag *objp)
+{
+  if (!xdr_u_long (xdrs, &objp->tag_type))
+    {
+      return FALSE;
+    }
+  if (!xdr_string (xdrs, &objp->tag_val, 1024))
+    {
+      return FALSE;
+    }
+  return TRUE;
+}
+
+bool_t
+xdr_nis_taglist (XDR *xdrs, nis_taglist *objp)
+{
+  if (!xdr_array (xdrs, (char **) &objp->tags.tags_val,
+		  (u_int *) &objp->tags.tags_len, ~0, sizeof (nis_tag),
+		  (xdrproc_t) xdr_nis_tag))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_dump_args (XDR *xdrs, dump_args *objp)
+{
+  if (!xdr_nis_name (xdrs, &objp->da_dir))
+    return FALSE;
+  if (!xdr_u_long (xdrs, &objp->da_time))
+    return FALSE;
+  if (!xdr_array (xdrs, (char **) &objp->da_cbhost.da_cbhost_val,
+		  (u_int *) &objp->da_cbhost.da_cbhost_len, 1,
+		  sizeof (nis_server), (xdrproc_t) xdr_nis_server))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_fd_args (XDR *xdrs, fd_args *objp)
+{
+  if (!xdr_nis_name (xdrs, &objp->dir_name))
+    return FALSE;
+  if (!xdr_nis_name (xdrs, &objp->requester))
+    return FALSE;
+  return TRUE;
+}
+
+bool_t
+xdr_fd_result (XDR *xdrs, fd_result *objp)
+{
+  if (!xdr_nis_error (xdrs, &objp->status))
+    return FALSE;
+  if (!xdr_nis_name (xdrs, &objp->source))
+    return FALSE;
+  if (!xdr_bytes (xdrs, (char **) &objp->dir_data.dir_data_val,
+		  (u_int *) &objp->dir_data.dir_data_len, ~0))
+    return FALSE;
+  if (!xdr_bytes (xdrs, (char **) &objp->signature.signature_val,
+		  (u_int *) &objp->signature.signature_len, ~0))
+    return FALSE;
+  return TRUE;
+}
diff --git a/nis/nss-nisplus.h b/nis/nss-nisplus.h
new file mode 100644
index 0000000000..ff497f1ca4
--- /dev/null
+++ b/nis/nss-nisplus.h
@@ -0,0 +1,90 @@
+/* Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@uni-paderborn.de>, 1997.
+
+   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 _NIS_NSS_NISPLUS_H
+#define _NIS_NSS_NISPLUS_H	1
+
+#include <rpcsvc/nis.h>
+
+#include "nsswitch.h"
+
+
+/* Convert NIS+ error number to NSS error number.  */
+static enum nss_status niserr2nss_tab[] =
+{
+  [NIS_SUCCESS] = NSS_STATUS_SUCCESS,
+  [NIS_S_SUCCESS] = NSS_STATUS_SUCCESS,
+  [NIS_NOTFOUND] = NSS_STATUS_NOTFOUND,
+  [NIS_S_NOTFOUND] = NSS_STATUS_TRYAGAIN,
+  [NIS_CACHEEXPIRED] = NSS_STATUS_UNAVAIL,
+  [NIS_NAMEUNREACHABLE] = NSS_STATUS_TRYAGAIN,
+  [NIS_UNKNOWNOBJ] = NSS_STATUS_NOTFOUND,
+  [NIS_TRYAGAIN] = NSS_STATUS_TRYAGAIN,
+  [NIS_SYSTEMERROR] = NSS_STATUS_UNAVAIL,	/* Maybe TRYAGAIN ? */
+  [NIS_CHAINBROKEN] = NSS_STATUS_UNAVAIL,
+  [NIS_PERMISSION] = NSS_STATUS_UNAVAIL,
+  [NIS_NOTOWNER] = NSS_STATUS_UNAVAIL,
+  [NIS_NOT_ME] = NSS_STATUS_UNAVAIL,
+  [NIS_NOMEMORY] = NSS_STATUS_TRYAGAIN,
+  [NIS_NAMEEXISTS] = NSS_STATUS_UNAVAIL,
+  [NIS_NOTMASTER] = NSS_STATUS_UNAVAIL,
+  [NIS_INVALIDOBJ] = NSS_STATUS_UNAVAIL,
+  [NIS_BADNAME] = NSS_STATUS_UNAVAIL,
+  [NIS_NOCALLBACK] = NSS_STATUS_UNAVAIL,
+  [NIS_CBRESULTS] = NSS_STATUS_UNAVAIL,
+  [NIS_NOSUCHNAME] = NSS_STATUS_NOTFOUND,
+  [NIS_NOTUNIQUE] = NSS_STATUS_UNAVAIL,
+  [NIS_IBMODERROR] = NSS_STATUS_UNAVAIL,
+  [NIS_NOSUCHTABLE] = NSS_STATUS_UNAVAIL,
+  [NIS_TYPEMISMATCH] = NSS_STATUS_UNAVAIL,
+  [NIS_LINKNAMEERROR] = NSS_STATUS_UNAVAIL,
+  [NIS_PARTIAL] = NSS_STATUS_NOTFOUND,
+  [NIS_TOOMANYATTRS] = NSS_STATUS_UNAVAIL,
+  [NIS_RPCERROR] = NSS_STATUS_UNAVAIL,
+  [NIS_BADATTRIBUTE] = NSS_STATUS_UNAVAIL,
+  [NIS_NOTSEARCHABLE] = NSS_STATUS_UNAVAIL,
+  [NIS_CBERROR] = NSS_STATUS_UNAVAIL,
+  [NIS_FOREIGNNS] = NSS_STATUS_UNAVAIL,
+  [NIS_BADOBJECT] = NSS_STATUS_UNAVAIL,
+  [NIS_NOTSAMEOBJ] = NSS_STATUS_UNAVAIL,
+  [NIS_MODFAIL] = NSS_STATUS_UNAVAIL,
+  [NIS_BADREQUEST] = NSS_STATUS_UNAVAIL,
+  [NIS_NOTEMPTY] = NSS_STATUS_UNAVAIL,
+  [NIS_COLDSTART_ERR] = NSS_STATUS_UNAVAIL,
+  [NIS_RESYNC] = NSS_STATUS_UNAVAIL,
+  [NIS_FAIL] = NSS_STATUS_UNAVAIL,
+  [NIS_UNAVAIL] = NSS_STATUS_UNAVAIL,
+  [NIS_RES2BIG] = NSS_STATUS_UNAVAIL,
+  [NIS_SRVAUTH] = NSS_STATUS_UNAVAIL,
+  [NIS_CLNTAUTH] = NSS_STATUS_UNAVAIL,
+  [NIS_NOFILESPACE] = NSS_STATUS_UNAVAIL,
+  [NIS_NOPROC] = NSS_STATUS_TRYAGAIN,
+  [NIS_DUMPLATER] = NSS_STATUS_UNAVAIL
+};
+#define NISERR_COUNT (sizeof (niserr2nss_tab) / sizeof (niserr2nss_tab[0]))
+
+static inline enum nss_status
+niserr2nss (int errval)
+{
+  if ((unsigned int) errval > NISERR_COUNT)
+    return NSS_STATUS_UNAVAIL;
+  return niserr2nss_tab[errval];
+}
+
+#endif /* nis/nss-nisplus.h */
diff --git a/nis/nss_nis/nis-service.c b/nis/nss_nis/nis-service.c
index fe189b161b..ae7667f231 100644
--- a/nis/nss_nis/nis-service.c
+++ b/nis/nss_nis/nis-service.c
@@ -204,7 +204,7 @@ _nss_nis_getservbyname_r (const char *name, char *protocol,
   enum nss_status status;
   int found;
 
-  if (name == NULL || protocol == NULL)
+  if (name == NULL)
     {
       __set_errno (EINVAL);
       return NSS_STATUS_UNAVAIL;
@@ -219,7 +219,7 @@ _nss_nis_getservbyname_r (const char *name, char *protocol,
          ((status = internal_nis_getservent_r (serv, buffer, buflen, &data))
           == NSS_STATUS_SUCCESS))
     {
-      if (strcmp (serv->s_proto, protocol) == 0)
+      if (protocol == NULL || strcmp (serv->s_proto, protocol) == 0)
 	{
 	  char **cp;
 
diff --git a/nis/nss_nisplus/nisplus-alias.c b/nis/nss_nisplus/nisplus-alias.c
new file mode 100644
index 0000000000..b0f035178e
--- /dev/null
+++ b/nis/nss_nisplus/nisplus-alias.c
@@ -0,0 +1,251 @@
+/* Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
+
+   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 <nss.h>
+#include <errno.h>
+#include <ctype.h>
+#include <string.h>
+#include <aliases.h>
+#include <libc-lock.h>
+#include <rpcsvc/nis.h>
+#include <rpcsvc/nislib.h>
+
+#include "nss-nisplus.h"
+
+__libc_lock_define_initialized (static, lock)
+
+static nis_result *result = NULL;
+static nis_name *names = NULL;
+
+#define NISENTRYVAL(idx,col,res) \
+        ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val)
+
+#define NISENTRYLEN(idx,col,res) \
+        ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len)
+
+static int
+_nss_nisplus_parse_aliasent (nis_result *result, struct aliasent *alias,
+			  char *buffer, size_t buflen)
+{
+  if (result == NULL)
+    return -1;
+
+  if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) ||
+      result->objects.objects_len != 1 ||
+      result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ ||
+      strcmp(result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type,
+	     "mail_aliases") != 0 ||
+      result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 2)
+    return -1;
+  else
+    {
+      char *first_unused = buffer + NISENTRYLEN(0, 1, result) + 1;
+      size_t room_left =
+	buflen - (buflen % __alignof__ (char *)) -
+	NISENTRYLEN(0, 1, result) - 2;
+      char *line;
+      char *cp;
+
+      if (NISENTRYLEN(0, 1, result) >= buflen)
+	{
+	  /* The line is too long for our buffer.  */
+	no_more_room:
+	  __set_errno (ERANGE);
+	  return -1;
+	}
+      else
+	{
+	  strncpy (buffer, NISENTRYVAL(0, 1, result), NISENTRYLEN(0, 1, result));
+	  buffer[NISENTRYLEN(0, 1, result)] = '\0';
+	}
+
+      if (NISENTRYLEN(0, 0, result) >= room_left)
+	goto no_more_room;
+
+      alias->alias_local = 0;
+      alias->alias_members_len = 0;
+      *first_unused = '\0';
+      ++first_unused;
+      strcpy (first_unused, NISENTRYVAL(0, 0, result));
+      first_unused[NISENTRYLEN(0, 0, result)] = '\0';
+      alias->alias_name = first_unused;
+
+      /* Terminate the line for any case.  */
+      cp = strpbrk (alias->alias_name, "#\n");
+      if (cp != NULL)
+	*cp = '\0';
+
+      first_unused += strlen (alias->alias_name) +1;
+      /* Adjust the pointer so it is aligned for
+	 storing pointers.  */
+      first_unused += __alignof__ (char *) - 1;
+      first_unused -= ((first_unused - (char *) 0) % __alignof__ (char *));
+      alias->alias_members = (char **) first_unused;
+
+      line = buffer;
+
+      while (*line != '\0')
+	{
+	  /* Skip leading blanks.  */
+	  while (isspace (*line))
+	    line++;
+
+	  if (*line == '\0')
+	    break;
+
+	  if (room_left < sizeof (char *))
+	    goto no_more_room;
+	  room_left -= sizeof (char *);
+	  alias->alias_members[alias->alias_members_len] = line;
+
+	  while (*line != '\0' && *line != ',')
+	    line++;
+
+	  if (line != alias->alias_members[alias->alias_members_len])
+	    {
+	      *line = '\0';
+	      line++;
+	      alias->alias_members_len++;
+	    }
+	}
+
+      return alias->alias_members_len == 0 ? 0 : 1;
+    }
+}
+
+enum nss_status
+_nss_nisplus_setaliasent (void)
+{
+  __libc_lock_lock (lock);
+
+  if (result)
+    nis_freeresult (result);
+  result = NULL;
+  if (names)
+    {
+      nis_freenames (names);
+      names = NULL;
+    }
+
+  __libc_lock_unlock (lock);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_endaliasent (void)
+{
+  __libc_lock_lock (lock);
+
+  if (result)
+    nis_freeresult (result);
+  result = NULL;
+  if (names)
+    {
+      nis_freenames (names);
+      names = NULL;
+    }
+
+  __libc_lock_unlock (lock);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+static enum nss_status
+internal_nisplus_getaliasent_r (struct aliasent *alias,
+				char *buffer, size_t buflen)
+{
+  int parse_res;
+
+  /* Get the next entry until we found a correct one. */
+  do
+    {
+      if (result == NULL)
+	{
+	  names = nis_getnames("mail_aliases.org_dir");
+	  if (names == NULL || names[0] == NULL)
+	    return NSS_STATUS_UNAVAIL;
+
+	  result = nis_first_entry(names[0]);
+	  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	    return niserr2nss (result->status);
+	}
+      else
+	{
+	  nis_result *res2;
+
+	  res2 = nis_next_entry(names[0], &result->cookie);
+	  nis_freeresult (result);
+	  result = res2;
+	  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	    return niserr2nss (result->status);
+	}
+
+      parse_res = _nss_nisplus_parse_aliasent (result, alias, buffer, buflen);
+    } while (!parse_res);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_getaliasent_r (struct aliasent *result, char *buffer,
+			    size_t buflen)
+{
+  int status;
+
+  __libc_lock_lock (lock);
+
+  status = internal_nisplus_getaliasent_r (result, buffer, buflen);
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+enum nss_status
+_nss_nisplus_getaliasbyname_r (const char *name, struct aliasent *alias,
+			    char *buffer, size_t buflen)
+{
+  int parse_res;
+
+  if (name == NULL || strlen(name) > 8)
+    return NSS_STATUS_NOTFOUND;
+  else
+    {
+      nis_result *result;
+      char buf[strlen (name) + 30];
+
+      sprintf(buf, "[name=%s],mail_aliases.org_dir", name);
+
+      result = nis_list(buf, EXPAND_NAME, NULL, NULL);
+
+      if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	return niserr2nss (result->status);
+
+      parse_res = _nss_nisplus_parse_aliasent (result, alias, buffer, buflen);
+
+      if (parse_res)
+	return NSS_STATUS_SUCCESS;
+
+      if (!parse_res && errno == ERANGE)
+	return NSS_STATUS_TRYAGAIN;
+      else
+	return NSS_STATUS_NOTFOUND;
+    }
+}
diff --git a/nis/nss_nisplus/nisplus-ethers.c b/nis/nss_nisplus/nisplus-ethers.c
new file mode 100644
index 0000000000..ac3e06960a
--- /dev/null
+++ b/nis/nss_nisplus/nisplus-ethers.c
@@ -0,0 +1,278 @@
+/* Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
+
+   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 <nss.h>
+#include <errno.h>
+#include <ctype.h>
+#include <string.h>
+#include <libc-lock.h>
+#include <netdb.h>
+#include <netinet/ether.h>
+#include <rpcsvc/nis.h>
+#include <rpcsvc/nislib.h>
+#include <netinet/if_ether.h>
+
+#include "nss-nisplus.h"
+
+__libc_lock_define_initialized (static, lock)
+
+static nis_result *result = NULL;
+static nis_name *names = NULL;
+
+/* Because the `ethers' lookup does not fit so well in the scheme so
+   we define a dummy struct here which helps us to use the available
+   functions.  */
+struct etherent
+{
+  const char *e_name;
+  struct ether_addr e_addr;
+};
+struct etherent_data {};
+
+#define ENTNAME         etherent
+#define DATABASE        "ethers"
+#include "../../nss/nss_files/files-parse.c"
+LINE_PARSER
+("#",
+ /* Read the ethernet address: 6 x 8bit hexadecimal number.  */
+ {
+   size_t cnt;
+
+   for (cnt = 0; cnt < 6; ++cnt)
+     {
+       unsigned int number;
+
+       if (cnt < 5)
+         INT_FIELD (number, ISCOLON , 0, 16, (unsigned int))
+       else
+         INT_FIELD (number, isspace, 0, 16, (unsigned int))
+
+       if (number > 0xff)
+         return 0;
+       result->e_addr.ether_addr_octet[cnt] = number;
+     }
+ };
+ STRING_FIELD (result->e_name, isspace, 1);
+ )
+
+#define NISENTRYVAL(idx,col,res) \
+        ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val)
+
+#define NISENTRYLEN(idx,col,res) \
+        ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len)
+
+static int
+_nss_nisplus_parse_etherent (nis_result *result, struct etherent *ether,
+			   char *buffer, size_t buflen)
+{
+  char *p = buffer;
+  size_t room_left = buflen;
+  struct parser_data *data = (void *) buffer;
+
+  if (result == NULL)
+    return -1;
+
+  if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) ||
+      result->objects.objects_len != 1 ||
+      result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ ||
+      strcmp(result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type,
+             "ethers_tbl") != 0 ||
+      result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 2)
+    return -1;
+
+  memset (p, '\0', room_left);
+
+  /* Generate the ether entry format and use the normal parser */
+  if (NISENTRYLEN (0, 0, result) +1 > room_left)
+    {
+      __set_errno (ERANGE);
+      return -1;
+    }
+  strncpy (p, NISENTRYVAL (0, 0, result), NISENTRYLEN (0, 0, result));
+  room_left -= (NISENTRYLEN (0, 0, result) +1);
+
+  if (NISENTRYLEN (0, 1, result) +1 > room_left)
+    {
+      __set_errno (ERANGE);
+      return -1;
+    }
+  strcat (p, "\t");
+  strncat (p, NISENTRYVAL (0, 1, result), NISENTRYLEN (0, 1, result));
+  room_left -= (NISENTRYLEN (0, 1, result) + 1);
+
+  return _nss_files_parse_etherent (p,ether, data, buflen);
+}
+
+enum nss_status
+_nss_nisplus_setetherent (void)
+{
+  __libc_lock_lock (lock);
+
+  if (result)
+    nis_freeresult (result);
+  result = NULL;
+  if (names)
+    {
+      nis_freenames (names);
+      names = NULL;
+    }
+
+  __libc_lock_unlock (lock);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_endetherent (void)
+{
+  __libc_lock_lock (lock);
+
+  if (result)
+    nis_freeresult (result);
+  result = NULL;
+  if (names)
+    {
+      nis_freenames (names);
+      names = NULL;
+    }
+
+  __libc_lock_unlock (lock);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+static enum nss_status
+internal_nisplus_getetherent_r (struct etherent *ether, char *buffer,
+				size_t buflen)
+{
+  int parse_res;
+
+  /* Get the next entry until we found a correct one. */
+  do
+    {
+      if (result == NULL)
+	{
+	  names = nis_getnames("ethers.org_dir");
+	  if (names == NULL || names[0] == NULL)
+	    return NSS_STATUS_UNAVAIL;
+
+	  result = nis_first_entry(names[0]);
+	  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	    return niserr2nss (result->status);
+	}
+      else
+	{
+	  nis_result *res2;
+
+	  res2 = nis_next_entry(names[0], &result->cookie);
+	  nis_freeresult (result);
+	  result = res2;
+	  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	    return niserr2nss (result->status);
+	}
+
+      parse_res = _nss_nisplus_parse_etherent (result, ether, buffer, buflen);
+    } while (!parse_res);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_getetherent_r (struct etherent *result, char *buffer,
+			    size_t buflen)
+{
+  int status;
+
+  __libc_lock_lock (lock);
+
+  status = internal_nisplus_getetherent_r (result, buffer, buflen);
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+enum nss_status
+_nss_nisplus_gethostton_r (const char *name, struct etherent *eth,
+			   char *buffer, size_t buflen)
+{
+  int parse_res;
+
+  if (name == NULL)
+    return NSS_STATUS_NOTFOUND;
+  else
+    {
+      nis_result *result;
+      char buf[strlen (name) + 255];
+
+      sprintf(buf, "[name=%s],ethers.org_dir", name);
+
+      result = nis_list(buf, EXPAND_NAME, NULL, NULL);
+
+      if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+        return niserr2nss (result->status);
+
+      parse_res = _nss_nisplus_parse_etherent (result, eth, buffer, buflen);
+
+      if (parse_res)
+        return NSS_STATUS_SUCCESS;
+
+      if (!parse_res && errno == ERANGE)
+        return NSS_STATUS_TRYAGAIN;
+      else
+        return NSS_STATUS_NOTFOUND;
+    }
+}
+
+enum nss_status
+_nss_nisplus_getntohost_r (const struct ether_addr *addr,
+			   struct etherent *eth,
+			   char *buffer, size_t buflen)
+{
+  int parse_res;
+  nis_result *result;
+  char buf[255];
+
+  if (addr == NULL)
+    {
+      __set_errno (EINVAL);
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  memset (&buf, '\0', sizeof (buf));
+  snprintf(buf, sizeof (buf), "[addr=%x:%x:%x:%x:%x:%x],ethers.org_dir",
+	   addr->ether_addr_octet[0], addr->ether_addr_octet[1],
+	   addr->ether_addr_octet[2], addr->ether_addr_octet[3],
+	   addr->ether_addr_octet[4], addr->ether_addr_octet[5]);
+
+  result = nis_list(buf, EXPAND_NAME, NULL, NULL);
+
+  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+    return niserr2nss (result->status);
+
+  parse_res = _nss_nisplus_parse_etherent (result, eth, buffer, buflen);
+
+  if (parse_res)
+    return NSS_STATUS_SUCCESS;
+
+  if (!parse_res && errno == ERANGE)
+    return NSS_STATUS_TRYAGAIN;
+  else
+    return NSS_STATUS_NOTFOUND;
+}
diff --git a/nis/nss_nisplus/nisplus-grp.c b/nis/nss_nisplus/nisplus-grp.c
new file mode 100644
index 0000000000..2e56afa6fc
--- /dev/null
+++ b/nis/nss_nisplus/nisplus-grp.c
@@ -0,0 +1,387 @@
+/* Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
+
+   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 <nss.h>
+#include <grp.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <libc-lock.h>
+#include <rpcsvc/nis.h>
+#include <rpcsvc/nislib.h>
+
+#include "nss-nisplus.h"
+
+__libc_lock_define_initialized (static, lock);
+
+static nis_result *result = NULL;
+static nis_name *names = NULL;
+
+#define NISENTRYVAL(idx,col,res) \
+((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val)
+
+#define NISENTRYLEN(idx,col,res) \
+  ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len)
+
+#define STRUCTURE       group
+#define ENTNAME         grent
+struct grent_data {};
+
+#define TRAILING_LIST_MEMBER            gr_mem
+#define TRAILING_LIST_SEPARATOR_P(c)    ((c) == ',')
+#include "../../nss/nss_files/files-parse.c"
+LINE_PARSER
+(,
+ STRING_FIELD (result->gr_name, ISCOLON, 0);
+ if (line[0] == '\0'
+     && (result->gr_name[0] == '+' || result->gr_name[0] == '-'))
+   {
+     result->gr_passwd = NULL;
+     result->gr_gid = 0;
+   }
+ else
+   {
+     STRING_FIELD (result->gr_passwd, ISCOLON, 0);
+     if (result->gr_name[0] == '+' || result->gr_name[0] == '-')
+       INT_FIELD_MAYBE_NULL (result->gr_gid, ISCOLON, 0, 10, , 0)
+     else
+       INT_FIELD (result->gr_gid, ISCOLON, 0, 10,)
+   }
+ )
+
+static int
+_nss_nisplus_parse_grent (nis_result * result, struct group *gr,
+			  char *buffer, size_t buflen)
+{
+#if 0
+  /* XXX here is a bug, sometimes we get some special characters at the
+     end of a line */
+  char *first_unused = buffer;
+  size_t room_left = buflen;
+  char *line;
+  int count;
+
+  if (result == NULL)
+    return -1;
+
+  if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) ||
+      result->objects.objects_len != 1 ||
+      result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ ||
+   strcmp (result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type,
+	   "group_tbl") != 0 ||
+      result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 4)
+    return -1;
+
+  if (NISENTRYLEN (0, 0, result) >= room_left)
+    {
+      /* The line is too long for our buffer.  */
+    no_more_room:
+      __set_errno (ERANGE);
+      return -1;
+    }
+
+  strncpy (first_unused, NISENTRYVAL (0, 0, result),
+	   NISENTRYLEN (0, 0, result));
+  first_unused[NISENTRYLEN (0, 0, result)] = '\0';
+  gr->gr_name = first_unused;
+  room_left -= (strlen (first_unused) + 1);
+  first_unused += strlen (first_unused) + 1;
+
+  if (NISENTRYLEN (0, 1, result) >= room_left)
+    goto no_more_room;
+
+  strncpy (first_unused, NISENTRYVAL (0, 1, result),
+	   NISENTRYLEN (0, 1, result));
+  first_unused[NISENTRYLEN (0, 1, result)] = '\0';
+  gr->gr_passwd = first_unused;
+  room_left -= (strlen (first_unused) + 1);
+  first_unused += strlen (first_unused) + 1;
+
+  if (NISENTRYLEN (0, 2, result) >= room_left)
+    goto no_more_room;
+
+  strncpy (first_unused, NISENTRYVAL (0, 2, result),
+	   NISENTRYLEN (0, 2, result));
+  first_unused[NISENTRYLEN (0, 2, result)] = '\0';
+  gr->gr_gid = atoi (first_unused);
+  room_left -= (strlen (first_unused) + 1);
+  first_unused += strlen (first_unused) + 1;
+
+  if (NISENTRYLEN (0, 3, result) >= room_left)
+    goto no_more_room;
+
+  strncpy (first_unused, NISENTRYVAL (0, 3, result),
+	   NISENTRYLEN (0, 3, result));
+  first_unused[NISENTRYLEN (0, 3, result)] = '\0';
+  line = first_unused;
+  room_left -= (strlen (line) + 1);
+  first_unused += strlen (line) + 1;
+  /* Adjust the pointer so it is aligned for
+     storing pointers.  */
+  first_unused += __alignof__ (char *) - 1;
+  first_unused -= ((first_unused - (char *) 0) % __alignof__ (char *));
+  gr->gr_mem = (char **) first_unused;
+
+  count = 0;
+  while (*line != '\0')
+    {
+      /* Skip leading blanks.  */
+      while (isspace (*line))
+	++line;
+
+      if (*line == '\0')
+	break;
+
+      if (room_left < sizeof (char *))
+	  goto no_more_room;
+      room_left -= sizeof (char *);
+      gr->gr_mem[count] = line;
+
+      while (*line != '\0' && *line != ',' && !isspace(*line))
+	++line;
+
+      if (line != gr->gr_mem[count])
+	{
+	  *line = '\0';
+	  ++line;
+	  ++count;
+	}
+      else
+	gr->gr_mem[count] = NULL;
+    }
+  if (room_left < sizeof (char *))
+      goto no_more_room;
+  room_left -= sizeof (char *);
+  gr->gr_mem[count] = NULL;
+
+  return 1;
+#else
+  char *p = buffer;
+  size_t room_left = buflen;
+  struct parser_data *data = (void *) buffer;
+
+  if (result == NULL)
+    return -1;
+
+  if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) ||
+      result->objects.objects_len != 1 ||
+      result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ ||
+   strcmp (result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type,
+	   "group_tbl") != 0 ||
+      result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 4)
+    return -1;
+
+  memset (p, '\0', room_left);
+
+  if (NISENTRYLEN (0, 0, result) + 1 > room_left)
+    {
+      __set_errno (ERANGE);
+      return -1;
+    }
+  strncpy (p, NISENTRYVAL (0, 0, result), NISENTRYLEN (0, 0, result));
+  room_left -= (NISENTRYLEN (0, 0, result) + 1);
+  strcat (p, ":");
+
+  if (NISENTRYLEN (0, 1, result) + 1 > room_left)
+    {
+      __set_errno (ERANGE);
+      return -1;
+    }
+  strncat (p, NISENTRYVAL (0, 1, result), NISENTRYLEN (0, 1, result));
+  room_left -= (NISENTRYLEN (0, 1, result) + 1);
+  strcat (p, ":");
+  if (NISENTRYLEN (0, 2, result) + 1 > room_left)
+    {
+      __set_errno (ERANGE);
+      return -1;
+    }
+  strncat (p, NISENTRYVAL (0, 2, result), NISENTRYLEN (0, 2, result));
+  room_left -= (NISENTRYLEN (0, 2, result) + 1);
+  strcat (p, ":");
+  if (NISENTRYLEN (0, 3, result) + 1 > room_left)
+    {
+      __set_errno (ERANGE);
+      return -1;
+    }
+  strncat (p, NISENTRYVAL (0, 3, result), NISENTRYLEN (0, 3, result));
+  room_left -= (NISENTRYLEN (0, 3, result) + 1);
+
+  return _nss_files_parse_grent (p, gr, data, buflen);
+#endif
+}
+
+enum nss_status
+_nss_nisplus_setgrent (void)
+{
+  __libc_lock_lock (lock);
+
+  if (result)
+    nis_freeresult (result);
+  result = NULL;
+  if (names)
+    {
+      nis_freenames (names);
+      names = NULL;
+    }
+
+  __libc_lock_unlock (lock);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_endgrent (void)
+{
+  __libc_lock_lock (lock);
+
+  if (result)
+    nis_freeresult (result);
+  result = NULL;
+  if (names)
+    {
+      nis_freenames (names);
+      names = NULL;
+    }
+
+  __libc_lock_unlock (lock);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+static enum nss_status
+internal_nisplus_getgrent_r (struct group *gr, char *buffer, size_t buflen)
+{
+  int parse_res;
+
+  /* Get the next entry until we found a correct one. */
+  do
+    {
+      if (result == NULL)
+	{
+	  names = nis_getnames ("group.org_dir");
+	  if (names == NULL || names[0] == NULL)
+	    return NSS_STATUS_UNAVAIL;
+
+	  result = nis_first_entry (names[0]);
+	  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	    return niserr2nss (result->status);
+	}
+      else
+	{
+	  nis_result *res;
+
+	  res = nis_next_entry (names[0], &result->cookie);
+	  nis_freeresult (result);
+	  result = res;
+	  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	    return niserr2nss (result->status);
+	}
+
+      parse_res = _nss_nisplus_parse_grent (result, gr, buffer, buflen);
+    }
+  while (!parse_res);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_getgrent_r (struct group *result, char *buffer, size_t buflen)
+{
+  int status;
+
+  __libc_lock_lock (lock);
+
+  status = internal_nisplus_getgrent_r (result, buffer, buflen);
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+enum nss_status
+_nss_nisplus_getgrnam_r (const char *name, struct group *gr,
+			 char *buffer, size_t buflen)
+{
+  int parse_res;
+
+  if (name == NULL || strlen (name) > 8)
+    return NSS_STATUS_NOTFOUND;
+  else
+    {
+      nis_result *result;
+      char buf[strlen (name) + 24];
+
+      sprintf (buf, "[name=%s],group.org_dir", name);
+
+      result = nis_list (buf, EXPAND_NAME, NULL, NULL);
+
+      if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	{
+	  enum nss_status status = niserr2nss (result->status);
+
+	  nis_freeresult (result);
+	  return status;
+	}
+
+      parse_res = _nss_nisplus_parse_grent (result, gr, buffer, buflen);
+
+      nis_freeresult (result);
+
+      if (parse_res)
+	return NSS_STATUS_SUCCESS;
+
+      if (!parse_res && errno == ERANGE)
+	return NSS_STATUS_TRYAGAIN;
+      else
+	return NSS_STATUS_NOTFOUND;
+    }
+}
+
+enum nss_status
+_nss_nisplus_getgrgid_r (const gid_t gid, struct group *gr,
+			 char *buffer, size_t buflen)
+{
+  int parse_res;
+  nis_result *result;
+  char buf[36];
+
+  sprintf (buf, "[gid=%d],group.org_dir", gid);
+
+  result = nis_list (buf, EXPAND_NAME, NULL, NULL);
+
+  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+    {
+      enum nss_status status = niserr2nss (result->status);
+
+      nis_freeresult (result);
+      return status;
+    }
+
+  parse_res = _nss_nisplus_parse_grent (result, gr, buffer, buflen);
+
+  nis_freeresult (result);
+
+  if (parse_res)
+    return NSS_STATUS_SUCCESS;
+
+  if (!parse_res && errno == ERANGE)
+    return NSS_STATUS_TRYAGAIN;
+  else
+    return NSS_STATUS_NOTFOUND;
+}
diff --git a/nis/nss_nisplus/nisplus-hosts.c b/nis/nss_nisplus/nisplus-hosts.c
new file mode 100644
index 0000000000..0a486411de
--- /dev/null
+++ b/nis/nss_nisplus/nisplus-hosts.c
@@ -0,0 +1,412 @@
+/* Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
+
+   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 <nss.h>
+#include <netdb.h>
+#include <errno.h>
+#include <ctype.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <libc-lock.h>
+#include <rpcsvc/nis.h>
+#include <rpcsvc/nislib.h>
+
+#include "nss-nisplus.h"
+
+__libc_lock_define_initialized (static, lock)
+
+static nis_result *result = NULL;
+static nis_name *names = NULL;
+
+#define NISENTRYVAL(idx,col,res) \
+        ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val)
+
+#define NISENTRYLEN(idx,col,res) \
+        ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len)
+
+/* Get implementation for some internal functions. */
+#include "../../resolv/mapv4v6addr.h"
+#include "../../resolv/mapv4v6hostent.h"
+
+#define ENTNAME         hostent
+#define DATABASE        "hosts"
+#define NEED_H_ERRNO
+
+#define ENTDATA hostent_data
+struct hostent_data
+  {
+    unsigned char host_addr[16];        /* IPv4 or IPv6 address.  */
+    char *h_addr_ptrs[2];       /* Points to that and null terminator.  */
+  };
+
+#define TRAILING_LIST_MEMBER            h_aliases
+#define TRAILING_LIST_SEPARATOR_P       isspace
+#include "../../nss/nss_files/files-parse.c"
+LINE_PARSER
+("#",
+ {
+   char *addr;
+
+   STRING_FIELD (addr, isspace, 1);
+
+   /* Parse address.  */
+   if ((_res.options & RES_USE_INET6)
+       && inet_pton (AF_INET6, addr, entdata->host_addr) > 0)
+     {
+       result->h_addrtype = AF_INET6;
+       result->h_length = IN6ADDRSZ;
+     }
+   else
+     if (inet_pton (AF_INET, addr, entdata->host_addr) > 0)
+       {
+         if (_res.options & RES_USE_INET6)
+           {
+             map_v4v6_address ((char *) entdata->host_addr,
+                               (char *) entdata->host_addr);
+             result->h_addrtype = AF_INET6;
+             result->h_length = IN6ADDRSZ;
+           }
+         else
+           {
+             result->h_addrtype = AF_INET;
+             result->h_length = INADDRSZ;
+           }
+       }
+     else
+       /* Illegal address: ignore line.  */
+       return 0;
+
+   /* Store a pointer to the address in the expected form.  */
+   entdata->h_addr_ptrs[0] = entdata->host_addr;
+   entdata->h_addr_ptrs[1] = NULL;
+   result->h_addr_list = entdata->h_addr_ptrs;
+
+   /* If we need the host entry in IPv6 form change it now.  */
+   if (_res.options & RES_USE_INET6)
+     {
+        char *bufptr = data->linebuffer;
+       size_t buflen = (char *) data + datalen - bufptr;
+       map_v4v6_hostent (result, &bufptr, &buflen);
+     }
+
+   STRING_FIELD (result->h_name, isspace, 1);
+ }
+)
+
+
+static int
+_nss_nisplus_parse_hostent (nis_result *result, struct hostent *host,
+			    char *buffer, size_t buflen)
+{
+  char *p = buffer;
+  size_t room_left = buflen;
+  int parse_res, i;
+  struct parser_data *data = (void *) buffer;
+
+  if (result == NULL)
+    return -1;
+
+  if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) ||
+      result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ ||
+      strcmp(result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type,
+             "hosts_tbl") != 0 ||
+      result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 4)
+    return -1;
+
+  memset (p, '\0', room_left);
+
+  /* Generate the hosts entry format and use the normal parser */
+  if (NISENTRYLEN (0, 2, result) + 1 > room_left)
+    {
+      __set_errno (ERANGE);
+      return -1;
+    }
+  strncpy (p, NISENTRYVAL (0, 2, result),
+	   NISENTRYLEN (0, 2, result));
+  room_left -= (NISENTRYLEN (0, 2, result) + 1);
+
+  if (NISENTRYLEN (0, 0, result) + 1 > room_left)
+    {
+      __set_errno (ERANGE);
+      return -1;
+    }
+  strcat (p, "\t");
+  strncat (p, NISENTRYVAL (0, 0, result), NISENTRYLEN (0, 0, result));
+  room_left -= (NISENTRYLEN (0, 0, result) + 1);
+                                       /* + 1: We overwrite the last \0 */
+
+  for (i = 1; i < result->objects.objects_len; i++)
+    {
+      if (NISENTRYLEN (i, 1, result) + 1 > room_left)
+	{
+	  __set_errno (ERANGE);
+	  return -1;
+	}
+      strcat (p, " ");
+      strcat (p, NISENTRYVAL (i, 1, result));
+      room_left -= (NISENTRYLEN (i, 1, result) + 1);
+    }
+
+  parse_res = parse_line (p, host, data, buflen);
+
+  return parse_res;
+}
+
+enum nss_status
+_nss_nisplus_sethostent (void)
+{
+  __libc_lock_lock (lock);
+
+  if (result)
+    nis_freeresult (result);
+  result = NULL;
+  if (names)
+    {
+      nis_freenames (names);
+      names = NULL;
+    }
+
+  __libc_lock_unlock (lock);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_endhostent (void)
+{
+  __libc_lock_lock (lock);
+
+  if (result)
+    nis_freeresult (result);
+  result = NULL;
+  if (names)
+    {
+      nis_freenames (names);
+      names = NULL;
+    }
+
+  __libc_lock_unlock (lock);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+static enum nss_status
+internal_nisplus_gethostent_r (struct hostent *host, char *buffer,
+			       size_t buflen, int *herrnop)
+{
+  int parse_res;
+
+  /* Get the next entry until we found a correct one. */
+  do
+    {
+      if (result == NULL)
+	{
+	  names = nis_getnames("hosts.org_dir");
+	  if (names == NULL || names[0] == NULL)
+	    return NSS_STATUS_UNAVAIL;
+
+	  result = nis_first_entry(names[0]);
+	  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+            {
+              int retval;
+
+              retval = niserr2nss (result->status);
+              if (retval == NSS_STATUS_TRYAGAIN)
+                {
+                  *herrnop = NETDB_INTERNAL;
+                  __set_errno (EAGAIN);
+                }
+              return retval;
+            }
+
+	}
+      else
+	{
+	  nis_result *res2;
+
+	  res2 = nis_next_entry(names[0], &result->cookie);
+	  nis_freeresult (result);
+	  result = res2;
+	  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+            {
+              int retval;
+
+              retval = niserr2nss (result->status);
+              if (retval == NSS_STATUS_TRYAGAIN)
+                {
+                  *herrnop = NETDB_INTERNAL;
+                  __set_errno (EAGAIN);
+                }
+              return retval;
+            }
+	}
+
+      parse_res = _nss_nisplus_parse_hostent (result, host, buffer, buflen);
+      if (!parse_res && errno == ERANGE)
+        {
+          *herrnop = NETDB_INTERNAL;
+          return NSS_STATUS_TRYAGAIN;
+        }
+
+    } while (!parse_res);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_gethostent_r (struct hostent *result, char *buffer,
+			   size_t buflen, int *herrnop)
+{
+  int status;
+
+  __libc_lock_lock (lock);
+
+  status = internal_nisplus_gethostent_r (result, buffer, buflen, herrnop);
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+enum nss_status
+_nss_nisplus_gethostbyname2_r (const char *name, int af, struct hostent *host,
+			      char *buffer, size_t buflen, int *herrnop)
+{
+  int parse_res, retval;
+
+  if (name == NULL)
+    {
+      __set_errno (EINVAL);
+      *herrnop = NETDB_INTERNAL;
+      return NSS_STATUS_NOTFOUND;
+    }
+  else
+    {
+      nis_result *result;
+      char buf[strlen (name) + 255];
+
+      /* Search at first in the alias list, and use the correct name
+	 for the next search */
+      sprintf(buf, "[name=%s],hosts.org_dir", name);
+      result = nis_list(buf, EXPAND_NAME, NULL, NULL);
+
+      /* If we do not find it, try it as original name. But if the
+	 database is correct, we should find it in the first case, too */
+      if ((result->status != NIS_SUCCESS &&
+	   result->status != NIS_S_SUCCESS) ||
+	  result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ ||
+	  strcmp(result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type,
+		 "hosts_tbl") != 0 ||
+	  result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len
+	  < 3)
+	sprintf(buf, "[cname=%s],hosts.org_dir", name);
+      else
+	sprintf(buf, "[cname=%s],hosts.org_dir", NISENTRYVAL(0, 0, result));
+
+      nis_freeresult (result);
+      result = nis_list(buf, EXPAND_NAME, NULL, NULL);
+
+      retval = niserr2nss (result->status);
+      if (retval != NSS_STATUS_SUCCESS)
+        {
+          if (retval == NSS_STATUS_TRYAGAIN)
+            {
+              __set_errno (EAGAIN);
+              *herrnop = NETDB_INTERNAL;
+            }
+	  nis_freeresult (result);
+          return retval;
+        }
+
+      parse_res = _nss_nisplus_parse_hostent (result, host, buffer, buflen);
+
+      nis_freeresult (result);
+
+      if (parse_res)
+	return NSS_STATUS_SUCCESS;
+
+      *herrnop = NETDB_INTERNAL;
+      if (!parse_res && errno == ERANGE)
+	return NSS_STATUS_TRYAGAIN;
+      else
+	return NSS_STATUS_NOTFOUND;
+    }
+}
+
+enum nss_status
+_nss_nisplus_gethostbyname_r (const char *name, struct hostent *host,
+			      char *buffer, size_t buflen, int *h_errnop)
+{
+  if (_res.options & RES_USE_INET6)
+    {
+      enum nss_status status;
+
+      status = _nss_nisplus_gethostbyname2_r (name, AF_INET6, host, buffer,
+					      buflen, h_errnop);
+      if (status == NSS_STATUS_SUCCESS)
+        return status;
+    }
+
+  return _nss_nisplus_gethostbyname2_r (name, AF_INET, host, buffer,
+					buflen, h_errnop);
+}
+
+enum nss_status
+_nss_nisplus_gethostbyaddr_r (const char *addr, struct hostent *host,
+			      char *buffer, size_t buflen, int *herrnop)
+{
+  if (addr == NULL)
+    return NSS_STATUS_NOTFOUND;
+  else
+    {
+      nis_result *result;
+      char buf[24 + strlen (addr)];
+      int retval, parse_res;
+
+      sprintf(buf, "[addr=%s],hosts.org_dir", addr);
+
+      result = nis_list(buf, EXPAND_NAME, NULL, NULL);
+
+      retval = niserr2nss (result->status);
+      if (retval != NSS_STATUS_SUCCESS)
+        {
+          if (retval == NSS_STATUS_TRYAGAIN)
+            {
+              __set_errno (EAGAIN);
+              *herrnop = NETDB_INTERNAL;
+            }
+	  nis_freeresult (result);
+          return retval;
+        }
+
+      parse_res = _nss_nisplus_parse_hostent (result, host, buffer, buflen);
+
+      nis_freeresult (result);
+
+      if (parse_res)
+	return NSS_STATUS_SUCCESS;
+
+      *herrnop = NETDB_INTERNAL;
+      if (!parse_res && errno == ERANGE)
+	return NSS_STATUS_TRYAGAIN;
+      else
+	return NSS_STATUS_NOTFOUND;
+    }
+}
diff --git a/nis/nss_nisplus/nisplus-netgrp.c b/nis/nss_nisplus/nisplus-netgrp.c
new file mode 100644
index 0000000000..766d2bc773
--- /dev/null
+++ b/nis/nss_nisplus/nisplus-netgrp.c
@@ -0,0 +1,141 @@
+/* Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
+
+   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 <nss.h>
+#include <errno.h>
+#include <ctype.h>
+#include <netdb.h>
+#include <string.h>
+#include <netgroup.h>
+#include <libc-lock.h>
+#include <rpcsvc/nis.h>
+#include <rpcsvc/nislib.h>
+
+#include "nss-nisplus.h"
+
+__libc_lock_define_initialized (static, lock)
+
+static char *data = NULL;
+static size_t data_size = 0;
+static char *cursor = NULL;;
+
+extern enum nss_status
+_nss_netgroup_parseline (char **cursor, struct __netgrent *result,
+                         char *buffer, size_t buflen);
+
+#define NISENTRYVAL(idx,col,res) \
+        ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val)
+
+#define NISENTRYLEN(idx,col,res) \
+        ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len)
+
+enum nss_status
+_nss_nisplus_setnetgrent (char *group)
+
+{
+  enum nss_status status;
+  nis_result *result;
+  char buf[strlen (group) + 30];
+  int i;
+  size_t len;
+
+  if (group == NULL || group[0] == '\0')
+    return NSS_STATUS_UNAVAIL;
+
+  status = NSS_STATUS_SUCCESS;
+
+  __libc_lock_lock (lock);
+
+  if (data != NULL)
+    {
+      free (data);
+      data = NULL;
+      data_size = 0;
+      cursor = NULL;
+    }
+
+  sprintf(buf, "[name=%s],netgroup.org_dir", group);
+
+  result = nis_list(buf, EXPAND_NAME, NULL, NULL);
+
+  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+    status = niserr2nss (result->status);
+
+  len = 0;
+  for (i = 0; i < result->objects.objects_len; i++)
+    len += 1 + NISENTRYLEN (i, 1, result) + 1 + NISENTRYLEN(i,2,result)
+      + 1 + NISENTRYLEN(i,3,result) + 1 + NISENTRYLEN(i,4,result) + 2;
+
+  data = malloc (len+1);
+  memset (data, '\0', len+1);
+
+  for (i = 0; i < result->objects.objects_len; i++)
+    {
+      strncat (data, NISENTRYVAL (i, 1, result), NISENTRYLEN (i, 1, result));
+      strcat (data," (");
+      strncat (data, NISENTRYVAL(i,2,result), NISENTRYLEN (i, 2, result));
+      strcat (data, ",");
+      strncat (data, NISENTRYVAL(i,3,result), NISENTRYLEN (i, 3, result));
+      strcat (data, ",");
+      strncat (data, NISENTRYVAL(i,4,result), NISENTRYLEN (i, 4, result));
+      strcat (data, ") ");
+    }
+
+  nis_freeresult (result);
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+enum nss_status
+_nss_nisplus_endnetgrent (void)
+{
+  __libc_lock_lock (lock);
+
+  if (data != NULL)
+    {
+      free (data);
+      data = NULL;
+      data_size = 0;
+      cursor = NULL;
+    }
+
+  __libc_lock_unlock (lock);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_getnetgrent_r (struct __netgrent *result,
+			    char *buffer, size_t buflen)
+{
+  enum nss_status status;
+
+  if (cursor == NULL)
+    return NSS_STATUS_NOTFOUND;
+
+  __libc_lock_lock (lock);
+
+  status = _nss_netgroup_parseline (&cursor, result, buffer, buflen);
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
diff --git a/nis/nss_nisplus/nisplus-network.c b/nis/nss_nisplus/nisplus-network.c
new file mode 100644
index 0000000000..28580b6bc9
--- /dev/null
+++ b/nis/nss_nisplus/nisplus-network.c
@@ -0,0 +1,340 @@
+/* Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
+
+   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 <nss.h>
+#include <netdb.h>
+#include <errno.h>
+#include <ctype.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include <libc-lock.h>
+#include <rpcsvc/nis.h>
+#include <rpcsvc/nislib.h>
+
+#include "nss-nisplus.h"
+
+/* Get the declaration of the parser function.  */
+#define ENTNAME netent
+#define DATABASE "networks"
+#define TRAILING_LIST_MEMBER            n_aliases
+#define TRAILING_LIST_SEPARATOR_P       isspace
+#include "../nss/nss_files/files-parse.c"
+LINE_PARSER
+("#",
+ {
+   char *addr;
+
+   STRING_FIELD (result->n_name, isspace, 1);
+
+   STRING_FIELD (addr, isspace, 1);
+   result->n_net = inet_network (addr);
+
+ })
+
+__libc_lock_define_initialized (static, lock)
+
+static nis_result *result = NULL;
+static nis_name *names = NULL;
+
+#define NISENTRYVAL(idx,col,res) \
+        ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val)
+
+#define NISENTRYLEN(idx,col,res) \
+        ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len)
+
+
+static int
+_nss_nisplus_parse_netent (nis_result *result, struct netent *network,
+			    char *buffer, size_t buflen)
+{
+  char *p = buffer;
+  size_t room_left = buflen;
+  int i;
+  struct parser_data *data = (void *) buffer;
+
+  if (result == NULL)
+    return -1;
+
+  if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) ||
+      result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ ||
+      strcmp(result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type,
+             "networks_tbl") != 0 ||
+      result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 3)
+    return -1;
+
+  /* Generate the network entry format and use the normal parser */
+  if (NISENTRYLEN (0, 0, result) +1 > room_left)
+    {
+      __set_errno (ERANGE);
+      return -1;
+    }
+
+  memset (p, '\0', room_left);
+
+  strncpy (p, NISENTRYVAL (0, 0, result), NISENTRYLEN (0, 0, result));
+  room_left -= (NISENTRYLEN (0, 0, result) +1);
+
+  if (NISENTRYLEN (0, 2, result) +1 > room_left)
+    {
+      __set_errno (ERANGE);
+      return -1;
+    }
+  strcat (p, "\t");
+  strncat (p, NISENTRYVAL (0, 2, result), NISENTRYLEN (0, 2, result));
+  room_left -= (NISENTRYLEN (0, 2, result) + 1);
+                                        /* + 1: We overwrite the last \0 */
+
+  for (i = 1; i < result->objects.objects_len; i++)
+    /* XXX should we start with i = 0 or with i = 1 ? */
+    {
+      if (NISENTRYLEN (i, 1, result) +1 > room_left)
+	{
+	  __set_errno (ERANGE);
+	  return -1;
+	}
+      strcat (p, " ");
+      strncat (p, NISENTRYVAL (i, 1, result), NISENTRYLEN (i, 1, result));
+      room_left -= (NISENTRYLEN (i, 1, result) + 1);
+    }
+
+  return _nss_files_parse_netent (p, network, data, buflen);
+}
+
+enum nss_status
+_nss_nisplus_setnetent (void)
+{
+  __libc_lock_lock (lock);
+
+  if (result)
+    nis_freeresult (result);
+  result = NULL;
+  if (names)
+    {
+      nis_freenames (names);
+      names = NULL;
+    }
+
+  __libc_lock_unlock (lock);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_endnetent (void)
+{
+  __libc_lock_lock (lock);
+
+  if (result)
+    nis_freeresult (result);
+  result = NULL;
+  if (names)
+    {
+      nis_freenames (names);
+      names = NULL;
+    }
+
+  __libc_lock_unlock (lock);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+static enum nss_status
+internal_nisplus_getnetent_r (struct netent *network, char *buffer,
+			       size_t buflen, int *herrnop)
+{
+  int parse_res;
+
+  /* Get the next entry until we found a correct one. */
+  do
+    {
+      if (result == NULL)
+	{
+	  names = nis_getnames("networks.org_dir");
+	  if (names == NULL || names[0] == NULL)
+	    return NSS_STATUS_UNAVAIL;
+
+	  result = nis_first_entry(names[0]);
+	  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	    {
+	      int retval;
+
+	      retval = niserr2nss (result->status);
+	      if (retval == NSS_STATUS_TRYAGAIN)
+		{
+		  *herrnop = NETDB_INTERNAL;
+		  __set_errno (EAGAIN);
+		}
+	      return retval;
+	    }
+	}
+      else
+	{
+	  nis_result *res;
+
+	  res = nis_next_entry(names[0], &result->cookie);
+	  nis_freeresult (result);
+	  result = res;
+	  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	    {
+	      int retval;
+
+	      retval = niserr2nss (result->status);
+	      if (retval == NSS_STATUS_TRYAGAIN)
+		{
+		  *herrnop = NETDB_INTERNAL;
+		  __set_errno (EAGAIN);
+		}
+	      return retval;
+	    }
+	}
+
+      parse_res = _nss_nisplus_parse_netent (result, network, buffer, buflen);
+      if (!parse_res && errno == ERANGE)
+        {
+          *herrnop = NETDB_INTERNAL;
+          return NSS_STATUS_TRYAGAIN;
+        }
+
+    } while (!parse_res);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_getnetent_r (struct netent *result, char *buffer,
+			   size_t buflen, int *herrnop)
+{
+  int status;
+
+  __libc_lock_lock (lock);
+
+  status = internal_nisplus_getnetent_r (result, buffer, buflen, herrnop);
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+enum nss_status
+_nss_nisplus_getnetbyname_r (const char *name, struct netent *network,
+			      char *buffer, size_t buflen, int *herrnop)
+{
+  int parse_res, retval;
+
+  if (name == NULL)
+    {
+      __set_errno (EINVAL);
+      *herrnop = NETDB_INTERNAL;
+      return NSS_STATUS_UNAVAIL;
+    }
+  else
+    {
+      nis_result *result;
+      char buf[strlen (name) + 255];
+
+
+      /* Search at first in the alias list, and use the correct name
+	 for the next search */
+      sprintf(buf, "[name=%s],networks.org_dir", name);
+      result = nis_list(buf, EXPAND_NAME, NULL, NULL);
+
+      /* If we do not find it, try it as original name. But if the
+	 database is correct, we should find it in the first case, too */
+      if ((result->status != NIS_SUCCESS &&
+	   result->status != NIS_S_SUCCESS) ||
+	  result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ ||
+	  strcmp(result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type,
+		 "networks_tbl") != 0 ||
+	  result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 3)
+	sprintf(buf, "[cname=%s],networks.org_dir", name);
+      else
+	sprintf(buf, "[cname=%s],networks.org_dir", NISENTRYVAL(0, 0, result));
+
+      nis_freeresult (result);
+      result = nis_list(buf, EXPAND_NAME, NULL, NULL);
+
+      retval = niserr2nss (result->status);
+      if (retval != NSS_STATUS_SUCCESS)
+	{
+	  if (retval == NSS_STATUS_TRYAGAIN)
+	    {
+	      __set_errno (EAGAIN);
+	      *herrnop = NETDB_INTERNAL;
+	    }
+	  nis_freeresult (result);
+	  return retval;
+	}
+
+      parse_res = _nss_nisplus_parse_netent (result, network, buffer, buflen);
+
+      nis_freeresult (result);
+
+      if (parse_res)
+	return NSS_STATUS_SUCCESS;
+
+      *herrnop = NETDB_INTERNAL;
+      if (!parse_res && errno == ERANGE)
+	return NSS_STATUS_TRYAGAIN;
+      else
+	return NSS_STATUS_NOTFOUND;
+    }
+}
+
+/* XXX type is ignored, SUN's NIS+ table doesn't support it */
+enum nss_status
+_nss_nisplus_getnetbyaddr_r (const unsigned long addr, const int type,
+			     struct netent *network,
+			     char *buffer, size_t buflen, int *herrnop)
+{
+  int parse_res, retval;
+  nis_result *result;
+  char buf[1024];
+  struct in_addr in;
+
+  in = inet_makeaddr (addr, 0);
+  snprintf(buf, sizeof (buf) - 1, "[addr=%s],networks.org_dir",
+	   inet_ntoa (in));
+
+  result = nis_list(buf, EXPAND_NAME, NULL, NULL);
+
+  retval = niserr2nss (result->status);
+  if (retval != NSS_STATUS_SUCCESS)
+    {
+      if (retval == NSS_STATUS_TRYAGAIN)
+	{
+	  __set_errno (EAGAIN);
+	  *herrnop = NETDB_INTERNAL;
+	}
+      nis_freeresult (result);
+      return retval;
+    }
+
+  parse_res = _nss_nisplus_parse_netent (result, network, buffer, buflen);
+
+  nis_freeresult (result);
+
+  if (parse_res)
+    return NSS_STATUS_SUCCESS;
+
+  *herrnop = NETDB_INTERNAL;
+  if (!parse_res && errno == ERANGE)
+    return NSS_STATUS_TRYAGAIN;
+  else
+    return NSS_STATUS_NOTFOUND;
+}
diff --git a/nis/nss_nisplus/nisplus-proto.c b/nis/nss_nisplus/nisplus-proto.c
new file mode 100644
index 0000000000..b26cb8230e
--- /dev/null
+++ b/nis/nss_nisplus/nisplus-proto.c
@@ -0,0 +1,284 @@
+/* Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
+
+   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 <nss.h>
+#include <errno.h>
+#include <ctype.h>
+#include <netdb.h>
+#include <string.h>
+#include <libc-lock.h>
+#include <rpcsvc/nis.h>
+#include <rpcsvc/nislib.h>
+
+#include "nss-nisplus.h"
+
+__libc_lock_define_initialized (static, lock)
+
+static nis_result *result = NULL;
+static nis_name *names = NULL;
+
+#define ENTNAME         protoent
+#define DATABASE        "protocols"
+#define TRAILING_LIST_MEMBER            p_aliases
+#define TRAILING_LIST_SEPARATOR_P       isspace
+#include "../../nss/nss_files/files-parse.c"
+LINE_PARSER
+("#",
+ STRING_FIELD (result->p_name, isspace, 1);
+ INT_FIELD (result->p_proto, isspace, 1, 10,);
+)
+
+#define NISENTRYVAL(idx,col,res) \
+        ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val)
+
+#define NISENTRYLEN(idx,col,res) \
+        ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len)
+
+static int
+_nss_nisplus_parse_protoent (nis_result * result, struct protoent *proto,
+			     char *buffer, size_t buflen)
+{
+  char *p = buffer;
+  size_t room_left = buflen;
+  int i;
+  struct parser_data *data = (void *) buffer;
+
+  if (result == NULL)
+    return -1;
+
+  if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) ||
+      result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ ||
+   strcmp (result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type,
+	   "protocols_tbl") != 0 ||
+      result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 3)
+    return -1;
+
+  memset (p, '\0', room_left);
+
+  /* Generate the protocols entry format and use the normal parser */
+  if (NISENTRYLEN (0, 0, result) + 1 > room_left)
+    {
+      __set_errno (ERANGE);
+      return -1;
+    }
+  strncpy (p, NISENTRYVAL (0, 0, result), NISENTRYLEN (0, 0, result));
+  room_left -= (NISENTRYLEN (0, 0, result) + 1);
+
+  if (NISENTRYLEN (0, 2, result) + 1 > room_left)
+    {
+      __set_errno (ERANGE);
+      return -1;
+    }
+  strcat (p, "\t");
+  strncat (p, NISENTRYVAL (0, 2, result), NISENTRYLEN (0, 2, result));
+  room_left -= (NISENTRYLEN (0, 2, result) + 1);
+  /* + 1: We overwrite the last \0 */
+
+  for (i = 1; i < result->objects.objects_len; i++)
+    {
+      if (NISENTRYLEN (i, 1, result) + 1 > room_left)
+	{
+	  __set_errno (ERANGE);
+	  return -1;
+	}
+      strcat (p, " ");
+      strncat (p, NISENTRYVAL (i, 1, result), NISENTRYLEN (i, 1, result));
+      room_left -= (NISENTRYLEN (i, 1, result) + 1);
+    }
+
+  return _nss_files_parse_protoent (p, proto, data, buflen);
+}
+
+enum nss_status
+_nss_nisplus_setprotoent (void)
+{
+  __libc_lock_lock (lock);
+
+  if (result)
+    nis_freeresult (result);
+  result = NULL;
+  if (names)
+    {
+      nis_freenames (names);
+      names = NULL;
+    }
+
+  __libc_lock_unlock (lock);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_endprotoent (void)
+{
+  __libc_lock_lock (lock);
+
+  if (result)
+    nis_freeresult (result);
+  result = NULL;
+  if (names)
+    {
+      nis_freenames (names);
+      names = NULL;
+    }
+
+  __libc_lock_unlock (lock);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+static enum nss_status
+internal_nisplus_getprotoent_r (struct protoent *proto, char *buffer,
+				size_t buflen)
+{
+  int parse_res;
+
+  /* Get the next entry until we found a correct one. */
+  do
+    {
+      if (result == NULL)
+	{
+	  names = nis_getnames ("protocols.org_dir");
+	  if (names == NULL || names[0] == NULL)
+	    return NSS_STATUS_UNAVAIL;
+
+	  result = nis_first_entry (names[0]);
+	  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	    return niserr2nss (result->status);
+	}
+      else
+	{
+	  nis_result *res;
+
+	  res = nis_next_entry (names[0], &result->cookie);
+	  nis_freeresult (result);
+	  result = res;
+
+	  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	    return niserr2nss (result->status);
+	}
+
+      parse_res = _nss_nisplus_parse_protoent (result, proto, buffer, buflen);
+    }
+  while (!parse_res);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_getprotoent_r (struct protoent *result, char *buffer,
+			    size_t buflen)
+{
+  int status;
+
+  __libc_lock_lock (lock);
+
+  status = internal_nisplus_getprotoent_r (result, buffer, buflen);
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+enum nss_status
+_nss_nisplus_getprotobyname_r (const char *name, struct protoent *proto,
+			       char *buffer, size_t buflen)
+{
+  int parse_res;
+
+  if (name == NULL)
+    return NSS_STATUS_NOTFOUND;
+  else
+    {
+      nis_result *result;
+      char buf[strlen (name) + 255];
+
+      /* Search at first in the alias list, and use the correct name
+         for the next search */
+      sprintf (buf, "[name=%s],protocols.org_dir", name);
+      result = nis_list (buf, EXPAND_NAME, NULL, NULL);
+
+      /* If we do not find it, try it as original name. But if the
+         database is correct, we should find it in the first case, too */
+      if ((result->status != NIS_SUCCESS &&
+	   result->status != NIS_S_SUCCESS) ||
+	  result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ ||
+	  strcmp (result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type,
+		  "protocols_tbl") != 0 ||
+	  result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 3)
+	sprintf (buf, "[cname=%s],protocols.org_dir", name);
+      else
+	sprintf (buf, "[cname=%s],protocols.org_dir", NISENTRYVAL (0, 0, result));
+
+      nis_freeresult (result);
+      result = nis_list (buf, EXPAND_NAME, NULL, NULL);
+
+      if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	{
+	  enum nss_status status = niserr2nss (result->status);
+
+	  nis_freeresult (result);
+	  return status;
+	}
+
+      parse_res = _nss_nisplus_parse_protoent (result, proto, buffer, buflen);
+
+      nis_freeresult (result);
+
+      if (parse_res)
+	return NSS_STATUS_SUCCESS;
+
+      if (!parse_res && errno == ERANGE)
+	return NSS_STATUS_TRYAGAIN;
+      else
+	return NSS_STATUS_NOTFOUND;
+    }
+}
+
+enum nss_status
+_nss_nisplus_getprotobynumber_r (const int number, struct protoent *proto,
+				 char *buffer, size_t buflen)
+{
+  int parse_res;
+  nis_result *result;
+  char buf[46];
+
+  snprintf (buf, sizeof (buf), "[number=%d],protocols.org_dir", number);
+
+  result = nis_list (buf, EXPAND_NAME, NULL, NULL);
+
+  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+    {
+      enum nss_status status = niserr2nss (result->status);
+
+      nis_freeresult (result);
+      return status;
+    }
+
+  parse_res = _nss_nisplus_parse_protoent (result, proto, buffer, buflen);
+
+  nis_freeresult (result);
+  if (parse_res)
+    return NSS_STATUS_SUCCESS;
+
+  if (!parse_res && errno == ERANGE)
+    return NSS_STATUS_TRYAGAIN;
+  else
+    return NSS_STATUS_NOTFOUND;
+}
diff --git a/nis/nss_nisplus/nisplus-publickey.c b/nis/nss_nisplus/nisplus-publickey.c
new file mode 100644
index 0000000000..7312c91229
--- /dev/null
+++ b/nis/nss_nisplus/nisplus-publickey.c
@@ -0,0 +1,347 @@
+/* Copyright (c) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
+
+   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 <nss.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <syslog.h>
+#include <rpc/key_prot.h>
+#include <rpcsvc/nis.h>
+#include <rpcsvc/nislib.h>
+
+#include <nss-nisplus.h>
+
+extern int xdecrypt (char *, char *);
+
+/* If we found the entry, we give a SUCCESS and an empty key back. */
+enum nss_status
+_nss_nisplus_getpublickey (const char *netname, char *pkey)
+{
+  nis_result *res;
+  enum nss_status retval;
+  char buf[NIS_MAXNAMELEN+2];
+  char *domain, *cptr;
+  int len;
+
+  pkey[0] = 0;
+
+  if (netname == NULL)
+    {
+      __set_errno (EINVAL);
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  domain = strchr (netname, '@');
+  if (!domain)
+    return NSS_STATUS_UNAVAIL;
+  domain++;
+
+  snprintf (buf, NIS_MAXNAMELEN,
+	    "[auth_name=%s,auth_type=DES],cred.org_dir.%s",
+	    netname, domain);
+
+  if (buf[strlen (buf)-1] != '.')
+    strcat(buf, ".");
+
+  res = nis_list(buf, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH,
+		 NULL, NULL);
+
+  retval = niserr2nss (res->status);
+
+  if (retval != NSS_STATUS_SUCCESS)
+    {
+      if (retval == NSS_STATUS_TRYAGAIN)
+	__set_errno (EAGAIN);
+      nis_freeresult (res);
+      return retval;
+    }
+
+  if (res->objects.objects_len > 1)
+    {
+      /*
+       * More than one principal with same uid?
+       * something wrong with cred table. Should be unique
+       * Warn user and continue.
+       */
+      printf (_("DES entry for netname %s not unique\n"), netname);
+      nis_freeresult (res);
+      return NSS_STATUS_SUCCESS;
+    }
+
+  len = ENTRY_LEN (res->objects.objects_val, 3);
+  memcpy (pkey, ENTRY_VAL (res->objects.objects_val,3), len);
+  pkey[len] = 0;
+  cptr = strchr (pkey, ':');
+  if (cptr)
+    cptr[0] = '\0';
+  nis_freeresult (res);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_getsecretkey (const char *netname, char *skey, char *passwd)
+{
+  nis_result *res;
+  enum nss_status retval;
+  char buf[NIS_MAXNAMELEN+2];
+  char *domain, *cptr;
+  int len;
+
+  skey[0] = 0;
+
+  if (netname == NULL)
+    {
+      __set_errno (EINVAL);
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  domain = strchr (netname, '@');
+  if (!domain)
+    return NSS_STATUS_UNAVAIL;
+  domain++;
+
+  snprintf (buf, NIS_MAXNAMELEN,
+	    "[auth_name=%s,auth_type=DES],cred.org_dir.%s",
+	    netname, domain);
+
+  if (buf[strlen(buf)-1] != '.')
+    strcat(buf, ".");
+
+  res = nis_list (buf, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH,
+		  NULL, NULL);
+
+  retval = niserr2nss (res->status);
+
+  if (retval != NSS_STATUS_SUCCESS)
+    {
+      if (retval == NSS_STATUS_TRYAGAIN)
+	__set_errno (EAGAIN);
+      nis_freeresult (res);
+      return retval;
+    }
+
+  if (res->objects.objects_len > 1)
+    {
+      /*
+       * More than one principal with same uid?
+       * something wrong with cred table. Should be unique
+       * Warn user and continue.
+       */
+      printf (_("DES entry for netname %s not unique\n"), netname);
+      nis_freeresult (res);
+      return NSS_STATUS_SUCCESS;
+    }
+
+  len = ENTRY_LEN (res->objects.objects_val, 4);
+  memcpy (buf, ENTRY_VAL (res->objects.objects_val,4), len);
+  skey[len] = 0;
+  cptr = strchr (skey, ':');
+  if (cptr)
+    cptr[0] = '\0';
+  nis_freeresult (res);
+
+  if (!xdecrypt (buf, passwd))
+    return NSS_STATUS_SUCCESS;
+
+  if (memcmp (buf, &(buf[HEXKEYBYTES]), KEYCHECKSUMSIZE) != 0)
+    return NSS_STATUS_SUCCESS;
+
+  buf[HEXKEYBYTES] = 0;
+  strcpy (skey, buf);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+/* Parse information from the passed string.
+   The format of the string passed is gid,grp,grp, ...  */
+static enum nss_status
+parse_grp_str (const char *s, gid_t *gidp, int *gidlenp, gid_t *gidlist)
+{
+  int gidlen;
+
+  if (!s || (!isdigit (*s)))
+    {
+      syslog (LOG_ERR, "netname2user: missing group id list in '%s'.", s);
+      return NSS_STATUS_NOTFOUND;
+    }
+
+  *gidp = (atoi (s));
+
+  gidlen = 0;
+
+  while ((s = strchr (s, ',')) != NULL)
+    {
+      s++;
+      gidlist[gidlen++] = atoi (s);
+    }
+  *gidlenp = gidlen;
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_netname2user (char netname[MAXNETNAMELEN + 1], uid_t *uidp,
+		       gid_t *gidp, int *gidlenp, gid_t *gidlist)
+{
+  char *domain;
+  nis_result *res;
+  char sname[NIS_MAXNAMELEN+1]; /*  search criteria + table name */
+  char principal[NIS_MAXNAMELEN+1];
+  int len;
+
+  /* 1.  Get home domain of user. */
+  domain = strchr (netname, '@');
+  if (! domain)
+    return NSS_STATUS_UNAVAIL;
+
+  domain++;  /* skip '@' */
+
+  /* 2.  Get user's nisplus principal name.  */
+  if ((strlen (netname) + strlen (domain)+45) >
+      (size_t) NIS_MAXNAMELEN)
+    return NSS_STATUS_UNAVAIL;
+
+  snprintf (sname, NIS_MAXNAMELEN,
+	    "[auth_name=%s,auth_type=DES],cred.org_dir.%s",
+	    netname, domain);
+  if (sname[strlen (sname) - 1] != '.')
+    strcat(sname, ".");
+
+  /* must use authenticated call here */
+  /* XXX but we cant, for now. XXX */
+  res = nis_list (sname, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH,
+		  NULL, NULL);
+  switch(res->status)
+    {
+    case NIS_SUCCESS:
+    case NIS_S_SUCCESS:
+      break;   /* go and do something useful */
+    case NIS_NOTFOUND:
+    case NIS_PARTIAL:
+    case NIS_NOSUCHNAME:
+    case NIS_NOSUCHTABLE:
+      nis_freeresult (res);
+      return NSS_STATUS_NOTFOUND;
+    case NIS_S_NOTFOUND:
+    case NIS_TRYAGAIN:
+      syslog (LOG_ERR, "netname2user: (nis+ lookup): %s\n",
+	      nis_sperrno (res->status));
+      nis_freeresult (res);
+      return NSS_STATUS_TRYAGAIN;
+    default:
+      syslog (LOG_ERR, "netname2user: (nis+ lookup): %s\n",
+	      nis_sperrno (res->status));
+      nis_freeresult (res);
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  if (res->objects.objects_len > 1)
+    {
+      /*
+       * A netname belonging to more than one principal?
+       * Something wrong with cred table. should be unique.
+       * Warn user and continue.
+       */
+      syslog (LOG_ALERT,
+	      _("netname2user: DES entry for %s in directory %s not unique"),
+	      netname, domain);
+    }
+
+  len = ENTRY_LEN(res->objects.objects_val, 0);
+  strncpy(principal, ENTRY_VAL(res->objects.objects_val, 0), len);
+  principal[len] = '\0';
+  nis_freeresult(res);
+
+  if (principal[0] == '\0')
+    return NSS_STATUS_UNAVAIL;
+
+  /*
+   *      3.  Use principal name to look up uid/gid information in
+   *      LOCAL entry in **local** cred table.
+   */
+  domain = nis_local_directory ();
+  if ((strlen(principal)+strlen(domain)+45) >
+      (size_t) NIS_MAXNAMELEN)
+    {
+      syslog (LOG_ERR, _("netname2user: principal name '%s' too long"),
+	      principal);
+      return NSS_STATUS_UNAVAIL;
+    }
+  sprintf(sname, "[cname=%s,auth_type=LOCAL],cred.org_dir.%s",
+	  principal, domain);
+  if (sname[strlen(sname) - 1] != '.')
+    strcat(sname, ".");
+
+  /* must use authenticated call here */
+  /* XXX but we cant, for now. XXX */
+  res = nis_list(sname, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH,
+		 NULL, NULL);
+  switch(res->status) {
+  case NIS_NOTFOUND:
+  case NIS_PARTIAL:
+  case NIS_NOSUCHNAME:
+  case NIS_NOSUCHTABLE:
+    nis_freeresult (res);
+    return NSS_STATUS_NOTFOUND;
+  case NIS_S_NOTFOUND:
+  case NIS_TRYAGAIN:
+    syslog (LOG_ERR,
+	    "netname2user: (nis+ lookup): %s\n",
+	    nis_sperrno (res->status));
+    nis_freeresult (res);
+    return NSS_STATUS_TRYAGAIN;
+  case NIS_SUCCESS:
+  case NIS_S_SUCCESS:
+    break;   /* go and do something useful */
+  default:
+    syslog (LOG_ERR, "netname2user: (nis+ lookup): %s\n",
+	    nis_sperrno (res->status));
+    nis_freeresult (res);
+    return NSS_STATUS_UNAVAIL;
+  }
+
+  if (res->objects.objects_len > 1)
+    {
+      /*
+       * A principal can have more than one LOCAL entry?
+       * Something wrong with cred table.
+       * Warn user and continue.
+       */
+      syslog(LOG_ALERT,
+	     _("netname2user: LOCAL entry for %s in directory %s not unique"),
+	     netname, domain);
+    }
+  /* Fetch the uid */
+  *uidp = (atoi (ENTRY_VAL (res->objects.objects_val, 2)));
+
+  if (*uidp == 0)
+    {
+      syslog (LOG_ERR, _("netname2user: should not have uid 0"));
+      return NSS_STATUS_NOTFOUND;
+    }
+
+  parse_grp_str (ENTRY_VAL (res->objects.objects_val, 3),
+		 gidp, gidlenp, gidlist);
+
+  nis_freeresult (res);
+  return NSS_STATUS_SUCCESS;
+}
diff --git a/nis/nss_nisplus/nisplus-pwd.c b/nis/nss_nisplus/nisplus-pwd.c
new file mode 100644
index 0000000000..3717d5e98a
--- /dev/null
+++ b/nis/nss_nisplus/nisplus-pwd.c
@@ -0,0 +1,293 @@
+/* Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
+
+   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 <nss.h>
+#include <errno.h>
+#include <pwd.h>
+#include <string.h>
+#include <libc-lock.h>
+#include <rpcsvc/nis.h>
+#include <rpcsvc/nislib.h>
+
+#include "nss-nisplus.h"
+
+__libc_lock_define_initialized (static, lock)
+
+static nis_result *result = NULL;
+static nis_name *names = NULL;
+
+#define NISENTRYVAL(idx,col,res) \
+        ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val)
+
+#define NISENTRYLEN(idx,col,res) \
+        ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len)
+
+static int
+_nss_nisplus_parse_pwent (nis_result *result, struct passwd *pw,
+			  char *buffer, size_t buflen)
+{
+  char *first_unused = buffer;
+  size_t room_left = buflen;
+
+  if (result == NULL)
+    return -1;
+
+  if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) ||
+      result->objects.objects_len != 1 ||
+      result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ ||
+      strcmp(result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type,
+	     "passwd_tbl") != 0 ||
+      result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 7)
+    return -1;
+
+  if (NISENTRYLEN(0, 0, result) >= room_left)
+    {
+      /* The line is too long for our buffer.  */
+    no_more_room:
+      __set_errno (ERANGE);
+      return -1;
+    }
+
+  strncpy (first_unused, NISENTRYVAL(0, 0, result),
+	   NISENTRYLEN (0, 0, result));
+  first_unused[NISENTRYLEN(0, 0, result)] = '\0';
+  pw->pw_name = first_unused;
+  room_left -= (strlen (first_unused) +1);
+  first_unused += strlen (first_unused) +1;
+
+  if (NISENTRYLEN(0, 1, result) >= room_left)
+    goto no_more_room;
+
+  strncpy (first_unused, NISENTRYVAL(0, 1, result),
+	   NISENTRYLEN (0, 1, result));
+  first_unused[NISENTRYLEN(0, 1, result)] = '\0';
+  pw->pw_passwd = first_unused;
+  room_left -= (strlen (first_unused) +1);
+  first_unused += strlen (first_unused) +1;
+
+  if (NISENTRYLEN(0, 2, result) >= room_left)
+    goto no_more_room;
+
+  strncpy (first_unused, NISENTRYVAL (0, 2, result),
+	   NISENTRYLEN (0, 2, result));
+  first_unused[NISENTRYLEN(0, 2, result)] = '\0';
+  pw->pw_uid = atoi (first_unused);
+  room_left -= (strlen (first_unused) +1);
+  first_unused += strlen (first_unused) +1;
+
+  if (NISENTRYLEN(0, 3, result) >= room_left)
+    goto no_more_room;
+
+  strncpy (first_unused, NISENTRYVAL(0, 3, result),
+	   NISENTRYLEN (0, 3, result));
+  first_unused[NISENTRYLEN(0, 3, result)] = '\0';
+  pw->pw_gid = atoi (first_unused);
+  room_left -= (strlen (first_unused) +1);
+  first_unused += strlen (first_unused) +1;
+
+  if (NISENTRYLEN(0, 4, result) >= room_left)
+    goto no_more_room;
+
+  strncpy (first_unused, NISENTRYVAL(0, 4, result),
+	   NISENTRYLEN (0, 4, result));
+  first_unused[NISENTRYLEN(0, 4, result)] = '\0';
+  pw->pw_gecos = first_unused;
+  room_left -= (strlen (first_unused) +1);
+  first_unused += strlen (first_unused) +1;
+
+  if (NISENTRYLEN(0, 5, result) >= room_left)
+    goto no_more_room;
+
+  strncpy (first_unused, NISENTRYVAL (0, 5, result),
+	   NISENTRYLEN (0, 5, result));
+  first_unused[NISENTRYLEN(0, 5, result)] = '\0';
+  pw->pw_dir = first_unused;
+  room_left -= (strlen (first_unused) +1);
+  first_unused += strlen (first_unused) +1;
+
+  if (NISENTRYLEN(0, 6, result) >= room_left)
+    goto no_more_room;
+
+  strncpy (first_unused, NISENTRYVAL (0, 6, result),
+	   NISENTRYLEN (0, 6, result));
+  first_unused[NISENTRYLEN (0, 6, result)] = '\0';
+  pw->pw_shell = first_unused;
+  room_left -= (strlen (first_unused) +1);
+  first_unused += strlen (first_unused) +1;
+
+  return 1;
+}
+
+enum nss_status
+_nss_nisplus_setpwent (void)
+{
+  __libc_lock_lock (lock);
+
+  if (result)
+    nis_freeresult (result);
+  result = NULL;
+  if (names)
+    {
+      nis_freenames (names);
+      names = NULL;
+    }
+
+  __libc_lock_unlock (lock);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_endpwent (void)
+{
+  __libc_lock_lock (lock);
+
+  if (result)
+    nis_freeresult (result);
+  result = NULL;
+  if (names)
+    {
+      nis_freenames (names);
+      names = NULL;
+    }
+
+  __libc_lock_unlock (lock);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+static enum nss_status
+internal_nisplus_getpwent_r (struct passwd *pw, char *buffer, size_t buflen)
+{
+  int parse_res;
+
+  /* Get the next entry until we found a correct one. */
+  do
+    {
+      if (result == NULL)
+	{
+	  names = nis_getnames ("passwd.org_dir");
+	  if (names == NULL || names[0] == NULL)
+	    return NSS_STATUS_UNAVAIL;
+
+	  result = nis_first_entry(names[0]);
+	  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	    return niserr2nss (result->status);
+	}
+      else
+	{
+	  nis_result *res;
+
+	  res = nis_next_entry(names[0], &result->cookie);
+	  nis_freeresult (result);
+	  result = res;
+	  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	    return niserr2nss (result->status);
+	}
+
+      parse_res = _nss_nisplus_parse_pwent (result, pw, buffer, buflen);
+    } while (!parse_res);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_getpwent_r (struct passwd *result, char *buffer, size_t buflen)
+{
+  int status;
+
+  __libc_lock_lock (lock);
+
+  status = internal_nisplus_getpwent_r (result, buffer, buflen);
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+enum nss_status
+_nss_nisplus_getpwnam_r (const char *name, struct passwd *pw,
+		     char *buffer, size_t buflen)
+{
+  int parse_res;
+
+  if (name == NULL || strlen (name) > 8)
+    return NSS_STATUS_NOTFOUND;
+  else
+    {
+      nis_result *result;
+      char buf[strlen (name) + 24];
+
+      sprintf(buf, "[name=%s],passwd.org_dir", name);
+
+      result = nis_list(buf, EXPAND_NAME, NULL, NULL);
+
+      if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	{
+	  enum nss_status status =  niserr2nss (result->status);
+
+	  nis_freeresult (result);
+	  return status;
+	}
+
+      parse_res = _nss_nisplus_parse_pwent (result, pw, buffer, buflen);
+
+      nis_freeresult (result);
+
+      if (parse_res)
+	return NSS_STATUS_SUCCESS;
+
+      if (!parse_res && errno == ERANGE)
+	return NSS_STATUS_TRYAGAIN;
+      else
+	return NSS_STATUS_NOTFOUND;
+    }
+}
+
+enum nss_status
+_nss_nisplus_getpwuid_r (const uid_t uid, struct passwd *pw,
+		     char *buffer, size_t buflen)
+{
+  int parse_res;
+  nis_result *result;
+  char buf[100];
+
+  sprintf(buf, "[uid=%d],passwd.org_dir", uid);
+
+  result = nis_list(buf, EXPAND_NAME, NULL, NULL);
+
+  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+   {
+     enum nss_status status = niserr2nss (result->status);
+
+     nis_freeresult (result);
+     return status;
+   }
+
+  parse_res = _nss_nisplus_parse_pwent (result, pw, buffer, buflen);
+
+  nis_freeresult (result);
+  if (parse_res)
+    return NSS_STATUS_SUCCESS;
+
+  if (!parse_res && errno == ERANGE)
+    return NSS_STATUS_TRYAGAIN;
+  else
+    return NSS_STATUS_NOTFOUND;
+}
diff --git a/nis/nss_nisplus/nisplus-rpc.c b/nis/nss_nisplus/nisplus-rpc.c
new file mode 100644
index 0000000000..326f262749
--- /dev/null
+++ b/nis/nss_nisplus/nisplus-rpc.c
@@ -0,0 +1,284 @@
+/* Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
+
+   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 <nss.h>
+#include <errno.h>
+#include <ctype.h>
+#include <string.h>
+#include <libc-lock.h>
+#include <rpc/netdb.h>
+#include <rpcsvc/nis.h>
+#include <rpcsvc/nislib.h>
+
+#include "nss-nisplus.h"
+
+__libc_lock_define_initialized (static, lock)
+
+static nis_result *result = NULL;
+static nis_name *names = NULL;
+
+#define ENTNAME         rpcent
+#define DATABASE        "rpc"
+#define TRAILING_LIST_MEMBER            r_aliases
+#define TRAILING_LIST_SEPARATOR_P       isspace
+#include "../../nss/nss_files/files-parse.c"
+LINE_PARSER
+("#",
+ STRING_FIELD (result->r_name, isspace, 1);
+ INT_FIELD (result->r_number, isspace, 1, 10,);
+ )
+
+#define NISENTRYVAL(idx,col,res) \
+        ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val)
+
+#define NISENTRYLEN(idx,col,res) \
+        ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len)
+
+static int
+_nss_nisplus_parse_rpcent (nis_result *result, struct rpcent *rpc,
+			   char *buffer, size_t buflen)
+{
+  char *p = buffer;
+  size_t room_left = buflen;
+  int i;
+  struct parser_data *data = (void *) buffer;
+
+  if (result == NULL)
+    return -1;
+
+  if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) ||
+      result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ ||
+      strcmp(result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type,
+             "rpc_tbl") != 0 ||
+      result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 3)
+    return -1;
+
+  memset (p, '\0', room_left);
+
+  /* Generate the rpc entry format and use the normal parser */
+  if (NISENTRYLEN (0, 0, result) +1 > room_left)
+    {
+      __set_errno (ERANGE);
+      return -1;
+    }
+  strncpy (p, NISENTRYVAL (0, 0, result), NISENTRYLEN (0, 0, result));
+  room_left -= (NISENTRYLEN (0, 0, result) +1);
+
+  if (NISENTRYLEN (0, 2, result) +1 > room_left)
+    {
+      __set_errno (ERANGE);
+      return -1;
+    }
+  strcat (p, "\t");
+  strncat (p, NISENTRYVAL (0, 2, result), NISENTRYLEN (0, 2, result));
+  room_left -= (NISENTRYLEN (0, 2, result) + 1);
+                                       /* + 1: We overwrite the last \0 */
+
+  for (i = 0; i < result->objects.objects_len; i++)
+    /* XXX should we start with i = 0 or with i = 1 ? */
+    {
+      if (NISENTRYLEN (i, 1, result) +1 > room_left)
+        {
+          __set_errno (ERANGE);
+          return -1;
+        }
+      strcat (p, " ");
+      strncat (p, NISENTRYVAL (i, 1, result), NISENTRYLEN (i, 1, result));
+      room_left -= (NISENTRYLEN (i, 1, result) + 1);
+    }
+
+  return _nss_files_parse_rpcent (p, rpc, data, buflen);
+}
+
+enum nss_status
+_nss_nisplus_setrpcent (void)
+{
+  __libc_lock_lock (lock);
+
+  if (result)
+    nis_freeresult (result);
+  result = NULL;
+  if (names)
+    {
+      nis_freenames (names);
+      names = NULL;
+    }
+
+  __libc_lock_unlock (lock);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_endrpcent (void)
+{
+  __libc_lock_lock (lock);
+
+  if (result)
+    nis_freeresult (result);
+  result = NULL;
+  if (names)
+    {
+      nis_freenames (names);
+      names = NULL;
+    }
+
+  __libc_lock_unlock (lock);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+static enum nss_status
+internal_nisplus_getrpcent_r (struct rpcent *rpc, char *buffer,
+			      size_t buflen)
+{
+  int parse_res;
+
+  /* Get the next entry until we found a correct one. */
+  do
+    {
+      if (result == NULL)
+	{
+	  names = nis_getnames ("rpc.org_dir");
+	  if (names == NULL || names[0] == NULL)
+	    return NSS_STATUS_UNAVAIL;
+
+	  result = nis_first_entry(names[0]);
+	  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	    return niserr2nss (result->status);
+	}
+      else
+	{
+	  nis_result *res;
+
+	  res = nis_next_entry (names[0], &result->cookie);
+	  nis_freeresult (result);
+	  result = res;
+	  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	    return niserr2nss (result->status);
+	}
+
+      parse_res = _nss_nisplus_parse_rpcent (result, rpc, buffer, buflen);
+    } while (!parse_res);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_getrpcent_r (struct rpcent *result, char *buffer,
+			  size_t buflen)
+{
+  int status;
+
+  __libc_lock_lock (lock);
+
+  status = internal_nisplus_getrpcent_r (result, buffer, buflen);
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+enum nss_status
+_nss_nisplus_getrpcbyname_r (const char *name, struct rpcent *rpc,
+			     char *buffer, size_t buflen)
+{
+  int parse_res;
+
+  if (name == NULL)
+    return NSS_STATUS_NOTFOUND;
+  else
+    {
+      nis_result *result;
+      char buf[strlen (name) + 255];
+
+      /* Search at first in the alias list, and use the correct name
+         for the next search */
+      sprintf (buf, "[name=%s],rpc.org_dir", name);
+      result = nis_list (buf, EXPAND_NAME, NULL, NULL);
+
+      /* If we do not find it, try it as original name. But if the
+         database is correct, we should find it in the first case, too */
+      if ((result->status != NIS_SUCCESS &&
+           result->status != NIS_S_SUCCESS) ||
+          result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ ||
+          strcmp (result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type,
+		  "rpc_tbl") != 0 ||
+          result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 3)
+        sprintf (buf, "[cname=%s],rpc.org_dir", name);
+      else
+        sprintf (buf, "[cname=%s],rpc.org_dir", NISENTRYVAL(0, 0, result));
+
+      nis_freeresult (result);
+      result = nis_list(buf, EXPAND_NAME, NULL, NULL);
+
+      if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	{
+	  enum nss_status status = niserr2nss (result->status);
+
+	  nis_freeresult (result);
+	  return status;
+	}
+
+      parse_res = _nss_nisplus_parse_rpcent (result, rpc, buffer, buflen);
+
+      nis_freeresult (result);
+
+      if (parse_res)
+	return NSS_STATUS_SUCCESS;
+
+      if (!parse_res && errno == ERANGE)
+	return NSS_STATUS_TRYAGAIN;
+      else
+	return NSS_STATUS_NOTFOUND;
+    }
+}
+
+enum nss_status
+_nss_nisplus_getrpcbynumber_r (const int number, struct rpcent *rpc,
+				char *buffer, size_t buflen)
+{
+  int parse_res;
+  nis_result *result;
+  char buf[100];
+
+  snprintf (buf, sizeof (buf), "[number=%d],rpc.org_dir", number);
+
+  result = nis_list(buf, EXPAND_NAME, NULL, NULL);
+
+  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+    {
+      enum nss_status status = niserr2nss (result->status);
+
+      nis_freeresult (result);
+      return status;
+    }
+
+  parse_res = _nss_nisplus_parse_rpcent (result, rpc, buffer, buflen);
+
+  nis_freeresult (result);
+
+  if (parse_res)
+    return NSS_STATUS_SUCCESS;
+
+  if (!parse_res && errno == ERANGE)
+    return NSS_STATUS_TRYAGAIN;
+  else
+    return NSS_STATUS_NOTFOUND;
+}
diff --git a/nis/nss_nisplus/nisplus-service.c b/nis/nss_nisplus/nisplus-service.c
new file mode 100644
index 0000000000..54f4f876c7
--- /dev/null
+++ b/nis/nss_nisplus/nisplus-service.c
@@ -0,0 +1,308 @@
+/* Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
+
+   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 <nss.h>
+#include <errno.h>
+#include <ctype.h>
+#include <netdb.h>
+#include <string.h>
+#include <libc-lock.h>
+#include <rpcsvc/nis.h>
+#include <rpcsvc/nislib.h>
+
+#include "nss-nisplus.h"
+
+__libc_lock_define_initialized (static, lock);
+
+static nis_result *result = NULL;
+static nis_name *names = NULL;
+
+#define ENTNAME         servent
+#define DATABASE        "services"
+#define TRAILING_LIST_MEMBER            s_aliases
+#define TRAILING_LIST_SEPARATOR_P       isspace
+#include "../../nss/nss_files/files-parse.c"
+#define ISSLASH(c) ((c) == '/')
+LINE_PARSER
+("#",
+ STRING_FIELD (result->s_name, isspace, 1);
+ INT_FIELD (result->s_port, ISSLASH, 10, 0, htons);
+ STRING_FIELD (result->s_proto, isspace, 1);
+ )
+
+
+#define NISENTRYVAL(idx,col,res) \
+  ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val)
+
+#define NISENTRYLEN(idx,col,res) \
+    ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len)
+
+static int
+_nss_nisplus_parse_servent (nis_result *result, struct servent *serv,
+			    char *buffer, size_t buflen)
+{
+  char *p = buffer;
+  size_t room_left = buflen;
+  int i;
+  struct parser_data *data = (void *) buffer;
+
+  if (result == NULL)
+    return -1;
+
+  if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) ||
+      result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ ||
+   strcmp (result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type,
+	   "services_tbl") != 0 ||
+      result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 4)
+    return -1;
+
+  memset (p, '\0', room_left);
+
+  /* Generate the services entry format and use the normal parser */
+  if (NISENTRYLEN (0, 0, result) + 1 > room_left)
+    {
+      __set_errno (ERANGE);
+      return -1;
+    }
+  strncpy (p, NISENTRYVAL (0, 0, result), NISENTRYLEN (0, 0, result));
+  room_left -= (NISENTRYLEN (0, 0, result) + 1);
+
+  if (NISENTRYLEN (0, 3, result) + 1 > room_left)
+    {
+      __set_errno (ERANGE);
+      return -1;
+    }
+  strcat (p, "\t");
+  strncat (p, NISENTRYVAL (0, 3, result), NISENTRYLEN (0, 3, result));
+  room_left -= (NISENTRYLEN (0, 3, result) + 1);
+  if (NISENTRYLEN (0, 2, result) + 1 > room_left)
+    {
+      __set_errno (ERANGE);
+      return -1;
+    }
+  strcat (p, "/");
+  strncat (p, NISENTRYVAL (0, 2, result), NISENTRYLEN (0, 2, result));
+  room_left -= (NISENTRYLEN (0, 2, result) + 1);
+
+  for (i = 1; i < result->objects.objects_len; i++)
+    {
+      if (NISENTRYLEN (i, 1, result) + 1 > room_left)
+	{
+	  __set_errno (ERANGE);
+	  return -1;
+	}
+      strcat (p, " ");
+      strcat (p, NISENTRYVAL (i, 1, result));
+      room_left -= (NISENTRYLEN (i, 1, result) + 1);
+    }
+
+  return _nss_files_parse_servent (p, serv, data, buflen);
+}
+
+enum nss_status
+_nss_nisplus_setservent (void)
+{
+  __libc_lock_lock (lock);
+
+  if (result)
+    nis_freeresult (result);
+  result = NULL;
+  if (names)
+    {
+      nis_freenames (names);
+      names = NULL;
+    }
+
+  __libc_lock_unlock (lock);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_endservent (void)
+{
+  __libc_lock_lock (lock);
+
+  if (result)
+    nis_freeresult (result);
+  result = NULL;
+  if (names)
+    {
+      nis_freenames (names);
+      names = NULL;
+    }
+
+  __libc_lock_unlock (lock);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+static enum nss_status
+internal_nisplus_getservent_r (struct servent *serv, char *buffer,
+			       size_t buflen)
+{
+  int parse_res;
+
+  /* Get the next entry until we found a correct one. */
+  do
+    {
+      if (result == NULL)
+	{
+	  names = nis_getnames ("services.org_dir");
+	  if (names == NULL || names[0] == NULL)
+	    return NSS_STATUS_UNAVAIL;
+
+	  result = nis_first_entry (names[0]);
+	  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	    return niserr2nss (result->status);
+	}
+      else
+	{
+	  nis_result *res;
+
+	  res = nis_next_entry (names[0], &result->cookie);
+	  nis_freeresult (result);
+	  result = res;
+	  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	    return niserr2nss (result->status);
+	}
+
+      parse_res = _nss_nisplus_parse_servent (result, serv, buffer, buflen);
+    }
+  while (!parse_res);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_getservent_r (struct servent *result, char *buffer,
+			   size_t buflen)
+{
+  int status;
+
+  __libc_lock_lock (lock);
+
+  status = internal_nisplus_getservent_r (result, buffer, buflen);
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+enum nss_status
+_nss_nisplus_getservbyname_r (const char *name, const char *protocol,
+			      struct servent *serv,
+			      char *buffer, size_t buflen)
+{
+  int parse_res;
+
+  if (name == NULL || protocol == NULL)
+    {
+      __set_errno (EINVAL);
+      return NSS_STATUS_NOTFOUND;
+    }
+  else
+    {
+      nis_result *result;
+      char buf[strlen (name) + 255];
+
+      /* Search at first in the alias list, and use the correct name
+         for the next search */
+      sprintf (buf, "[name=%s,proto=%s],services.org_dir", name,
+	       protocol);
+      result = nis_list (buf, EXPAND_NAME, NULL, NULL);
+
+      /* If we do not find it, try it as original name. But if the
+         database is correct, we should find it in the first case, too */
+      if ((result->status != NIS_SUCCESS &&
+	   result->status != NIS_S_SUCCESS) ||
+	  result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ ||
+	  strcmp (result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type,
+		  "services_tbl") != 0 ||
+	  result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 4)
+	sprintf (buf, "[cname=%s,proto=%s],services.org_dir", name, protocol);
+      else
+	sprintf (buf, "[cname=%s,proto=%s],services.org_dir",
+		 NISENTRYVAL (0, 0, result), protocol);
+
+      nis_freeresult (result);
+      result = nis_list (buf, EXPAND_NAME, NULL, NULL);
+
+      if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	{
+	  enum nss_status status = niserr2nss (result->status);
+
+	  nis_freeresult (result);
+	  return status;
+	}
+
+      parse_res = _nss_nisplus_parse_servent (result, serv, buffer, buflen);
+
+      nis_freeresult (result);
+
+      if (parse_res)
+	return NSS_STATUS_SUCCESS;
+
+      if (!parse_res && errno == ERANGE)
+	return NSS_STATUS_TRYAGAIN;
+      else
+	return NSS_STATUS_NOTFOUND;
+    }
+}
+
+enum nss_status
+_nss_nisplus_getservbynumber_r (const int number, const char *protocol,
+				struct servent *serv,
+				char *buffer, size_t buflen)
+{
+  int parse_res;
+  nis_result *result;
+  char buf[60 + strlen (protocol)];
+
+  if (protocol == NULL)
+    {
+      __set_errno (EINVAL);
+      return NSS_STATUS_NOTFOUND;
+    }
+
+  snprintf (buf, sizeof (buf), "[number=%d,proto=%s],services.org_dir",
+	    number, protocol);
+
+  result = nis_list (buf, EXPAND_NAME, NULL, NULL);
+
+  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+    {
+      enum nss_status status = niserr2nss (result->status);
+
+      nis_freeresult (result);
+      return status;
+    }
+
+  parse_res = _nss_nisplus_parse_servent (result, serv, buffer, buflen);
+
+  nis_freeresult (result);
+
+  if (parse_res)
+    return NSS_STATUS_SUCCESS;
+
+  if (!parse_res && errno == ERANGE)
+    return NSS_STATUS_TRYAGAIN;
+  else
+    return NSS_STATUS_NOTFOUND;
+}
diff --git a/nis/nss_nisplus/nisplus-spwd.c b/nis/nss_nisplus/nisplus-spwd.c
new file mode 100644
index 0000000000..ec4b5b3340
--- /dev/null
+++ b/nis/nss_nisplus/nisplus-spwd.c
@@ -0,0 +1,262 @@
+/* Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
+
+   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 <nss.h>
+#include <errno.h>
+#include <shadow.h>
+#include <string.h>
+#include <libc-lock.h>
+#include <rpcsvc/nis.h>
+#include <rpcsvc/nislib.h>
+
+#include "nss-nisplus.h"
+
+__libc_lock_define_initialized (static, lock)
+
+static nis_result *result = NULL;
+static nis_name *names = NULL;
+
+#define NISENTRYVAL(idx,col,res) \
+        ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val)
+
+#define NISENTRYLEN(idx,col,res) \
+        ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len)
+
+static int
+_nss_nisplus_parse_spent (nis_result *result, struct spwd *sp,
+			  char *buffer, size_t buflen)
+{
+  char *first_unused = buffer;
+  size_t room_left = buflen;
+  char *line, *cp;
+
+  if (result == NULL)
+    return -1;
+
+  if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) ||
+      result->objects.objects_len != 1 ||
+      result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ ||
+      strcmp (result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type,
+	      "passwd_tbl") != 0 ||
+      result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 8)
+    return -1;
+
+  if (NISENTRYLEN(0, 0, result) >= room_left)
+    {
+      /* The line is too long for our buffer.  */
+    no_more_room:
+      __set_errno (ERANGE);
+      return -1;
+    }
+
+  strncpy (first_unused, NISENTRYVAL (0, 0, result),
+	   NISENTRYLEN (0, 0, result));
+  first_unused[NISENTRYLEN(0, 0, result)] = '\0';
+  sp->sp_namp = first_unused;
+  room_left -= (strlen (first_unused) +1);
+  first_unused += strlen (first_unused) +1;
+
+  if (NISENTRYLEN(0, 1, result) >= room_left)
+    goto no_more_room;
+
+  strncpy (first_unused, NISENTRYVAL (0, 1, result),
+	   NISENTRYLEN (0, 1, result));
+  first_unused[NISENTRYLEN(0, 1, result)] = '\0';
+  sp->sp_pwdp = first_unused;
+  room_left -= (strlen (first_unused) +1);
+  first_unused += strlen (first_unused) +1;
+
+  sp->sp_lstchg = sp->sp_min = sp->sp_max = sp->sp_warn = sp->sp_inact =
+    sp->sp_expire = sp->sp_flag = -1;
+
+  line = NISENTRYVAL (0, 7, result);
+  cp = strchr (line, ':');
+  if (cp == NULL)
+    return 0;
+  *cp++ = '\0';
+  sp->sp_lstchg = atoi (line);
+
+  line = cp;
+  cp = strchr (line, ':');
+  if (cp == NULL)
+    return 0;
+  *cp++ = '\0';
+  sp->sp_min = atoi(line);
+
+  line = cp;
+  cp = strchr (line, ':');
+  if (cp == NULL)
+    return 0;
+  *cp++ = '\0';
+  sp->sp_max = atoi(line);
+
+  line = cp;
+  cp = strchr (line, ':');
+  if (cp == NULL)
+    return 0;
+  *cp++ = '\0';
+  sp->sp_warn = atoi(line);
+
+  line = cp;
+  cp = strchr (line, ':');
+  if (cp == NULL)
+    return 0;
+  *cp++ = '\0';
+  sp->sp_inact = atoi(line);
+
+  line = cp;
+  cp = strchr (line, ':');
+  if (cp == NULL)
+    return 0;
+  *cp++ = '\0';
+  sp->sp_expire = atoi(line);
+
+  line = cp;
+  if (line == NULL)
+    return 0;
+  sp->sp_flag = atoi(line);
+
+  return 1;
+}
+
+enum nss_status
+_nss_nisplus_setspent (void)
+{
+  __libc_lock_lock (lock);
+
+  if (result)
+    nis_freeresult (result);
+  result = NULL;
+  if (names)
+    {
+      nis_freenames (names);
+      names = NULL;
+    }
+
+  __libc_lock_unlock (lock);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_endspent (void)
+{
+  __libc_lock_lock (lock);
+
+  if (result)
+    nis_freeresult (result);
+  result = NULL;
+  if (names)
+    {
+      nis_freenames (names);
+      names = NULL;
+    }
+
+  __libc_lock_unlock (lock);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+static enum nss_status
+internal_nisplus_getspent_r (struct spwd *sp, char *buffer, size_t buflen)
+{
+  int parse_res;
+
+  /* Get the next entry until we found a correct one. */
+  do
+    {
+      if (result == NULL)
+	{
+	  names = nis_getnames ("passwd.org_dir");
+	  if (names == NULL || names[0] == NULL)
+	    return NSS_STATUS_UNAVAIL;
+
+	  result = nis_first_entry (names[0]);
+	  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	    return niserr2nss (result->status);
+	}
+      else
+	{
+	  nis_result *res;
+
+	  res = nis_next_entry (names[0], &result->cookie);
+	  nis_freeresult (result);
+	  result = res;
+	  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	    return niserr2nss (result->status);
+	}
+
+      parse_res = _nss_nisplus_parse_spent (result, sp, buffer, buflen);
+    } while (!parse_res);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_getspent_r (struct spwd *result, char *buffer, size_t buflen)
+{
+  int status;
+
+  __libc_lock_lock (lock);
+
+  status = internal_nisplus_getspent_r (result, buffer, buflen);
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+enum nss_status
+_nss_nisplus_getspnam_r (const char *name, struct spwd *sp,
+		     char *buffer, size_t buflen)
+{
+  int parse_res;
+
+  if (name == NULL || strlen (name) > 8)
+    return NSS_STATUS_NOTFOUND;
+  else
+    {
+      nis_result *result;
+      char buf[strlen (name) + 24];
+
+      sprintf (buf, "[name=%s],passwd.org_dir", name);
+
+      result = nis_list (buf, EXPAND_NAME, NULL, NULL);
+
+      if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	{
+	  enum nss_status status = niserr2nss (result->status);
+
+	  nis_freeresult (result);
+	  return status;
+	}
+
+      parse_res = _nss_nisplus_parse_spent (result, sp, buffer, buflen);
+
+      nis_freeresult (result);
+
+      if (parse_res)
+	return NSS_STATUS_SUCCESS;
+
+      if (!parse_res && errno == ERANGE)
+	return NSS_STATUS_TRYAGAIN;
+      else
+	return NSS_STATUS_NOTFOUND;
+    }
+}
diff --git a/nis/rpcsvc/nis.h b/nis/rpcsvc/nis.h
new file mode 100644
index 0000000000..c2c5319abd
--- /dev/null
+++ b/nis/rpcsvc/nis.h
@@ -0,0 +1,1008 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+#ifndef _NIS_H_RPCGEN
+#define _NIS_H_RPCGEN
+
+#include <rpc/rpc.h>
+
+/*
+ *	nis.h
+ *
+ *	This file is the main include file for NIS clients. It contains
+ *	both the client library function defines and the various data
+ * 	structures used by the NIS service. It includes the file nis_tags.h
+ *	which defines the tag values. This allows the tags to change without
+ *	having to change the nis.x file.
+ *
+ *	NOTE : DO NOT EDIT THIS FILE! It is automatically generated when
+ *	       rpcgen is run on the nis.x file. Note that there is a
+ *	       simple sed script to remove some unneeded lines. (See the
+ *	       Makefile target nis.h)
+ *
+ */
+#include <rpcsvc/nis_tags.h>
+#include <rpc/xdr.h>
+#pragma ident	"@(#)nis_object.x	1.7	92/07/14 SMI"
+
+#ifndef __nis_object_h
+#define __nis_object_h
+
+#define NIS_MAXSTRINGLEN 255
+#define NIS_MAXNAMELEN 1024
+#define NIS_MAXATTRNAME 32
+#define NIS_MAXATTRVAL 2048
+#define NIS_MAXCOLUMNS 64
+#define NIS_MAXATTR 16
+#define NIS_MAXPATH 1024
+#define NIS_MAXREPLICAS 128
+#define NIS_MAXLINKS 16
+#define NIS_PK_NONE 0
+#define NIS_PK_DH 1
+#define NIS_PK_RSA 2
+#define NIS_PK_KERB 3
+
+struct nis_attr {
+	char *zattr_ndx;
+	struct {
+		u_int zattr_val_len;
+		char *zattr_val_val;
+	} zattr_val;
+};
+typedef struct nis_attr nis_attr;
+#ifdef __cplusplus
+extern "C" bool_t xdr_nis_attr(XDR *, nis_attr*);
+#elif __STDC__
+extern  bool_t xdr_nis_attr(XDR *, nis_attr*);
+#else /* Old Style C */
+bool_t xdr_nis_attr();
+#endif /* Old Style C */
+
+
+typedef char *nis_name;
+#ifdef __cplusplus
+extern "C" bool_t xdr_nis_name(XDR *, nis_name*);
+#elif __STDC__
+extern  bool_t xdr_nis_name(XDR *, nis_name*);
+#else /* Old Style C */
+bool_t xdr_nis_name();
+#endif /* Old Style C */
+
+
+enum zotypes {
+	BOGUS_OBJ = 0,
+	NO_OBJ = 1,
+	DIRECTORY_OBJ = 2,
+	GROUP_OBJ = 3,
+	TABLE_OBJ = 4,
+	ENTRY_OBJ = 5,
+	LINK_OBJ = 6,
+	PRIVATE_OBJ = 7,
+};
+typedef enum zotypes zotypes;
+#ifdef __cplusplus
+extern "C" bool_t xdr_zotypes(XDR *, zotypes*);
+#elif __STDC__
+extern  bool_t xdr_zotypes(XDR *, zotypes*);
+#else /* Old Style C */
+bool_t xdr_zotypes();
+#endif /* Old Style C */
+
+
+enum nstype {
+	UNKNOWN = 0,
+	NIS = 1,
+	SUNYP = 2,
+	IVY = 3,
+	DNS = 4,
+	X500 = 5,
+	DNANS = 6,
+	XCHS = 7,
+	CDS = 8,
+};
+typedef enum nstype nstype;
+#ifdef __cplusplus
+extern "C" bool_t xdr_nstype(XDR *, nstype*);
+#elif __STDC__
+extern  bool_t xdr_nstype(XDR *, nstype*);
+#else /* Old Style C */
+bool_t xdr_nstype();
+#endif /* Old Style C */
+
+
+struct oar_mask {
+	u_long oa_rights;
+	zotypes oa_otype;
+};
+typedef struct oar_mask oar_mask;
+#ifdef __cplusplus
+extern "C" bool_t xdr_oar_mask(XDR *, oar_mask*);
+#elif __STDC__
+extern  bool_t xdr_oar_mask(XDR *, oar_mask*);
+#else /* Old Style C */
+bool_t xdr_oar_mask();
+#endif /* Old Style C */
+
+
+struct endpoint {
+	char *uaddr;
+	char *family;
+	char *proto;
+};
+typedef struct endpoint endpoint;
+#ifdef __cplusplus
+extern "C" bool_t xdr_endpoint(XDR *, endpoint*);
+#elif __STDC__
+extern  bool_t xdr_endpoint(XDR *, endpoint*);
+#else /* Old Style C */
+bool_t xdr_endpoint();
+#endif /* Old Style C */
+
+
+struct nis_server {
+	nis_name name;
+	struct {
+		u_int ep_len;
+		endpoint *ep_val;
+	} ep;
+	u_long key_type;
+	netobj pkey;
+};
+typedef struct nis_server nis_server;
+#ifdef __cplusplus
+extern "C" bool_t xdr_nis_server(XDR *, nis_server*);
+#elif __STDC__
+extern  bool_t xdr_nis_server(XDR *, nis_server*);
+#else /* Old Style C */
+bool_t xdr_nis_server();
+#endif /* Old Style C */
+
+
+struct directory_obj {
+	nis_name do_name;
+	nstype do_type;
+	struct {
+		u_int do_servers_len;
+		nis_server *do_servers_val;
+	} do_servers;
+	u_long do_ttl;
+	struct {
+		u_int do_armask_len;
+		oar_mask *do_armask_val;
+	} do_armask;
+};
+typedef struct directory_obj directory_obj;
+#ifdef __cplusplus
+extern "C" bool_t xdr_directory_obj(XDR *, directory_obj*);
+#elif __STDC__
+extern  bool_t xdr_directory_obj(XDR *, directory_obj*);
+#else /* Old Style C */
+bool_t xdr_directory_obj();
+#endif /* Old Style C */
+
+#define EN_BINARY 1
+#define EN_CRYPT 2
+#define EN_XDR 4
+#define EN_MODIFIED 8
+#define EN_ASN1 64
+
+struct entry_col {
+	u_long ec_flags;
+	struct {
+		u_int ec_value_len;
+		char *ec_value_val;
+	} ec_value;
+};
+typedef struct entry_col entry_col;
+#ifdef __cplusplus
+extern "C" bool_t xdr_entry_col(XDR *, entry_col*);
+#elif __STDC__
+extern  bool_t xdr_entry_col(XDR *, entry_col*);
+#else /* Old Style C */
+bool_t xdr_entry_col();
+#endif /* Old Style C */
+
+
+struct entry_obj {
+	char *en_type;
+	struct {
+		u_int en_cols_len;
+		entry_col *en_cols_val;
+	} en_cols;
+};
+typedef struct entry_obj entry_obj;
+#ifdef __cplusplus
+extern "C" bool_t xdr_entry_obj(XDR *, entry_obj*);
+#elif __STDC__
+extern  bool_t xdr_entry_obj(XDR *, entry_obj*);
+#else /* Old Style C */
+bool_t xdr_entry_obj();
+#endif /* Old Style C */
+
+
+struct group_obj {
+	u_long gr_flags;
+	struct {
+		u_int gr_members_len;
+		nis_name *gr_members_val;
+	} gr_members;
+};
+typedef struct group_obj group_obj;
+#ifdef __cplusplus
+extern "C" bool_t xdr_group_obj(XDR *, group_obj*);
+#elif __STDC__
+extern  bool_t xdr_group_obj(XDR *, group_obj*);
+#else /* Old Style C */
+bool_t xdr_group_obj();
+#endif /* Old Style C */
+
+
+struct link_obj {
+	zotypes li_rtype;
+	struct {
+		u_int li_attrs_len;
+		nis_attr *li_attrs_val;
+	} li_attrs;
+	nis_name li_name;
+};
+typedef struct link_obj link_obj;
+#ifdef __cplusplus
+extern "C" bool_t xdr_link_obj(XDR *, link_obj*);
+#elif __STDC__
+extern  bool_t xdr_link_obj(XDR *, link_obj*);
+#else /* Old Style C */
+bool_t xdr_link_obj();
+#endif /* Old Style C */
+
+#define TA_BINARY 1
+#define TA_CRYPT 2
+#define TA_XDR 4
+#define TA_SEARCHABLE 8
+#define TA_CASE 16
+#define TA_MODIFIED 32
+#define TA_ASN1 64
+
+struct table_col {
+	char *tc_name;
+	u_long tc_flags;
+	u_long tc_rights;
+};
+typedef struct table_col table_col;
+#ifdef __cplusplus
+extern "C" bool_t xdr_table_col(XDR *, table_col*);
+#elif __STDC__
+extern  bool_t xdr_table_col(XDR *, table_col*);
+#else /* Old Style C */
+bool_t xdr_table_col();
+#endif /* Old Style C */
+
+
+struct table_obj {
+	char *ta_type;
+	int ta_maxcol;
+	u_char ta_sep;
+	struct {
+		u_int ta_cols_len;
+		table_col *ta_cols_val;
+	} ta_cols;
+	char *ta_path;
+};
+typedef struct table_obj table_obj;
+#ifdef __cplusplus
+extern "C" bool_t xdr_table_obj(XDR *, table_obj*);
+#elif __STDC__
+extern  bool_t xdr_table_obj(XDR *, table_obj*);
+#else /* Old Style C */
+bool_t xdr_table_obj();
+#endif /* Old Style C */
+
+
+struct objdata {
+	zotypes zo_type;
+	union {
+		struct directory_obj di_data;
+		struct group_obj gr_data;
+		struct table_obj ta_data;
+		struct entry_obj en_data;
+		struct link_obj li_data;
+		struct {
+			u_int po_data_len;
+			char *po_data_val;
+		} po_data;
+	} objdata_u;
+};
+typedef struct objdata objdata;
+#ifdef __cplusplus
+extern "C" bool_t xdr_objdata(XDR *, objdata*);
+#elif __STDC__
+extern  bool_t xdr_objdata(XDR *, objdata*);
+#else /* Old Style C */
+bool_t xdr_objdata();
+#endif /* Old Style C */
+
+
+struct nis_oid {
+	u_long ctime;
+	u_long mtime;
+};
+typedef struct nis_oid nis_oid;
+#ifdef __cplusplus
+extern "C" bool_t xdr_nis_oid(XDR *, nis_oid*);
+#elif __STDC__
+extern  bool_t xdr_nis_oid(XDR *, nis_oid*);
+#else /* Old Style C */
+bool_t xdr_nis_oid();
+#endif /* Old Style C */
+
+
+struct nis_object {
+	nis_oid zo_oid;
+	nis_name zo_name;
+	nis_name zo_owner;
+	nis_name zo_group;
+	nis_name zo_domain;
+	u_long zo_access;
+	u_long zo_ttl;
+	objdata zo_data;
+};
+typedef struct nis_object nis_object;
+#ifdef __cplusplus
+extern "C" bool_t xdr_nis_object(XDR *, nis_object*);
+#elif __STDC__
+extern  bool_t xdr_nis_object(XDR *, nis_object*);
+#else /* Old Style C */
+bool_t xdr_nis_object();
+#endif /* Old Style C */
+
+
+#endif /* if __nis_object_h */
+
+
+enum nis_error {
+	NIS_SUCCESS = 0,
+	NIS_S_SUCCESS = 1,
+	NIS_NOTFOUND = 2,
+	NIS_S_NOTFOUND = 3,
+	NIS_CACHEEXPIRED = 4,
+	NIS_NAMEUNREACHABLE = 5,
+	NIS_UNKNOWNOBJ = 6,
+	NIS_TRYAGAIN = 7,
+	NIS_SYSTEMERROR = 8,
+	NIS_CHAINBROKEN = 9,
+	NIS_PERMISSION = 10,
+	NIS_NOTOWNER = 11,
+	NIS_NOT_ME = 12,
+	NIS_NOMEMORY = 13,
+	NIS_NAMEEXISTS = 14,
+	NIS_NOTMASTER = 15,
+	NIS_INVALIDOBJ = 16,
+	NIS_BADNAME = 17,
+	NIS_NOCALLBACK = 18,
+	NIS_CBRESULTS = 19,
+	NIS_NOSUCHNAME = 20,
+	NIS_NOTUNIQUE = 21,
+	NIS_IBMODERROR = 22,
+	NIS_NOSUCHTABLE = 23,
+	NIS_TYPEMISMATCH = 24,
+	NIS_LINKNAMEERROR = 25,
+	NIS_PARTIAL = 26,
+	NIS_TOOMANYATTRS = 27,
+	NIS_RPCERROR = 28,
+	NIS_BADATTRIBUTE = 29,
+	NIS_NOTSEARCHABLE = 30,
+	NIS_CBERROR = 31,
+	NIS_FOREIGNNS = 32,
+	NIS_BADOBJECT = 33,
+	NIS_NOTSAMEOBJ = 34,
+	NIS_MODFAIL = 35,
+	NIS_BADREQUEST = 36,
+	NIS_NOTEMPTY = 37,
+	NIS_COLDSTART_ERR = 38,
+	NIS_RESYNC = 39,
+	NIS_FAIL = 40,
+	NIS_UNAVAIL = 41,
+	NIS_RES2BIG = 42,
+	NIS_SRVAUTH = 43,
+	NIS_CLNTAUTH = 44,
+	NIS_NOFILESPACE = 45,
+	NIS_NOPROC = 46,
+	NIS_DUMPLATER = 47,
+};
+typedef enum nis_error nis_error;
+#ifdef __cplusplus
+extern "C" bool_t xdr_nis_error(XDR *, nis_error*);
+#elif __STDC__
+extern  bool_t xdr_nis_error(XDR *, nis_error*);
+#else /* Old Style C */
+bool_t xdr_nis_error();
+#endif /* Old Style C */
+
+
+struct nis_result {
+	nis_error status;
+	struct {
+		u_int objects_len;
+		nis_object *objects_val;
+	} objects;
+	netobj cookie;
+	u_long zticks;
+	u_long dticks;
+	u_long aticks;
+	u_long cticks;
+};
+typedef struct nis_result nis_result;
+#ifdef __cplusplus
+extern "C" bool_t xdr_nis_result(XDR *, nis_result*);
+#elif __STDC__
+extern  bool_t xdr_nis_result(XDR *, nis_result*);
+#else /* Old Style C */
+bool_t xdr_nis_result();
+#endif /* Old Style C */
+
+
+struct ns_request {
+	nis_name ns_name;
+	struct {
+		u_int ns_object_len;
+		nis_object *ns_object_val;
+	} ns_object;
+};
+typedef struct ns_request ns_request;
+#ifdef __cplusplus
+extern "C" bool_t xdr_ns_request(XDR *, ns_request*);
+#elif __STDC__
+extern  bool_t xdr_ns_request(XDR *, ns_request*);
+#else /* Old Style C */
+bool_t xdr_ns_request();
+#endif /* Old Style C */
+
+
+struct ib_request {
+	nis_name ibr_name;
+	struct {
+		u_int ibr_srch_len;
+		nis_attr *ibr_srch_val;
+	} ibr_srch;
+	u_long ibr_flags;
+	struct {
+		u_int ibr_obj_len;
+		nis_object *ibr_obj_val;
+	} ibr_obj;
+	struct {
+		u_int ibr_cbhost_len;
+		nis_server *ibr_cbhost_val;
+	} ibr_cbhost;
+	u_long ibr_bufsize;
+	netobj ibr_cookie;
+};
+typedef struct ib_request ib_request;
+#ifdef __cplusplus
+extern "C" bool_t xdr_ib_request(XDR *, ib_request*);
+#elif __STDC__
+extern  bool_t xdr_ib_request(XDR *, ib_request*);
+#else /* Old Style C */
+bool_t xdr_ib_request();
+#endif /* Old Style C */
+
+
+struct ping_args {
+	nis_name dir;
+	u_long stamp;
+};
+typedef struct ping_args ping_args;
+#ifdef __cplusplus
+extern "C" bool_t xdr_ping_args(XDR *, ping_args*);
+#elif __STDC__
+extern  bool_t xdr_ping_args(XDR *, ping_args*);
+#else /* Old Style C */
+bool_t xdr_ping_args();
+#endif /* Old Style C */
+
+
+enum log_entry_t {
+	LOG_NOP = 0,
+	ADD_NAME = 1,
+	REM_NAME = 2,
+	MOD_NAME_OLD = 3,
+	MOD_NAME_NEW = 4,
+	ADD_IBASE = 5,
+	REM_IBASE = 6,
+	MOD_IBASE = 7,
+	UPD_STAMP = 8,
+};
+typedef enum log_entry_t log_entry_t;
+#ifdef __cplusplus
+extern "C" bool_t xdr_log_entry_t(XDR *, log_entry_t*);
+#elif __STDC__
+extern  bool_t xdr_log_entry_t(XDR *, log_entry_t*);
+#else /* Old Style C */
+bool_t xdr_log_entry_t();
+#endif /* Old Style C */
+
+
+struct log_entry {
+	u_long le_time;
+	log_entry_t le_type;
+	nis_name le_princp;
+	nis_name le_name;
+	struct {
+		u_int le_attrs_len;
+		nis_attr *le_attrs_val;
+	} le_attrs;
+	nis_object le_object;
+};
+typedef struct log_entry log_entry;
+#ifdef __cplusplus
+extern "C" bool_t xdr_log_entry(XDR *, log_entry*);
+#elif __STDC__
+extern  bool_t xdr_log_entry(XDR *, log_entry*);
+#else /* Old Style C */
+bool_t xdr_log_entry();
+#endif /* Old Style C */
+
+
+struct log_result {
+	nis_error lr_status;
+	netobj lr_cookie;
+	struct {
+		u_int lr_entries_len;
+		log_entry *lr_entries_val;
+	} lr_entries;
+};
+typedef struct log_result log_result;
+#ifdef __cplusplus
+extern "C" bool_t xdr_log_result(XDR *, log_result*);
+#elif __STDC__
+extern  bool_t xdr_log_result(XDR *, log_result*);
+#else /* Old Style C */
+bool_t xdr_log_result();
+#endif /* Old Style C */
+
+
+struct cp_result {
+	nis_error cp_status;
+	u_long cp_zticks;
+	u_long cp_dticks;
+};
+typedef struct cp_result cp_result;
+#ifdef __cplusplus
+extern "C" bool_t xdr_cp_result(XDR *, cp_result*);
+#elif __STDC__
+extern  bool_t xdr_cp_result(XDR *, cp_result*);
+#else /* Old Style C */
+bool_t xdr_cp_result();
+#endif /* Old Style C */
+
+
+struct nis_tag {
+	u_long tag_type;
+	char *tag_val;
+};
+typedef struct nis_tag nis_tag;
+#ifdef __cplusplus
+extern "C" bool_t xdr_nis_tag(XDR *, nis_tag*);
+#elif __STDC__
+extern  bool_t xdr_nis_tag(XDR *, nis_tag*);
+#else /* Old Style C */
+bool_t xdr_nis_tag();
+#endif /* Old Style C */
+
+
+struct nis_taglist {
+	struct {
+		u_int tags_len;
+		nis_tag *tags_val;
+	} tags;
+};
+typedef struct nis_taglist nis_taglist;
+#ifdef __cplusplus
+extern "C" bool_t xdr_nis_taglist(XDR *, nis_taglist*);
+#elif __STDC__
+extern  bool_t xdr_nis_taglist(XDR *, nis_taglist*);
+#else /* Old Style C */
+bool_t xdr_nis_taglist();
+#endif /* Old Style C */
+
+
+struct dump_args {
+	nis_name da_dir;
+	u_long da_time;
+	struct {
+		u_int da_cbhost_len;
+		nis_server *da_cbhost_val;
+	} da_cbhost;
+};
+typedef struct dump_args dump_args;
+#ifdef __cplusplus
+extern "C" bool_t xdr_dump_args(XDR *, dump_args*);
+#elif __STDC__
+extern  bool_t xdr_dump_args(XDR *, dump_args*);
+#else /* Old Style C */
+bool_t xdr_dump_args();
+#endif /* Old Style C */
+
+
+struct fd_args {
+	nis_name dir_name;
+	nis_name requester;
+};
+typedef struct fd_args fd_args;
+#ifdef __cplusplus
+extern "C" bool_t xdr_fd_args(XDR *, fd_args*);
+#elif __STDC__
+extern  bool_t xdr_fd_args(XDR *, fd_args*);
+#else /* Old Style C */
+bool_t xdr_fd_args();
+#endif /* Old Style C */
+
+
+struct fd_result {
+	nis_error status;
+	nis_name source;
+	struct {
+		u_int dir_data_len;
+		char *dir_data_val;
+	} dir_data;
+	struct {
+		u_int signature_len;
+		char *signature_val;
+	} signature;
+};
+typedef struct fd_result fd_result;
+#ifdef __cplusplus
+extern "C" bool_t xdr_fd_result(XDR *, fd_result*);
+#elif __STDC__
+extern  bool_t xdr_fd_result(XDR *, fd_result*);
+#else /* Old Style C */
+bool_t xdr_fd_result();
+#endif /* Old Style C */
+
+/*
+ * Generic "hash" datastructures, used by all types of hashed data.
+ */
+struct nis_hash_data {
+	nis_name		name;	   /* NIS name of hashed item      */
+	int			keychain;  /* It's hash key (for pop)      */
+	struct nis_hash_data	*next;	   /* Hash collision pointer       */
+	struct nis_hash_data	*prv_item; /* A serial, doubly linked list */
+	struct nis_hash_data	*nxt_item; /* of items in the hash table   */
+};
+typedef struct nis_hash_data NIS_HASH_ITEM;
+
+struct nis_hash_table {
+	NIS_HASH_ITEM	*keys[64];	/* A hash table of items           */
+	NIS_HASH_ITEM	*first;		/* The first "item" in serial list */
+};
+typedef struct nis_hash_table NIS_HASH_TABLE;
+
+/* Structure for storing dynamically allocated static data */
+struct nis_sdata {
+	void	*buf;	/* Memory allocation pointer 	*/
+	u_long	size;	/* Buffer size			*/
+};
+
+/* Generic client creating flags */
+#define ZMH_VC		1
+#define ZMH_DG		2
+#define ZMH_AUTH	4
+
+/* Testing Access rights for objects */
+
+#define NIS_READ_ACC		1
+#define NIS_MODIFY_ACC		2
+#define NIS_CREATE_ACC		4
+#define NIS_DESTROY_ACC	8
+/* Test macros. a == access rights, m == desired rights. */
+#define WORLD(a, m)	(((a) & (m)) != 0)
+#define GROUP(a, m)	(((a) & ((m) << 8)) != 0)
+#define OWNER(a, m)	(((a) & ((m) << 16)) != 0)
+#define NOBODY(a, m)	(((a) & ((m) << 24)) != 0)
+
+#define OATYPE(d, n) (((d)->do_armask.do_armask_val+n)->oa_otype)
+#define OARIGHTS(d, n) (((d)->do_armask.do_armask_val+n)->oa_rights)
+#define WORLD_DEFAULT (NIS_READ_ACC)
+#define GROUP_DEFAULT (NIS_READ_ACC << 8)
+#define OWNER_DEFAULT ((NIS_READ_ACC + NIS_MODIFY_ACC + NIS_CREATE_ACC +\
+			NIS_DESTROY_ACC) << 16)
+#define DEFAULT_RIGHTS (WORLD_DEFAULT | GROUP_DEFAULT | OWNER_DEFAULT)
+
+/* Result manipulation defines ... */
+#define NIS_RES_NUMOBJ(x)	((x)->objects.objects_len)
+#define NIS_RES_OBJECT(x)	((x)->objects.objects_val)
+#define NIS_RES_COOKIE(x)	((x)->cookie)
+#define NIS_RES_STATUS(x)	((x)->status)
+
+/* These defines make getting at the variant part of the object easier. */
+#define TA_data zo_data.objdata_u.ta_data
+#define EN_data zo_data.objdata_u.en_data
+#define DI_data zo_data.objdata_u.di_data
+#define LI_data zo_data.objdata_u.li_data
+#define GR_data zo_data.objdata_u.gr_data
+
+#define __type_of(o) ((o)->zo_data.zo_type)
+
+/* Declarations for the internal subroutines in nislib.c */
+enum name_pos {SAME_NAME, HIGHER_NAME, LOWER_NAME, NOT_SEQUENTIAL, BAD_NAME};
+typedef enum name_pos name_pos;
+
+/*
+ * Defines for getting at column data in entry objects. Because RPCGEN
+ * generates some rather wordy structures, we create some defines that
+ * collapse the needed keystrokes to access a particular value using
+ * these definitions they take an nis_object *, and an int and return
+ * a u_char * for Value, and an int for length.
+ */
+#define ENTRY_VAL(obj, col) (obj)->EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val
+#define ENTRY_LEN(obj, col) (obj)->EN_data.en_cols.en_cols_val[col].ec_value.ec_value_len
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Prototypes, and extern declarations for the NIS library functions. */
+#include <rpcsvc/nislib.h>
+#endif /* __NIS_RPCGEN_H */
+/* EDIT_START */
+
+/*
+ * nis_3.h
+ *
+ * This file contains definitions that are only of interest to the actual
+ * service daemon and client stubs. Normal users of NIS will not include
+ * this file.
+ *
+ * NOTE : This include file is automatically created by a combination
+ * of rpcgen and sed. DO NOT EDIT IT, change the nis.x file instead
+ * and then remake this file.
+ */
+#ifndef __nis_3_h
+#define __nis_3_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define NIS_PROG ((u_long)100300)
+extern struct rpcgen_table nis_prog_3_table[];
+extern int nis_prog_3_nproc;
+#define NIS_VERSION ((u_long)3)
+
+#ifdef __cplusplus
+#define NIS_LOOKUP ((u_long)1)
+extern "C" nis_result * nis_lookup_3(ns_request *, CLIENT *);
+extern "C" nis_result * nis_lookup_3_svc(ns_request *, struct svc_req *);
+#define NIS_ADD ((u_long)2)
+extern "C" nis_result * nis_add_3(ns_request *, CLIENT *);
+extern "C" nis_result * nis_add_3_svc(ns_request *, struct svc_req *);
+#define NIS_MODIFY ((u_long)3)
+extern "C" nis_result * nis_modify_3(ns_request *, CLIENT *);
+extern "C" nis_result * nis_modify_3_svc(ns_request *, struct svc_req *);
+#define NIS_REMOVE ((u_long)4)
+extern "C" nis_result * nis_remove_3(ns_request *, CLIENT *);
+extern "C" nis_result * nis_remove_3_svc(ns_request *, struct svc_req *);
+#define NIS_IBLIST ((u_long)5)
+extern "C" nis_result * nis_iblist_3(ib_request *, CLIENT *);
+extern "C" nis_result * nis_iblist_3_svc(ib_request *, struct svc_req *);
+#define NIS_IBADD ((u_long)6)
+extern "C" nis_result * nis_ibadd_3(ib_request *, CLIENT *);
+extern "C" nis_result * nis_ibadd_3_svc(ib_request *, struct svc_req *);
+#define NIS_IBMODIFY ((u_long)7)
+extern "C" nis_result * nis_ibmodify_3(ib_request *, CLIENT *);
+extern "C" nis_result * nis_ibmodify_3_svc(ib_request *, struct svc_req *);
+#define NIS_IBREMOVE ((u_long)8)
+extern "C" nis_result * nis_ibremove_3(ib_request *, CLIENT *);
+extern "C" nis_result * nis_ibremove_3_svc(ib_request *, struct svc_req *);
+#define NIS_IBFIRST ((u_long)9)
+extern "C" nis_result * nis_ibfirst_3(ib_request *, CLIENT *);
+extern "C" nis_result * nis_ibfirst_3_svc(ib_request *, struct svc_req *);
+#define NIS_IBNEXT ((u_long)10)
+extern "C" nis_result * nis_ibnext_3(ib_request *, CLIENT *);
+extern "C" nis_result * nis_ibnext_3_svc(ib_request *, struct svc_req *);
+#define NIS_FINDDIRECTORY ((u_long)12)
+extern "C" fd_result * nis_finddirectory_3(fd_args *, CLIENT *);
+extern "C" fd_result * nis_finddirectory_3_svc(fd_args *, struct svc_req *);
+#define NIS_STATUS ((u_long)14)
+extern "C" nis_taglist * nis_status_3(nis_taglist *, CLIENT *);
+extern "C" nis_taglist * nis_status_3_svc(nis_taglist *, struct svc_req *);
+#define NIS_DUMPLOG ((u_long)15)
+extern "C" log_result * nis_dumplog_3(dump_args *, CLIENT *);
+extern "C" log_result * nis_dumplog_3_svc(dump_args *, struct svc_req *);
+#define NIS_DUMP ((u_long)16)
+extern "C" log_result * nis_dump_3(dump_args *, CLIENT *);
+extern "C" log_result * nis_dump_3_svc(dump_args *, struct svc_req *);
+#define NIS_CALLBACK ((u_long)17)
+extern "C" bool_t * nis_callback_3(netobj *, CLIENT *);
+extern "C" bool_t * nis_callback_3_svc(netobj *, struct svc_req *);
+#define NIS_CPTIME ((u_long)18)
+extern "C" u_long * nis_cptime_3(nis_name *, CLIENT *);
+extern "C" u_long * nis_cptime_3_svc(nis_name *, struct svc_req *);
+#define NIS_CHECKPOINT ((u_long)19)
+extern "C" cp_result * nis_checkpoint_3(nis_name *, CLIENT *);
+extern "C" cp_result * nis_checkpoint_3_svc(nis_name *, struct svc_req *);
+#define NIS_PING ((u_long)20)
+extern "C" void * nis_ping_3(ping_args *, CLIENT *);
+extern "C" void * nis_ping_3_svc(ping_args *, struct svc_req *);
+#define NIS_SERVSTATE ((u_long)21)
+extern "C" nis_taglist * nis_servstate_3(nis_taglist *, CLIENT *);
+extern "C" nis_taglist * nis_servstate_3_svc(nis_taglist *, struct svc_req *);
+#define NIS_MKDIR ((u_long)22)
+extern "C" nis_error * nis_mkdir_3(nis_name *, CLIENT *);
+extern "C" nis_error * nis_mkdir_3_svc(nis_name *, struct svc_req *);
+#define NIS_RMDIR ((u_long)23)
+extern "C" nis_error * nis_rmdir_3(nis_name *, CLIENT *);
+extern "C" nis_error * nis_rmdir_3_svc(nis_name *, struct svc_req *);
+#define NIS_UPDKEYS ((u_long)24)
+extern "C" nis_error * nis_updkeys_3(nis_name *, CLIENT *);
+extern "C" nis_error * nis_updkeys_3_svc(nis_name *, struct svc_req *);
+
+#elif __STDC__
+#define NIS_LOOKUP ((u_long)1)
+extern  nis_result * nis_lookup_3(ns_request *, CLIENT *);
+extern  nis_result * nis_lookup_3_svc(ns_request *, struct svc_req *);
+#define NIS_ADD ((u_long)2)
+extern  nis_result * nis_add_3(ns_request *, CLIENT *);
+extern  nis_result * nis_add_3_svc(ns_request *, struct svc_req *);
+#define NIS_MODIFY ((u_long)3)
+extern  nis_result * nis_modify_3(ns_request *, CLIENT *);
+extern  nis_result * nis_modify_3_svc(ns_request *, struct svc_req *);
+#define NIS_REMOVE ((u_long)4)
+extern  nis_result * nis_remove_3(ns_request *, CLIENT *);
+extern  nis_result * nis_remove_3_svc(ns_request *, struct svc_req *);
+#define NIS_IBLIST ((u_long)5)
+extern  nis_result * nis_iblist_3(ib_request *, CLIENT *);
+extern  nis_result * nis_iblist_3_svc(ib_request *, struct svc_req *);
+#define NIS_IBADD ((u_long)6)
+extern  nis_result * nis_ibadd_3(ib_request *, CLIENT *);
+extern  nis_result * nis_ibadd_3_svc(ib_request *, struct svc_req *);
+#define NIS_IBMODIFY ((u_long)7)
+extern  nis_result * nis_ibmodify_3(ib_request *, CLIENT *);
+extern  nis_result * nis_ibmodify_3_svc(ib_request *, struct svc_req *);
+#define NIS_IBREMOVE ((u_long)8)
+extern  nis_result * nis_ibremove_3(ib_request *, CLIENT *);
+extern  nis_result * nis_ibremove_3_svc(ib_request *, struct svc_req *);
+#define NIS_IBFIRST ((u_long)9)
+extern  nis_result * nis_ibfirst_3(ib_request *, CLIENT *);
+extern  nis_result * nis_ibfirst_3_svc(ib_request *, struct svc_req *);
+#define NIS_IBNEXT ((u_long)10)
+extern  nis_result * nis_ibnext_3(ib_request *, CLIENT *);
+extern  nis_result * nis_ibnext_3_svc(ib_request *, struct svc_req *);
+#define NIS_FINDDIRECTORY ((u_long)12)
+extern  fd_result * nis_finddirectory_3(fd_args *, CLIENT *);
+extern  fd_result * nis_finddirectory_3_svc(fd_args *, struct svc_req *);
+#define NIS_STATUS ((u_long)14)
+extern  nis_taglist * nis_status_3(nis_taglist *, CLIENT *);
+extern  nis_taglist * nis_status_3_svc(nis_taglist *, struct svc_req *);
+#define NIS_DUMPLOG ((u_long)15)
+extern  log_result * nis_dumplog_3(dump_args *, CLIENT *);
+extern  log_result * nis_dumplog_3_svc(dump_args *, struct svc_req *);
+#define NIS_DUMP ((u_long)16)
+extern  log_result * nis_dump_3(dump_args *, CLIENT *);
+extern  log_result * nis_dump_3_svc(dump_args *, struct svc_req *);
+#define NIS_CALLBACK ((u_long)17)
+extern  bool_t * nis_callback_3(netobj *, CLIENT *);
+extern  bool_t * nis_callback_3_svc(netobj *, struct svc_req *);
+#define NIS_CPTIME ((u_long)18)
+extern  u_long * nis_cptime_3(nis_name *, CLIENT *);
+extern  u_long * nis_cptime_3_svc(nis_name *, struct svc_req *);
+#define NIS_CHECKPOINT ((u_long)19)
+extern  cp_result * nis_checkpoint_3(nis_name *, CLIENT *);
+extern  cp_result * nis_checkpoint_3_svc(nis_name *, struct svc_req *);
+#define NIS_PING ((u_long)20)
+extern  void * nis_ping_3(ping_args *, CLIENT *);
+extern  void * nis_ping_3_svc(ping_args *, struct svc_req *);
+#define NIS_SERVSTATE ((u_long)21)
+extern  nis_taglist * nis_servstate_3(nis_taglist *, CLIENT *);
+extern  nis_taglist * nis_servstate_3_svc(nis_taglist *, struct svc_req *);
+#define NIS_MKDIR ((u_long)22)
+extern  nis_error * nis_mkdir_3(nis_name *, CLIENT *);
+extern  nis_error * nis_mkdir_3_svc(nis_name *, struct svc_req *);
+#define NIS_RMDIR ((u_long)23)
+extern  nis_error * nis_rmdir_3(nis_name *, CLIENT *);
+extern  nis_error * nis_rmdir_3_svc(nis_name *, struct svc_req *);
+#define NIS_UPDKEYS ((u_long)24)
+extern  nis_error * nis_updkeys_3(nis_name *, CLIENT *);
+extern  nis_error * nis_updkeys_3_svc(nis_name *, struct svc_req *);
+
+#else /* Old Style C */
+#define NIS_LOOKUP ((u_long)1)
+extern  nis_result * nis_lookup_3();
+extern  nis_result * nis_lookup_3_svc();
+#define NIS_ADD ((u_long)2)
+extern  nis_result * nis_add_3();
+extern  nis_result * nis_add_3_svc();
+#define NIS_MODIFY ((u_long)3)
+extern  nis_result * nis_modify_3();
+extern  nis_result * nis_modify_3_svc();
+#define NIS_REMOVE ((u_long)4)
+extern  nis_result * nis_remove_3();
+extern  nis_result * nis_remove_3_svc();
+#define NIS_IBLIST ((u_long)5)
+extern  nis_result * nis_iblist_3();
+extern  nis_result * nis_iblist_3_svc();
+#define NIS_IBADD ((u_long)6)
+extern  nis_result * nis_ibadd_3();
+extern  nis_result * nis_ibadd_3_svc();
+#define NIS_IBMODIFY ((u_long)7)
+extern  nis_result * nis_ibmodify_3();
+extern  nis_result * nis_ibmodify_3_svc();
+#define NIS_IBREMOVE ((u_long)8)
+extern  nis_result * nis_ibremove_3();
+extern  nis_result * nis_ibremove_3_svc();
+#define NIS_IBFIRST ((u_long)9)
+extern  nis_result * nis_ibfirst_3();
+extern  nis_result * nis_ibfirst_3_svc();
+#define NIS_IBNEXT ((u_long)10)
+extern  nis_result * nis_ibnext_3();
+extern  nis_result * nis_ibnext_3_svc();
+#define NIS_FINDDIRECTORY ((u_long)12)
+extern  fd_result * nis_finddirectory_3();
+extern  fd_result * nis_finddirectory_3_svc();
+#define NIS_STATUS ((u_long)14)
+extern  nis_taglist * nis_status_3();
+extern  nis_taglist * nis_status_3_svc();
+#define NIS_DUMPLOG ((u_long)15)
+extern  log_result * nis_dumplog_3();
+extern  log_result * nis_dumplog_3_svc();
+#define NIS_DUMP ((u_long)16)
+extern  log_result * nis_dump_3();
+extern  log_result * nis_dump_3_svc();
+#define NIS_CALLBACK ((u_long)17)
+extern  bool_t * nis_callback_3();
+extern  bool_t * nis_callback_3_svc();
+#define NIS_CPTIME ((u_long)18)
+extern  u_long * nis_cptime_3();
+extern  u_long * nis_cptime_3_svc();
+#define NIS_CHECKPOINT ((u_long)19)
+extern  cp_result * nis_checkpoint_3();
+extern  cp_result * nis_checkpoint_3_svc();
+#define NIS_PING ((u_long)20)
+extern  void * nis_ping_3();
+extern  void * nis_ping_3_svc();
+#define NIS_SERVSTATE ((u_long)21)
+extern  nis_taglist * nis_servstate_3();
+extern  nis_taglist * nis_servstate_3_svc();
+#define NIS_MKDIR ((u_long)22)
+extern  nis_error * nis_mkdir_3();
+extern  nis_error * nis_mkdir_3_svc();
+#define NIS_RMDIR ((u_long)23)
+extern  nis_error * nis_rmdir_3();
+extern  nis_error * nis_rmdir_3_svc();
+#define NIS_UPDKEYS ((u_long)24)
+extern  nis_error * nis_updkeys_3();
+extern  nis_error * nis_updkeys_3_svc();
+#endif /* Old Style C */
+struct rpcgen_table {
+	char	*(*proc)();
+	xdrproc_t	xdr_arg;
+	unsigned	len_arg;
+	xdrproc_t	xdr_res;
+	unsigned	len_res;
+};
+
+#endif /* !_NIS_H_RPCGEN */
diff --git a/nis/rpcsvc/nis.x b/nis/rpcsvc/nis.x
new file mode 100644
index 0000000000..625ed57f10
--- /dev/null
+++ b/nis/rpcsvc/nis.x
@@ -0,0 +1,446 @@
+%/*
+% * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+% * unrestricted use provided that this legend is included on all tape
+% * media and as a part of the software program in whole or part.  Users
+% * may copy or modify Sun RPC without charge, but are not authorized
+% * to license or distribute it to anyone else except as part of a product or
+% * program developed by the user or with the express written consent of
+% * Sun Microsystems, Inc.
+% *
+% * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+% * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+% * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+% *
+% * Sun RPC is provided with no support and without any obligation on the
+% * part of Sun Microsystems, Inc. to assist in its use, correction,
+% * modification or enhancement.
+% *
+% * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+% * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+% * OR ANY PART THEREOF.
+% *
+% * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+% * or profits or other special, indirect and consequential damages, even if
+% * Sun has been advised of the possibility of such damages.
+% *
+% * Sun Microsystems, Inc.
+% * 2550 Garcia Avenue
+% * Mountain View, California  94043
+% */
+
+/* 
+ * From 4.1 : @(#)nis.x	1.61 Copyright 1989 Sun Microsystems
+ *
+ * RPC Language Protocol description file for NIS Plus
+ * This version : 1.61
+ * Last Modified : 3/19/91
+ */
+#ifdef RPC_HDR
+%/*
+% *	nis.h
+% *
+% *	This file is the main include file for NIS clients. It contains
+% *	both the client library function defines and the various data
+% * 	structures used by the NIS service. It includes the file nis_tags.h
+% *	which defines the tag values. This allows the tags to change without
+% *	having to change the nis.x file.
+% * 	
+% *	NOTE : DO NOT EDIT THIS FILE! It is automatically generated when
+% *	       rpcgen is run on the nis.x file. Note that there is a 
+% *	       simple sed script to remove some unneeded lines. (See the
+% *	       Makefile target nis.h)
+% *
+% */
+%#include <rpcsvc/nis_tags.h>
+#endif
+
+/* This gets stuffed into the source files. */
+#if RPC_HDR
+%#include <rpc/xdr.h>
+#endif
+#if RPC_SVC
+%#include "nis_svc.h"
+#endif
+
+/* Include the RPC Language description of NIS objects */
+#include "nis_object.x"
+
+/* Errors  that can be returned by the service */
+enum nis_error {
+	NIS_SUCCESS = 0,	/* A-ok, let's rock n roll 	*/
+	NIS_S_SUCCESS = 1,	/* Name found (maybe)	   	*/
+	NIS_NOTFOUND = 2,	/* Name definitely not found 	*/
+	NIS_S_NOTFOUND = 3,	/* Name maybe not found 	*/
+	NIS_CACHEEXPIRED = 4,	/* Name exists but cache out of date */
+	NIS_NAMEUNREACHABLE = 5, /* Can't get there from here */
+	NIS_UNKNOWNOBJ = 6,	/* Object type is bogus */
+	NIS_TRYAGAIN = 7,	/* I'm busy, call back */
+	NIS_SYSTEMERROR = 8,	/* Out of band failure */
+	NIS_CHAINBROKEN = 9,	/* First/Next warning */
+	NIS_PERMISSION = 10,	/* Not enough permission to access */
+	NIS_NOTOWNER = 11,	/* You don't own it, sorry */
+	NIS_NOT_ME = 12,	/* I don't serve this name */
+	NIS_NOMEMORY = 13,	/* Outta VM! Help! */
+	NIS_NAMEEXISTS = 14,	/* Can't create over another name */
+	NIS_NOTMASTER = 15,	/* I'm justa secondaray, don't ask me */
+	NIS_INVALIDOBJ = 16,	/* Object is broken somehow */
+	NIS_BADNAME = 17,	/* Unparsable name */
+	NIS_NOCALLBACK = 18,	/* Couldn't talk to call back proc */
+	NIS_CBRESULTS = 19,	/* Results being called back to you */
+	NIS_NOSUCHNAME = 20,	/* Name unknown */
+	NIS_NOTUNIQUE = 21,	/* Value is not uniques (entry) */
+	NIS_IBMODERROR = 22,	/* Inf. Base. Modify error. */
+	NIS_NOSUCHTABLE = 23,	/* Name for table was wrong */
+	NIS_TYPEMISMATCH = 24, 	/* Entry and table type mismatch */
+	NIS_LINKNAMEERROR = 25,	/* Link points to bogus name */
+	NIS_PARTIAL = 26,	/* Partial success, found table */
+	NIS_TOOMANYATTRS = 27,	/* Too many attributes */
+	NIS_RPCERROR = 28,	/* RPC error encountered */
+	NIS_BADATTRIBUTE = 29,	/* Bad or invalid attribute */
+	NIS_NOTSEARCHABLE = 30,	/* Non-searchable object searched */
+	NIS_CBERROR = 31,	/* Error during callback (svc crash) */
+	NIS_FOREIGNNS = 32,	/* Foreign Namespace */
+	NIS_BADOBJECT = 33,	/* Malformed object structure */
+	NIS_NOTSAMEOBJ = 34,	/* Object swapped during deletion */
+	NIS_MODFAIL = 35,	/* Failure during a Modify. */
+	NIS_BADREQUEST = 36,	/* Illegal query for table */
+	NIS_NOTEMPTY = 37,	/* Attempt to remove a non-empty tbl */
+	NIS_COLDSTART_ERR = 38, /* Error accesing the cold start file */
+	NIS_RESYNC = 39,	/* Transaction log too far out of date */
+	NIS_FAIL = 40,		/* NIS operation failed. */
+	NIS_UNAVAIL = 41,	/* NIS+ service is unavailable (client) */
+	NIS_RES2BIG = 42,	/* NIS+ result too big for datagram */
+	NIS_SRVAUTH = 43,	/* NIS+ server wasn't authenticated. */
+	NIS_CLNTAUTH = 44,	/* NIS+ Client wasn't authenticated. */
+	NIS_NOFILESPACE = 45,	/* NIS+ server ran out of disk space */
+	NIS_NOPROC = 46,	/* NIS+ server couldn't create new proc */
+	NIS_DUMPLATER = 47	/* NIS+ server already has dump child */
+};
+
+
+/* 
+ * Structure definitions for the parameters and results of the actual
+ * NIS RPC calls.
+ *
+ * This is the standard result (in the protocol) of most of the nis 
+ * requests.
+ */
+
+struct nis_result {
+	nis_error	status;		/* Status of the response */
+	nis_object	objects<>;	/* objects found 	  */
+	netobj		cookie;		/* Cookie Data 		  */
+	u_long		zticks;		/* server ticks	 	  */
+	u_long		dticks;		/* DBM ticks.		  */
+	u_long		aticks;		/* Cache (accel) ticks	  */
+	u_long		cticks;		/* Client ticks		  */
+};
+
+/* 
+ * A Name Service request 
+ * This request is used to access the name space, ns_name is the name 
+ * of the object within the namespace and the object is it's value, for
+ * add/modify, a copy of the original for remove. 
+ */
+
+struct ns_request {
+	nis_name	ns_name;	/* Name in the NIS name space	*/
+	nis_object	ns_object<1>;	/* Optional Object (add/remove)	*/
+};
+
+/* 
+ * An information base request
+ * This request includes the NIS name of the table we wish to search, the
+ * search criteria in the form of attribute/value pairs and an optional
+ * callback program number. If the callback program number is provided
+ * the server will send back objects one at a time, otherwise it will
+ * return them all in the response.
+ */
+
+struct ib_request {
+	nis_name  	ibr_name;	/* The name of the Table 	*/
+	nis_attr  	ibr_srch<>; 	/* The search critereia 	*/
+	u_long		ibr_flags;	/* Optional flags 		*/
+	nis_object	ibr_obj<1>;	/* optional object (add/modify) */
+	nis_server	ibr_cbhost<1>;	/* Optional callback info	*/
+	u_long		ibr_bufsize;	/* Optional first/next bufsize	*/
+	netobj		ibr_cookie;	/* The first/next cookie	*/
+};
+
+/*
+ * This argument to the PING call notifies the replicas that something in 
+ * a directory has changed and this is it's timestamp. The replica will use
+ * the timestamp to determine if its resync operation was successful.
+ */
+struct ping_args {
+	nis_name	dir;	/* Directory that had the change */
+	u_long		stamp;	/* timestamp of the transaction  */
+};
+
+/* 
+ * These are the type of entries that are stored in the transaction log, 
+ * note that modifications will appear as two entries, for names, they have
+ * a "OLD" entry followed by a "NEW" entry. For entries in tables, there
+ * is a remove followed by an add. It is done this way so that we can read
+ * the log backwards to back out transactions and forwards to propogate
+ * updated.
+ */
+enum log_entry_t {
+	LOG_NOP = 0,
+	ADD_NAME = 1,		/* Name Added to name space 		  */
+	REM_NAME = 2,		/* Name removed from name space 	  */
+	MOD_NAME_OLD = 3,	/* Name was modified in the name space 	  */
+	MOD_NAME_NEW = 4,	/* Name was modified in the name space 	  */
+	ADD_IBASE = 5,		/* Entry added to information base 	  */
+	REM_IBASE = 6,		/* Entry removed from information base    */
+	MOD_IBASE = 7,		/* Entry was modified in information base */
+	UPD_STAMP = 8		/* Update timestamp (used as fenceposts)  */
+};
+	
+/*
+ * This result is returned from the name service when it is requested to 
+ * dump logged entries from its transaction log. Information base updates
+ * will have the name of the information base in the le_name field and
+ * a canonical set of attribute/value pairs to fully specify the entry's
+ * 'name'. 
+ */
+struct log_entry {
+	u_long		le_time;	/* Time in seconds 		*/
+	log_entry_t	le_type;	/* Type of log entry 		*/
+	nis_name	le_princp;	/* Principal making the change	*/
+	nis_name	le_name;	/* Name of table/dir involved 	*/
+	nis_attr	le_attrs<>;	/* List of AV pairs.		*/
+	nis_object	le_object;	/* Actual object value 		*/
+};
+
+struct log_result {
+	nis_error 	lr_status;	/* The status itself 	 	*/
+	netobj		lr_cookie;	/* Used by the dump callback	*/
+	log_entry	lr_entries<>;	/* zero or more entries 	*/
+};
+	
+struct cp_result {
+	nis_error	cp_status;	/* Status of the checkpoint 	*/
+	u_long		cp_zticks;	/* Service 'ticks' 	    	*/
+	u_long		cp_dticks;	/* Database 'ticks'	    	*/
+};
+
+/*
+ * This structure defines a generic NIS tag list. The taglist contains
+ * zero or tags, each of which is a type and a value. (u_long). 
+ * These are used to report statistics (see tag definitions below)
+ * and to set or reset state variables.
+ */
+struct nis_tag {
+	u_long	tag_type;	/* Statistic tag (may vary) 	 */
+	string	tag_val<1024>;	/* Statistic value may also vary */
+};
+
+struct nis_taglist {
+	nis_tag tags<>;		/* List of tags */
+};
+
+struct dump_args {
+	nis_name	da_dir;		/* Directory to dump 	*/
+	u_long		da_time;	/* From this timestamp	*/
+	nis_server	da_cbhost<1>;	/* Callback to use.	*/
+};
+
+struct fd_args {
+	nis_name	dir_name;  /* The directory we're looking for */
+	nis_name	requester; /* Host principal name for signature */
+};
+
+struct fd_result {
+	nis_error	status;		/* Status returned by function	*/
+	nis_name	source;		/* Source of this answer   	*/
+	opaque		dir_data<>;	/* Directory Data (XDR'ed) 	*/ 
+	opaque		signature<>;	/* Signature of the source 	*/
+};
+
+
+/* 
+ * What's going on here? Well, it's like this. When the service
+ * is being compiled it wants to have the service definition specific
+ * info included, and when the client is being compiled it wants that
+ * info. This includes the appropriate file which was generated by
+ * make in the protocols directory (probably /usr/include/rpcsvc). 
+ */
+#ifdef RPC_SVC
+%#include "nis_svc.h"
+#endif
+#ifdef RPC_CLNT
+%#include "nis_clnt.h"
+#endif
+
+program  NIS_PROG {
+
+	/* RPC Language description of the NIS+ protocol */
+	version NIS_VERSION {
+		/* The name service functions */
+		nis_result  NIS_LOOKUP(ns_request) = 1;
+		nis_result  NIS_ADD(ns_request) = 2;
+		nis_result  NIS_MODIFY(ns_request) = 3;
+		nis_result  NIS_REMOVE(ns_request) = 4;
+
+		/* The information base functions */
+		nis_result  NIS_IBLIST(ib_request) = 5;
+		nis_result  NIS_IBADD(ib_request) = 6;
+		nis_result  NIS_IBMODIFY(ib_request) = 7;
+		nis_result  NIS_IBREMOVE(ib_request) = 8;
+		nis_result  NIS_IBFIRST(ib_request) = 9;
+		nis_result  NIS_IBNEXT(ib_request) = 10;
+
+		/* NIS Administrative functions */
+		fd_result   NIS_FINDDIRECTORY(fd_args) = 12;
+
+		/* If fetch and optionally reset statistics */
+		nis_taglist  NIS_STATUS(nis_taglist) = 14;
+		
+		/* Dump changes to directory since time in da_time */
+		log_result  NIS_DUMPLOG(dump_args) = 15;
+		
+		/* Dump contents of directory named */
+		log_result  NIS_DUMP(dump_args) = 16;
+
+		/* Check status of callback thread */
+		bool	    NIS_CALLBACK(netobj) = 17;
+
+		/* Return last update time for named dir */
+		u_long      NIS_CPTIME(nis_name) = 18;
+
+		/* Checkpoint directory or table named */
+		cp_result   NIS_CHECKPOINT(nis_name) = 19;
+
+		/* Send 'status changed' ping to replicates */
+		void	    NIS_PING(ping_args) = 20;
+	
+		/* Modify server behaviour (such as debugging) */
+		nis_taglist NIS_SERVSTATE(nis_taglist) = 21;
+	
+		/* Create a Directory */
+		nis_error   NIS_MKDIR(nis_name) = 22;
+	
+		/* Remove a Directory */
+		nis_error   NIS_RMDIR(nis_name) = 23;
+		
+		/* Update public keys of a directory object */
+		nis_error   NIS_UPDKEYS(nis_name) = 24;
+	} = 3;
+} = 100300;
+
+/*
+ * Included below are the defines that become part of nis.h,
+ * they are technically not part of the protocol, but do define
+ * key aspects of the implementation and are therefore useful
+ * in building a conforming server or client.
+ */
+#if RPC_HDR
+%/*
+% * Generic "hash" datastructures, used by all types of hashed data.
+% */
+%struct nis_hash_data {
+%	nis_name		name;	   /* NIS name of hashed item      */
+%	int			keychain;  /* It's hash key (for pop)      */
+%	struct nis_hash_data	*next;	   /* Hash collision pointer       */
+%	struct nis_hash_data	*prv_item; /* A serial, doubly linked list */
+%	struct nis_hash_data	*nxt_item; /* of items in the hash table   */
+%};
+%typedef struct nis_hash_data NIS_HASH_ITEM;
+%
+%struct nis_hash_table {
+%	NIS_HASH_ITEM	*keys[64];	/* A hash table of items           */
+%	NIS_HASH_ITEM	*first;		/* The first "item" in serial list */
+%};
+%typedef struct nis_hash_table NIS_HASH_TABLE;
+%
+%/* Structure for storing dynamically allocated static data */
+%struct nis_sdata {
+%	void	*buf;	/* Memory allocation pointer 	*/
+%	u_long	size;	/* Buffer size			*/
+%};
+%
+%/* Generic client creating flags */
+%#define ZMH_VC		1
+%#define ZMH_DG		2
+%#define ZMH_AUTH	4
+%
+%/* Testing Access rights for objects */
+%
+%#define NIS_READ_ACC		1
+%#define NIS_MODIFY_ACC		2
+%#define NIS_CREATE_ACC		4
+%#define NIS_DESTROY_ACC	8
+%/* Test macros. a == access rights, m == desired rights. */
+%#define WORLD(a, m)	(((a) & (m)) != 0)
+%#define GROUP(a, m)	(((a) & ((m) << 8)) != 0)
+%#define OWNER(a, m)	(((a) & ((m) << 16)) != 0)
+%#define NOBODY(a, m)	(((a) & ((m) << 24)) != 0)
+%
+%#define OATYPE(d, n) (((d)->do_armask.do_armask_val+n)->oa_otype)
+%#define OARIGHTS(d, n) (((d)->do_armask.do_armask_val+n)->oa_rights)
+%#define WORLD_DEFAULT (NIS_READ_ACC)
+%#define GROUP_DEFAULT (NIS_READ_ACC << 8)
+%#define OWNER_DEFAULT ((NIS_READ_ACC +\
+			 NIS_MODIFY_ACC +\
+			 NIS_CREATE_ACC +\
+			 NIS_DESTROY_ACC) << 16)
+%#define DEFAULT_RIGHTS (WORLD_DEFAULT | GROUP_DEFAULT | OWNER_DEFAULT)
+%
+%/* Result manipulation defines ... */
+%#define NIS_RES_NUMOBJ(x)	((x)->objects.objects_len)
+%#define NIS_RES_OBJECT(x)	((x)->objects.objects_val)
+%#define NIS_RES_COOKIE(x)	((x)->cookie)
+%#define NIS_RES_STATUS(x)	((x)->status)
+%
+%/* These defines make getting at the variant part of the object easier. */
+%#define TA_data zo_data.objdata_u.ta_data
+%#define EN_data zo_data.objdata_u.en_data
+%#define DI_data zo_data.objdata_u.di_data
+%#define LI_data zo_data.objdata_u.li_data
+%#define GR_data zo_data.objdata_u.gr_data
+%
+%#define __type_of(o) ((o)->zo_data.zo_type)
+%
+%/* Declarations for the internal subroutines in nislib.c */
+%enum name_pos {SAME_NAME, HIGHER_NAME, LOWER_NAME, NOT_SEQUENTIAL, BAD_NAME};
+%typedef enum name_pos name_pos;
+%
+%/*
+% * Defines for getting at column data in entry objects. Because RPCGEN
+% * generates some rather wordy structures, we create some defines that
+% * collapse the needed keystrokes to access a particular value using
+% * these definitions they take an nis_object *, and an int and return
+% * a u_char * for Value, and an int for length.
+% */
+%#define ENTRY_VAL(obj, col) \
+%	(obj)->EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val
+%#define ENTRY_LEN(obj, col) \
+%	(obj)->EN_data.en_cols.en_cols_val[col].ec_value.ec_value_len
+%
+%#ifdef __cplusplus
+%}
+%#endif
+%
+%/* Prototypes, and extern declarations for the NIS library functions. */
+%#include <rpcsvc/nislib.h>
+%#endif /* __NIS_RPCGEN_H */
+%/* EDIT_START */
+%
+%/*
+% * nis_3.h
+% * 
+% * This file contains definitions that are only of interest to the actual
+% * service daemon and client stubs. Normal users of NIS will not include
+% * this file.
+% *
+% * NOTE : This include file is automatically created by a combination 
+% * of rpcgen and sed. DO NOT EDIT IT, change the nis.x file instead
+% * and then remake this file.
+% */
+%#ifndef __nis_3_h
+%#define __nis_3_h
+%#ifdef __cplusplus
+%extern "C" {
+%#endif
+#endif
diff --git a/nis/rpcsvc/nis_object.x b/nis/rpcsvc/nis_object.x
new file mode 100644
index 0000000000..e13ae47b70
--- /dev/null
+++ b/nis/rpcsvc/nis_object.x
@@ -0,0 +1,287 @@
+/*
+ *	nis_object.x
+ *
+ *	Copyright (c) 1988-1992 Sun Microsystems Inc
+ *	All Rights Reserved.
+ */
+
+%#pragma ident	"@(#)nis_object.x	1.7	92/07/14 SMI"
+
+#if RPC_HDR
+%
+%#ifndef __nis_object_h
+%#define __nis_object_h
+%
+#endif
+/* 
+ * 	This file defines the format for a NIS object in RPC language.
+ * It is included by the main .x file and the database access protocol
+ * file. It is common because both of them need to deal with the same
+ * type of object. Generating the actual code though is a bit messy because
+ * the nis.x file and the nis_dba.x file will generate xdr routines to 
+ * encode/decode objects when only one set is needed. Such is life when
+ * one is using rpcgen.
+ *
+ * Note, the protocol doesn't specify any limits on such things as
+ * maximum name length, number of attributes, etc. These are enforced
+ * by the database backend. When you hit them you will no. Also see
+ * the db_getlimits() function for fetching the limit values.
+ *
+ */
+
+/* Some manifest constants, chosen to maximize flexibility without
+ * plugging the wire full of data.
+ */
+const NIS_MAXSTRINGLEN = 255;
+const NIS_MAXNAMELEN   = 1024;
+const NIS_MAXATTRNAME  = 32;
+const NIS_MAXATTRVAL   = 2048;
+const NIS_MAXCOLUMNS   = 64;
+const NIS_MAXATTR      = 16;
+const NIS_MAXPATH      = 1024;
+const NIS_MAXREPLICAS  = 128;
+const NIS_MAXLINKS     = 16;
+
+const NIS_PK_NONE      = 0;	/* no public key (unix/sys auth) */
+const NIS_PK_DH	       = 1;	/* Public key is Diffie-Hellman type */
+const NIS_PK_RSA       = 2;	/* Public key if RSA type */
+const NIS_PK_KERB      = 3;	/* Use kerberos style authentication */
+
+/*
+ * The fundamental name type of NIS. The name may consist of two parts,
+ * the first being the fully qualified name, and the second being an 
+ * optional set of attribute/value pairs.
+ */
+struct nis_attr {
+	string	zattr_ndx<>;	/* name of the index 		*/
+	opaque	zattr_val<>;	/* Value for the attribute. 	*/
+};
+
+typedef string nis_name<>;	/* The NIS name itself. */
+
+/* NIS object types are defined by the following enumeration. The numbers
+ * they use are based on the following scheme :
+ *		     0 - 1023 are reserved for Sun,
+ * 		1024 - 2047 are defined to be private to a particular tree.
+ *		2048 - 4095 are defined to be user defined.
+ *		4096 - ...  are reserved for future use.
+ */
+
+enum zotypes {
+	BOGUS_OBJ  	= 0,	/* Uninitialized object structure 	*/
+	NO_OBJ   	= 1,	/* NULL object (no data)	 	*/
+	DIRECTORY_OBJ 	= 2,	/* Directory object describing domain 	*/
+	GROUP_OBJ  	= 3,	/* Group object (a list of names) 	*/
+	TABLE_OBJ  	= 4,	/* Table object (a database schema) 	*/
+	ENTRY_OBJ  	= 5,	/* Entry object (a database record) 	*/
+	LINK_OBJ   	= 6, 	/* A name link.				*/
+	PRIVATE_OBJ   	= 7 	/* Private object (all opaque data) 	*/
+};
+
+/*
+ * The types of Name services NIS knows about. They are enumerated
+ * here. The Binder code will use this type to determine if it has
+ * a set of library routines that will access the indicated name service.
+ */
+enum nstype {
+	UNKNOWN = 0,
+	NIS = 1,	/* Nis Plus Service		*/
+	SUNYP = 2,	/* Old NIS Service		*/
+	IVY = 3,	/* Nis Plus Plus Service	*/
+	DNS = 4,	/* Domain Name Service		*/
+	X500 = 5,	/* ISO/CCCIT X.500 Service	*/
+	DNANS = 6,	/* Digital DECNet Name Service	*/
+	XCHS = 7,	/* Xerox ClearingHouse Service	*/
+	CDS= 8
+};
+
+/*
+ * DIRECTORY - The name service object. These objects identify other name
+ * servers that are serving some portion of the name space. Each has a
+ * type associated with it. The resolver library will note whether or not
+ * is has the needed routines to access that type of service. 
+ * The oarmask structure defines an access rights mask on a per object 
+ * type basis for the name spaces. The only bits currently used are 
+ * create and destroy. By enabling or disabling these access rights for
+ * a specific object type for a one of the accessor entities (owner,
+ * group, world) the administrator can control what types of objects 
+ * may be freely added to the name space and which require the 
+ * administrator's approval.
+ */
+struct oar_mask {
+	u_long	oa_rights;	/* Access rights mask 	*/
+	zotypes	oa_otype;	/* Object type 		*/
+};
+
+struct endpoint {
+	string		uaddr<>;
+	string		family<>;   /* Transport family (INET, OSI, etc) */
+	string		proto<>;    /* Protocol (TCP, UDP, CLNP,  etc)   */
+};
+
+/*
+ * Note: pkey is a netobj which is limited to 1024 bytes which limits the
+ * keysize to 8192 bits. This is consider to be a reasonable limit for
+ * the expected lifetime of this service.
+ */
+struct nis_server {
+	nis_name	name; 	 	/* Principal name of the server  */
+	endpoint	ep<>;  		/* Universal addr(s) for server  */
+	u_long		key_type;	/* Public key type		 */
+	netobj		pkey;		/* server's public key  	 */
+};
+
+struct directory_obj {
+	nis_name   do_name;	 /* Name of the directory being served   */
+	nstype	   do_type;	 /* one of NIS, DNS, IVY, YP, or X.500 	 */
+	nis_server do_servers<>; /* <0> == Primary name server     	 */
+	u_long	   do_ttl;	 /* Time To Live (for caches) 		 */
+	oar_mask   do_armask<>;  /* Create/Destroy rights by object type */
+};
+
+/* 
+ * ENTRY - This is one row of data from an information base. 
+ * The type value is used by the client library to convert the entry to 
+ * it's internal structure representation. The Table name is a back pointer
+ * to the table where the entry is stored. This allows the client library 
+ * to determine where to send a request if the client wishes to change this
+ * entry but got to it through a LINK rather than directly.
+ * If the entry is a "standalone" entry then this field is void.
+ */
+const EN_BINARY   = 1;	/* Indicates value is binary data 	*/
+const EN_CRYPT    = 2;	/* Indicates the value is encrypted	*/
+const EN_XDR      = 4;	/* Indicates the value is XDR encoded	*/
+const EN_MODIFIED = 8;	/* Indicates entry is modified. 	*/
+const EN_ASN1     = 64;	/* Means contents use ASN.1 encoding    */
+
+struct entry_col {
+	u_long	ec_flags;	/* Flags for this value */
+	opaque	ec_value<>;	/* It's textual value	*/
+};
+
+struct entry_obj {
+	string 	en_type<>;	/* Type of entry such as "passwd" */
+	entry_col en_cols<>;	/* Value for the entry		  */
+};
+
+/*
+ * GROUP - The group object contains a list of NIS principal names. Groups
+ * are used to authorize principals. Each object has a set of access rights
+ * for members of its group. Principal names in groups are in the form 
+ * name.directory and recursive groups are expressed as @groupname.directory
+ */
+struct group_obj {
+	u_long		gr_flags;	/* Flags controlling group	*/
+	nis_name	gr_members<>;  	/* List of names in group 	*/
+};
+
+/*
+ * LINK - This is the LINK object. It is quite similar to a symbolic link
+ * in the UNIX filesystem. The attributes in the main object structure are
+ * relative to the LINK data and not what it points to (like the file system)
+ * "modify" privleges here indicate the right to modify what the link points
+ * at and not to modify that actual object pointed to by the link.
+ */
+struct link_obj {
+	zotypes	 li_rtype;	/* Real type of the object	*/
+	nis_attr li_attrs<>;	/* Attribute/Values for tables	*/
+	nis_name li_name; 	/* The object's real NIS name	*/
+};
+
+/*
+ * TABLE - This is the table object. It implements a simple 
+ * data base that applications and use for configuration or 
+ * administration purposes. The role of the table is to group together
+ * a set of related entries. Tables are the simple database component
+ * of NIS. Like many databases, tables are logically divided into columns
+ * and rows. The columns are labeled with indexes and each ENTRY makes
+ * up a row. Rows may be addressed within the table by selecting one
+ * or more indexes, and values for those indexes. Each row which has
+ * a value for the given index that matches the desired value is returned.
+ * Within the definition of each column there is a flags variable, this
+ * variable contains flags which determine whether or not the column is
+ * searchable, contains binary data, and access rights for the entry objects
+ * column value. 
+ */
+
+const TA_BINARY     = 1;	/* Means table data is binary 		*/
+const TA_CRYPT      = 2;	/* Means value should be encrypted 	*/
+const TA_XDR        = 4;	/* Means value is XDR encoded		*/
+const TA_SEARCHABLE = 8;	/* Means this column is searchable	*/
+const TA_CASE       = 16;	/* Means this column is Case Sensitive	*/
+const TA_MODIFIED   = 32;	/* Means this columns attrs are modified*/
+const TA_ASN1       = 64;	/* Means contents use ASN.1 encoding     */
+
+struct table_col {
+	string	tc_name<64>;	/* Column Name 	 	   */
+	u_long	tc_flags;	/* control flags	   */
+	u_long	tc_rights;	/* Access rights mask	   */
+};
+
+struct table_obj {
+	string 	  ta_type<64>;	 /* Table type such as "passwd"	*/
+	int	  ta_maxcol;	 /* Total number of columns	*/
+	u_char	  ta_sep;	 /* Separator character 	*/
+	table_col ta_cols<>; 	 /* The number of table indexes */
+	string	  ta_path<>;	 /* A search path for this table */
+};
+
+/*
+ * This union joins together all of the currently known objects. 
+ */
+union objdata switch (zotypes zo_type) {
+        case DIRECTORY_OBJ :
+                struct directory_obj di_data;
+        case GROUP_OBJ :
+                struct group_obj gr_data;
+        case TABLE_OBJ :
+                struct table_obj ta_data;
+        case ENTRY_OBJ:
+                struct entry_obj en_data;
+        case LINK_OBJ :
+                struct link_obj li_data;
+        case PRIVATE_OBJ :
+                opaque	po_data<>;
+	case NO_OBJ :
+		void;
+        case BOGUS_OBJ :
+		void;
+        default :
+                void;
+};
+
+/*
+ * This is the basic NIS object data type. It consists of a generic part
+ * which all objects contain, and a specialized part which varies depending
+ * on the type of the object. All of the specialized sections have been
+ * described above. You might have wondered why they all start with an 
+ * integer size, followed by the useful data. The answer is, when the 
+ * server doesn't recognize the type returned it treats it as opaque data. 
+ * And the definition for opaque data is {int size; char *data;}. In this
+ * way, servers and utility routines that do not understand a given type
+ * may still pass it around. One has to be careful in setting
+ * this variable accurately, it must take into account such things as
+ * XDR padding of structures etc. The best way to set it is to note one's
+ * position in the XDR encoding stream, encode the structure, look at the
+ * new position and calculate the size. 
+ */
+struct nis_oid {
+	u_long	ctime;		/* Time of objects creation 	*/
+	u_long	mtime;		/* Time of objects modification */
+};
+
+struct nis_object {
+	nis_oid	 zo_oid;	/* object identity verifier.		*/ 
+	nis_name zo_name;	/* The NIS name for this object		*/
+	nis_name zo_owner;	/* NIS name of object owner.		*/
+	nis_name zo_group;	/* NIS name of access group.		*/
+	nis_name zo_domain;	/* The administrator for the object	*/
+	u_long	 zo_access;	/* Access rights (owner, group, world)	*/
+	u_long	 zo_ttl;	/* Object's time to live in seconds.	*/
+	objdata	 zo_data;	/* Data structure for this type 	*/
+};
+#if RPC_HDR
+%
+%#endif /* if __nis_object_h */
+%
+#endif
diff --git a/nis/rpcsvc/nis_tags.h b/nis/rpcsvc/nis_tags.h
new file mode 100644
index 0000000000..30bdff6d1a
--- /dev/null
+++ b/nis/rpcsvc/nis_tags.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 1991, Sun Microsystems Inc.
+ */
+
+/*
+ *	nis_tags.h
+ *
+ *	This file contains the tags and statistics definitions. It is
+ *	automatically included by nis.h
+ */
+
+#ifndef	_RPCSVC_NIS_TAGS_H
+#define	_RPCSVC_NIS_TAGS_H
+
+#pragma ident	"@(#)nis_tags.h	1.13	95/02/17 SMI"
+/* from file: zns_tags.h	1.7 Copyright (c) 1990 Sun Microsystems */
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+
+#define	NIS_DIR	"data"
+
+/* Lookup and List function flags */
+#define	FOLLOW_LINKS	(1<<0)	/* Follow link objects 			*/
+#define	FOLLOW_PATH	(1<<1)	/* Follow the path in a table 		*/
+#define	HARD_LOOKUP	(1<<2)	/* Block until successful 		*/
+#define	ALL_RESULTS	(1<<3)	/* Retrieve all results 		*/
+#define	NO_CACHE	(1<<4)	/* Do not return 'cached' results 	*/
+#define	MASTER_ONLY	(1<<5)	/* Get value only from master server	*/
+#define	EXPAND_NAME	(1<<6)	/* Expand partitially qualified names	*/
+
+/* Semantic modification for table operations flags */
+#define	RETURN_RESULT	(1<<7)	/* Return resulting object to client    */
+#define	ADD_OVERWRITE	(1<<8)	/* Allow overwrites on ADD		*/
+#define	REM_MULTIPLE	(1<<9)	/* Allow wildcard deletes		*/
+#define	MOD_SAMEOBJ	(1<<10)	/* Check modified object before write	*/
+#define	ADD_RESERVED	(1<<11)	/* Spare ADD semantic			*/
+#define	REM_RESERVED	(1<<12)	/* Spare REM semantic			*/
+#define	MOD_EXCLUSIVE	(1<<13)	/* Modify no overwrite on modified keys */
+
+/* Transport specific modifications to the operation */
+#define	USE_DGRAM	(1<<16) /* Use a datagram transport 		*/
+#define	NO_AUTHINFO	(1<<17) /* Don't bother attaching auth info	*/
+
+/*
+ * Declarations for "standard" NIS+ tags
+ * State variable tags have values	0 - 2047
+ * Statistic tags have values		2048 - 65535
+ * User Tags have values		>2^16
+ */
+#define	TAG_DEBUG	1	/* set debug level 		*/
+#define	TAG_STATS	2	/* Enable/disable statistics 	*/
+#define	TAG_GCACHE	3	/* Flush the Group Cache	*/
+#define	TAG_GCACHE_ALL	TAG_GCACHE
+#define	TAG_DCACHE	4	/* Flush the directory cache	*/
+#define	TAG_DCACHE_ONE	TAG_DCACHE
+#define	TAG_OCACHE	5	/* Flush the Object Cache	*/
+#define	TAG_SECURE	6	/* Set the security level 	*/
+#define	TAG_TCACHE_ONE	7	/* Flush the table cache	*/
+#define	TAG_DCACHE_ALL	8	/* Flush entire directory cache	*/
+#define	TAG_TCACHE_ALL	9	/* Flush entire table cache	*/
+#define	TAG_GCACHE_ONE	10	/* Flush one group object	*/
+#define	TAG_DCACHE_ONE_REFRESH 11 /* Flush and refresh one DO	*/
+
+#define	TAG_OPSTATS	2048	/* NIS+ operations statistics   */
+#define	TAG_THREADS	2049	/* Child process/thread status  */
+#define	TAG_HEAP	2050	/* Heap usage statistics	*/
+#define	TAG_UPDATES	2051	/* Updates to this service	*/
+#define	TAG_VISIBLE	2052	/* First update that isn't replicated */
+#define	TAG_S_DCACHE	2053	/* Directory cache statistics	*/
+#define	TAG_S_OCACHE	2054	/* Object cache statistics	*/
+#define	TAG_S_GCACHE	2055	/* Group cache statistics	*/
+#define	TAG_S_STORAGE	2056	/* Group cache statistics	*/
+#define	TAG_UPTIME	2057	/* Time that server has been up */
+#define	TAG_DIRLIST	2058	/* Dir served by this server    */
+#define	TAG_NISCOMPAT	2059	/* Whether supports NIS compat mode */
+#define	TAG_DNSFORWARDING 2060	/* Whether DNS forwarding supported */
+#define	TAG_SECURITY_LEVEL 2061	/* Security level of the server	*/
+#define	TAG_ROOTSERVER	2062	/* Whether root server		*/
+
+/*
+ * Declarations for the Group object flags. Currently
+ * there are only 3.
+ */
+#define	IMPMEM_GROUPS  1	/* Implicit Membership allowed 	*/
+#define	RECURS_GROUPS  2	/* Recursive Groups allowed 	*/
+#define	NEGMEM_GROUPS  4	/* Negative Groups allowed	*/
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _RPCSVC_NIS_TAGS_H */
diff --git a/nis/rpcsvc/nislib.h b/nis/rpcsvc/nislib.h
new file mode 100644
index 0000000000..2ad38ef9c8
--- /dev/null
+++ b/nis/rpcsvc/nislib.h
@@ -0,0 +1,165 @@
+/* Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
+
+   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	__RPCSVC_NISLIB_H__
+#define	__RPCSVC_NISLIB_H__
+
+#include <features.h>
+
+__BEGIN_DECLS
+
+/*
+** nis_names
+*/
+extern nis_result *nis_lookup __P ((__const nis_name, const u_long));
+extern nis_result *nis_add __P ((__const nis_name, const nis_object *));
+extern nis_result *nis_remove __P ((__const nis_name, const nis_object *));
+extern nis_result *nis_modify __P ((__const nis_name, const nis_object *));
+/*
+** nis_table
+*/
+extern nis_result *nis_list __P ((__const nis_name, const u_long,
+				  int (*)(__const nis_name,
+					  __const nis_object *,
+					  __const void *), __const void *));
+extern nis_result *nis_add_entry __P ((__const nis_name, __const nis_object *,
+				       __const u_long));
+extern nis_result *nis_modify_entry __P ((__const nis_name,
+					  __const nis_object *,
+					  __const u_long));
+extern nis_result *nis_remove_entry __P ((__const nis_name,
+					  __const nis_object *,
+					  __const u_long));
+extern nis_result *nis_first_entry __P ((__const nis_name));
+extern nis_result *nis_next_entry __P ((__const nis_name, __const netobj *));
+/*
+** nis_server
+*/
+extern nis_error nis_mkdir __P ((__const nis_name, __const nis_server *));
+extern nis_error nis_rmdir __P ((__const nis_name, __const nis_server *));
+extern nis_error nis_servstate __P ((__const nis_server *, __const nis_tag *,
+				     __const int, nis_tag **));
+extern nis_error nis_stats __P ((__const nis_server *, __const nis_tag *,
+				 __const int, nis_tag **));
+extern void nis_freetags __P ((nis_tag *, __const int));
+extern nis_server **nis_getservlist __P ((__const nis_name));
+extern void nis_freeservlist __P ((nis_server **));
+/*
+** nis_subr
+*/
+extern nis_name nis_leaf_of __P ((__const nis_name));
+extern nis_name nis_leaf_of_r __P ((__const nis_name, char *, size_t));
+extern nis_name nis_name_of __P ((__const nis_name));
+extern nis_name nis_name_of_r __P ((__const nis_name, char *, size_t));
+extern nis_name nis_domain_of __P ((__const nis_name));
+extern nis_name nis_domain_of_r __P ((__const nis_name, char *, size_t));
+extern nis_name *nis_getnames __P ((__const nis_name));
+extern void nis_freenames __P ((nis_name *));
+extern name_pos nis_dir_cmp __P ((nis_name, nis_name));
+extern nis_object *nis_clone_object __P ((__const nis_object *, nis_object *));
+extern void nis_destroy_object __P ((nis_object *));
+extern void nis_print_object __P ((__const nis_object *));
+/*
+** nis_local_names
+*/
+extern nis_name nis_local_group __P ((void));
+extern nis_name nis_local_directory __P ((void));
+extern nis_name nis_local_principal __P ((void));
+extern nis_name nis_local_host __P ((void));
+/*
+** nis_error
+*/
+extern const char *nis_sperrno __P ((__const nis_error));
+extern void nis_perror __P ((__const nis_error, __const char *));
+extern void nis_lerror __P ((__const nis_error, __const char *));
+extern char *nis_sperror __P ((__const nis_error, __const char *));
+extern char *nis_sperror_r __P ((__const nis_error, __const char *,
+				 char *, size_t));
+/*
+** nis_groups
+*/
+extern bool_t nis_ismember __P ((__const nis_name, __const nis_name));
+extern nis_error nis_addmember __P ((__const nis_name, __const nis_name));
+extern nis_error nis_removemember __P ((__const nis_name, __const nis_name));
+extern nis_error nis_creategroup __P ((__const nis_name, __const u_long));
+extern nis_error nis_destroygroup __P ((__const nis_name));
+extern void nis_print_group_entry __P ((__const nis_name));
+extern nis_error nis_verifygroup __P ((__const nis_name));
+/*
+** nis_ping
+*/
+extern void nis_ping __P ((__const nis_name, __const u_long,
+			   __const nis_object *));
+extern nis_result *nis_checkpoint __P ((__const nis_name));
+
+/*
+** nis_print (XXX INTERNAL FUNCTIONS, SHOULD NOT BE USED !!)
+*/
+extern void nis_print_result __P ((__const nis_result *));
+extern void nis_print_rights __P ((__const u_long));
+extern void nis_print_directory __P ((__const directory_obj *));
+extern void nis_print_group __P ((__const group_obj *));
+extern void nis_print_table __P ((__const table_obj *));
+extern void nis_print_link __P ((__const link_obj *));
+extern void nis_print_entry __P ((__const entry_obj *));
+/*
+** nis_file (XXX INTERNAL FUNCTIONS, SHOULD NOT BE USED !!)
+*/
+extern directory_obj *readColdStartFile __P ((void));
+extern bool_t writeColdStartFile __P ((__const directory_obj *));
+extern nis_object *nis_read_obj __P ((__const char *));
+extern bool_t nis_write_obj __P ((__const char *, __const nis_object *));
+/*
+** nis_clone - (XXX INTERNAL FUNCTIONS, SHOULD NOT BE USED !!)
+*/
+
+extern directory_obj *nis_clone_directory __P ((__const directory_obj *,
+						directory_obj *));
+extern group_obj *nis_clone_group __P ((__const group_obj *, group_obj *));
+extern table_obj *nis_clone_table __P ((__const table_obj *, table_obj *));
+extern entry_obj *nis_clone_entry __P ((__const entry_obj *, entry_obj *));
+extern link_obj *nis_clone_link __P ((__const link_obj *, link_obj *));
+extern objdata *nis_clone_objdata __P ((__const objdata *, objdata *));
+extern nis_result *nis_clone_result __P ((__const nis_result *, nis_result *));
+/*
+** nis_free - nis_freeresult
+*/
+extern void nis_freeresult __P ((nis_result *));
+/* (XXX INTERNAL FUNCTIONS, SHOULD NOT BE USED !!) */
+extern void nis_free_attr __P ((nis_attr *));
+extern void nis_free_request __P ((ib_request *));
+extern void nis_free_endpoints __P ((endpoint *, int));
+extern void nis_free_servers __P ((nis_server *, int));
+extern void nis_free_directory __P ((directory_obj *));
+extern void nis_free_group __P ((group_obj *));
+extern void nis_free_table __P ((table_obj *));
+extern void nis_free_entry __P ((entry_obj *));
+extern void nis_free_link __P ((link_obj *));
+extern void nis_free_object __P ((nis_object *));
+
+/* This is the SUN definition, but I don't know for what we need
+   the directory_obj parameter */
+/* extern fd_result *nis_finddirectory __P ((directory_obj *, nis_name)); */
+extern fd_result *__nis_finddirectory __P ((nis_name));
+extern int __start_clock(int);
+extern u_long __stop_clock(int);
+
+__END_DECLS
+
+#endif	/* __RPCSVC_NISLIB_H__ */
diff --git a/nss/nss_files/files-service.c b/nss/nss_files/files-service.c
index 5fb38e2058..317b4fa9cc 100644
--- a/nss/nss_files/files-service.c
+++ b/nss/nss_files/files-service.c
@@ -41,8 +41,8 @@ LINE_PARSER
 
 DB_LOOKUP (servbyname, 1 + strlen (name), (".%s/%s", name, proto),
 	   {
-	     /* Must match both protocol and name.  */
-	     if (strcmp (result->s_proto, proto))
+	     /* Must match both protocol (if specified) and name.  */
+	     if (proto != NULL && strcmp (result->s_proto, proto))
 	       continue;
 	     LOOKUP_NAME (s_name, s_aliases)
 	   },
diff --git a/setjmp/tst-setjmp.c b/setjmp/tst-setjmp.c
index 53fee89864..6147ae9567 100644
--- a/setjmp/tst-setjmp.c
+++ b/setjmp/tst-setjmp.c
@@ -52,6 +52,29 @@ main (void)
 	jump (value + 1);
     }
 
+  if (!lose && value == 10)
+    {
+      /* Do a second test, this time without `setjmp' being a macro.  */
+#undef setjmp
+      value = setjmp (env);
+      if (value != last_value + 1)
+	{
+	  fputs("Shouldn't have ", stdout);
+	  lose = 1;
+	}
+      last_value = value;
+      switch (value)
+	{
+	case 0:
+	  puts("Saved environment.");
+	  jump (0);
+	default:
+	  printf ("Jumped to %d.\n", value);
+	  if (value < 10)
+	    jump (value + 1);
+	}
+    }
+
   if (lose || value != 10)
     puts ("Test FAILED!");
   else
diff --git a/shlib-versions b/shlib-versions
index 3ad220d625..145de21e0f 100644
--- a/shlib-versions
+++ b/shlib-versions
@@ -56,13 +56,15 @@ alpha-.*-linux.*	libnss_dns=1.1
 alpha-.*-linux.*	libnss_db=1.1
 alpha-.*-linux.*	libnss_compat=1.1
 alpha-.*-linux.*	libnss_nis=1.1
+alpha-.*-linux.*	libnss_nisplus=1.1
 .*-.*-.*		libnss_files=1
 .*-.*-.*		libnss_dns=1
 .*-.*-.*		libnss_db=1
 .*-.*-.*		libnss_compat=1
 .*-.*-.*		libnss_nis=1
+.*-.*-.*		libnss_nisplus=1
 
-# Version for libnsl with YP functions.
+# Version for libnsl with YP and NIS+ functions.
 alpha-.*-linux.*	libnsl=1.1
 .*-.*-.*		libnsl=1
 
diff --git a/sysdeps/generic/setenv.c b/sysdeps/generic/setenv.c
index 6d0c23114c..94dc7472ec 100644
--- a/sysdeps/generic/setenv.c
+++ b/sysdeps/generic/setenv.c
@@ -132,9 +132,9 @@ setenv (name, value, replace)
 	      return -1;
 	    }
 	  *ep = new;
+	  memcpy (*ep, name, namelen);
+	  (*ep)[namelen] = '=';
 	}
-      memcpy (*ep, name, namelen);
-      (*ep)[namelen] = '=';
       memcpy (&(*ep)[namelen + 1], value, vallen);
     }
 
diff --git a/sysdeps/i386/setjmp.S b/sysdeps/i386/setjmp.S
index 23e2b74401..203c2d16d0 100644
--- a/sysdeps/i386/setjmp.S
+++ b/sysdeps/i386/setjmp.S
@@ -1,21 +1,21 @@
 /* setjmp for i386.
-Copyright (C) 1995, 1996 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
+   Copyright (C) 1995, 1996, 1997 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., 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 <sysdep.h>
 #define _ASM
@@ -24,7 +24,9 @@ Cambridge, MA 02139, USA.  */
 	/* Binary compatibility entry point.  */
 ENTRY (__setjmp)
 	popl %eax		/* Pop return address.  */
+	popl %ecx		/* Pop jmp_buf.  */
 	pushl $0		/* Push zero argument.  */
+	pushl %ecx		/* Push jmp_buf.  */
 	pushl %eax		/* Push back return address.  */
 
 ENTRY (__sigsetjmp)
diff --git a/sysdeps/libm-i387/e_pow.S b/sysdeps/libm-i387/e_pow.S
index efe184168b..ab6b454339 100644
--- a/sysdeps/libm-i387/e_pow.S
+++ b/sysdeps/libm-i387/e_pow.S
@@ -64,6 +64,13 @@ nan:	.byte 0, 0, 0, 0, 0, 0, 0xff, 0x7f
 ENTRY(__ieee754_pow)
 	fldl	12(%esp)	// y
 	fxam
+
+#ifdef	PIC
+	call	1f
+1:	popl	%ecx
+	addl	$_GLOBAL_OFFSET_TABLE_+[.-1b], %ecx
+#endif
+
 	fnstsw
 	movb	%ah, %dl
 	andb	$0x45, %ah
@@ -76,12 +83,6 @@ ENTRY(__ieee754_pow)
 	cmpb	$0x01, %ah	// is y == NaN ?
 	je	30f
 
-#ifdef	PIC
-	call	1f
-1:	popl	%ecx
-	addl	$_GLOBAL_OFFSET_TABLE_+[.-1b], %ecx
-#endif
-
 	fldl	4(%esp)		// x : y
 
 	subl	$8,%esp
diff --git a/sysdeps/libm-i387/e_powf.S b/sysdeps/libm-i387/e_powf.S
index 54af93c961..48316464ef 100644
--- a/sysdeps/libm-i387/e_powf.S
+++ b/sysdeps/libm-i387/e_powf.S
@@ -64,6 +64,13 @@ nan:	.byte 0, 0, 0, 0, 0, 0, 0xff, 0x7f
 ENTRY(__ieee754_powf)
 	flds	8(%esp)	// y
 	fxam
+
+#ifdef	PIC
+	call	1f
+1:	popl	%ecx
+	addl	$_GLOBAL_OFFSET_TABLE_+[.-1b], %ecx
+#endif
+
 	fnstsw
 	movb	%ah, %dl
 	andb	$0x45, %ah
@@ -76,12 +83,6 @@ ENTRY(__ieee754_powf)
 	cmpb	$0x01, %ah	// is y == NaN ?
 	je	30f
 
-#ifdef	PIC
-	call	1f
-1:	popl	%ecx
-	addl	$_GLOBAL_OFFSET_TABLE_+[.-1b], %ecx
-#endif
-
 	flds	4(%esp)		// x : y
 
 	subl	$4, %esp
diff --git a/sysdeps/libm-i387/e_powl.S b/sysdeps/libm-i387/e_powl.S
index 3cfb96b213..dba725aa77 100644
--- a/sysdeps/libm-i387/e_powl.S
+++ b/sysdeps/libm-i387/e_powl.S
@@ -64,6 +64,13 @@ nan:	.byte 0, 0, 0, 0, 0, 0, 0xff, 0x7f
 ENTRY(__ieee754_powl)
 	fldt	16(%esp)	// y
 	fxam
+
+#ifdef	PIC
+	call	1f
+1:	popl	%ecx
+	addl	$_GLOBAL_OFFSET_TABLE_+[.-1b], %ecx
+#endif
+
 	fnstsw
 	movb	%ah, %dl
 	andb	$0x45, %ah
@@ -76,12 +83,6 @@ ENTRY(__ieee754_powl)
 	cmpb	$0x01, %ah	// is y == NaN ?
 	je	30f
 
-#ifdef	PIC
-	call	1f
-1:	popl	%ecx
-	addl	$_GLOBAL_OFFSET_TABLE_+[.-1b], %ecx
-#endif
-
 	fldt	4(%esp)		// x : y
 
 	subl	$8,%esp
diff --git a/sysdeps/powerpc/__longjmp.S b/sysdeps/powerpc/__longjmp.S
index 928b5c540a..da621e22c0 100644
--- a/sysdeps/powerpc/__longjmp.S
+++ b/sysdeps/powerpc/__longjmp.S
@@ -62,5 +62,6 @@ ENTRY (__longjmp)
 	lfd 30,((JB_FPRS+16*2)*4)(3)
 	lwz 31,((JB_GPRS+17)*4)(3)
 	lfd 31,((JB_FPRS+17*2)*4)(3)
+	mr 3,4
 	blr
 END (__longjmp)
diff --git a/sysdeps/powerpc/bsd-_setjmp.S b/sysdeps/powerpc/bsd-_setjmp.S
index 90171ea616..a9aefcc977 100644
--- a/sysdeps/powerpc/bsd-_setjmp.S
+++ b/sysdeps/powerpc/bsd-_setjmp.S
@@ -25,5 +25,9 @@
 
 ENTRY (_setjmp)
 	li 4,0				/* Set second argument to 0.  */
-	b C_SYMBOL_NAME(__sigsetjmp)
+#ifdef PIC
+	b __sigsetjmp@plt
+#else
+	b __sigsetjmp
+#endif
 END (_setjmp)
diff --git a/sysdeps/powerpc/bsd-setjmp.S b/sysdeps/powerpc/bsd-setjmp.S
new file mode 100644
index 0000000000..19c2fe308c
--- /dev/null
+++ b/sysdeps/powerpc/bsd-setjmp.S
@@ -0,0 +1,33 @@
+/* BSD `setjmp' entry point to `sigsetjmp (..., 1)'.  PowerPC version.
+   Copyright (C) 1994, 1997 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.  */
+
+/* This just does a tail-call to `__sigsetjmp (ARG, 1)'.
+   We cannot do it in C because it must be a tail-call, so frame-unwinding
+   in setjmp doesn't clobber the state restored by longjmp.  */
+
+#include <sysdep.h>
+
+ENTRY (setjmp)
+	li 4,1				/* Set second argument to 1.  */
+#ifdef PIC
+	b __sigsetjmp@plt
+#else
+	b __sigsetjmp
+#endif
+END (setjmp)
diff --git a/sysdeps/powerpc/dl-machine.h b/sysdeps/powerpc/dl-machine.h
index a60a29723d..541892cdfc 100644
--- a/sysdeps/powerpc/dl-machine.h
+++ b/sysdeps/powerpc/dl-machine.h
@@ -26,6 +26,14 @@
 /* stuff for the PLT */
 #define PLT_INITIAL_ENTRY_WORDS 18
 #define PLT_LONGBRANCH_ENTRY_WORDS 10
+#define PLT_DOUBLE_SIZE (1<<13)
+#define PLT_ENTRY_START_WORDS(entry_number) \
+  (PLT_INITIAL_ENTRY_WORDS + (entry_number)*2 + \
+   ((entry_number) > PLT_DOUBLE_SIZE ? \
+    ((entry_number) - PLT_DOUBLE_SIZE)*2 : \
+    0))
+#define PLT_DATA_START_WORDS(num_entries) PLT_ENTRY_START_WORDS(num_entries)
+
 #define OPCODE_ADDI(rd,ra,simm) \
   (0x38000000 | (rd) << 21 | (ra) << 16 | (simm) & 0xffff)
 #define OPCODE_ADDIS(rd,ra,simm) \
@@ -44,6 +52,19 @@
 #define OPCODE_LI(rd,simm)    OPCODE_ADDI(rd,0,simm)
 #define OPCODE_SLWI(ra,rs,sh) OPCODE_RLWINM(ra,rs,sh,0,31-sh)
 
+#define PPC_DCBST(where) asm __volatile__ ("dcbst 0,%0" : : "r"(where))
++#define PPC_SYNC asm __volatile__ ("sync")
++#define PPC_ISYNC asm __volatile__ ("sync; isync")
++#define PPC_ICBI(where) asm __volatile__ ("icbi 0,%0" : : "r"(where))
+
+/* Use this when you've modified some code, but it won't be in the
+   instruction fetch queue (or when it doesn't matter if it is). */
+#define MODIFIED_CODE_NOQUEUE(where) \
+     do { PPC_DCBST(where); PPC_SYNC; PPC_ICBI(where); } while (0)
+/* Use this when it might be in the instruction queue. */
+#define MODIFIED_CODE(where) \
+     do { PPC_DCBST(where); PPC_SYNC; PPC_ICBI(where); PPC_ISYNC; } while (0)
+
 
 /* Return nonzero iff E_MACHINE is compatible with the running host.  */
 static inline int
@@ -53,7 +74,8 @@ elf_machine_matches_host (Elf32_Half e_machine)
 }
 
 
-/* Return the link-time address of _DYNAMIC, the first value in the GOT.  */
+/* Return the link-time address of _DYNAMIC, stored as
+   the first value in the GOT. */
 static inline Elf32_Addr
 elf_machine_dynamic (void)
 {
@@ -79,11 +101,11 @@ elf_machine_load_address (void)
        get confused.
 
      asm ("bcl 20,31,0f ;"
-          "0: mflr 0 ;"
-          "lis %0,0b@ha;"
-          "addi %0,%0,0b@l;"
-          "subf %0,%0,0"
-          : "=b" (addr) : : "r0", "lr");
+	  "0: mflr 0 ;"
+	  "lis %0,0b@ha;"
+	  "addi %0,%0,0b@l;"
+	  "subf %0,%0,0"
+	  : "=b" (addr) : : "r0", "lr");
 
      doesn't work, because the linker doesn't have to (and in fact doesn't)
      update the @ha and @l references; the loader (which runs after this
@@ -134,7 +156,8 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
   if (rinfo == R_PPC_NONE)
     return;
 
-  if (sym && ELF32_ST_TYPE (sym->st_info) == STT_SECTION ||
+  assert (sym != NULL);
+  if (ELF32_ST_TYPE (sym->st_info) == STT_SECTION ||
       rinfo == R_PPC_RELATIVE)
     {
       /* Has already been relocated.  */
@@ -143,133 +166,124 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
     }
   else
     {
-      assert (sym != NULL);
-      if (rinfo == R_PPC_JMP_SLOT)
-	loadbase = (Elf32_Word) (char *) RESOLVE (&sym,
-						  version, DL_LOOKUP_NOPLT);
+      int flags;
+
+      /* We never want to use a PLT entry as the destination of a
+	 reloc, when what is being relocated is a branch. This is
+	 partly for efficiency, but mostly so we avoid loops.  */
+      if (rinfo == R_PPC_REL24 ||
+	  rinfo == R_PPC_ADDR24 ||
+	  rinfo == R_PPC_JMP_SLOT)
+	flags = DL_LOOKUP_NOPLT;
+      else if (rinfo == R_PPC_COPY)
+	flags = DL_LOOKUP_NOEXEC;
       else
-	loadbase = (Elf32_Word) (char *) RESOLVE (&sym, version, 0);
+	flags = 0;
+
+      loadbase = (Elf32_Word) (char *) (RESOLVE (&sym, version, flags));
       if (sym == NULL)
 	{
 	  /* Weak symbol that wasn't actually defined anywhere.  */
-	  assert (loadbase == 0);
+	  assert(loadbase == 0);
 	  finaladdr = reloc->r_addend;
 	}
       else
-	finaladdr = (loadbase + (Elf32_Word)(char *)sym->st_value
-		     + reloc->r_addend);
+	finaladdr = (loadbase + (Elf32_Word) (char *) sym->st_value +
+		     reloc->r_addend);
     }
 
-  switch (rinfo)
+  /* This is an if/else if chain because GCC 2.7.2.[012] turns case
+     statements into non-PIC table lookups.  When a later version
+     comes out that fixes this, this should be changed.  */
+  if (rinfo == R_PPC_ADDR16_LO)
     {
-    case R_PPC_UADDR16:
-    case R_PPC_ADDR16_LO:
-    case R_PPC_ADDR16:
       *(Elf32_Half*) reloc_addr = finaladdr;
-      break;
-
-    case R_PPC_ADDR16_HI:
+    }
+  else if (rinfo == R_PPC_ADDR16_HI)
+    {
       *(Elf32_Half*) reloc_addr = finaladdr >> 16;
-      break;
-
-    case R_PPC_ADDR16_HA:
+    }
+  else if (rinfo == R_PPC_ADDR16_HA)
+    {
       *(Elf32_Half*) reloc_addr = finaladdr + 0x8000 >> 16;
-      break;
-
-    case R_PPC_REL24:
-      {
-	Elf32_Sword delta = finaladdr - (Elf32_Word) (char *) reloc_addr;
-	assert (delta << 6 >> 6 == delta);
-	*reloc_addr = *reloc_addr & 0xfc000003 | delta & 0x3fffffc;
-      }
-      break;
-
-    case R_PPC_UADDR32:
-    case R_PPC_GLOB_DAT:
-    case R_PPC_ADDR32:
-    case R_PPC_RELATIVE:
+    }
+  else if (rinfo == R_PPC_REL24)
+    {
+      Elf32_Sword delta = finaladdr - (Elf32_Word) (char *) reloc_addr;
+      assert (delta << 6 >> 6 == delta);
+      *reloc_addr = *reloc_addr & 0xfc000003 | delta & 0x3fffffc;
+    }
+  else if (rinfo == R_PPC_UADDR32 ||
+      rinfo == R_PPC_GLOB_DAT ||
+      rinfo == R_PPC_ADDR32 ||
+      rinfo == R_PPC_RELATIVE)
+    {
       *reloc_addr = finaladdr;
-      break;
-
-    case R_PPC_ADDR24:
+    }
+  else if (rinfo == R_PPC_ADDR24)
+    {
+      assert (finaladdr << 6 >> 6 == finaladdr);
       *reloc_addr = *reloc_addr & 0xfc000003 | finaladdr & 0x3fffffc;
-      break;
-
-    case R_PPC_REL14_BRTAKEN:
-    case R_PPC_REL14_BRNTAKEN:
-    case R_PPC_REL14:
-      {
-	Elf32_Sword delta = finaladdr - (Elf32_Word) (char *) reloc_addr;
-	*reloc_addr = *reloc_addr & 0xffdf0003 | delta & 0xfffc;
-	if (rinfo == R_PPC_REL14_BRTAKEN && delta >= 0 ||
-	    rinfo == R_PPC_REL14_BRNTAKEN && delta < 0)
-	  *reloc_addr |= 0x00200000;
-      }
-      break;
-
-    case R_PPC_COPY:
-      {
-	/* Can't use memcpy (because we can't call any functions here).  */
-	int i;
-	for (i = 0; i < sym->st_size; ++i)
-	  ((unsigned char *) reloc_addr)[i] =
-	    ((unsigned char *)finaladdr)[i];
-      }
-      break;
-
-    case R_PPC_REL32:
+    }
+  else if (rinfo == R_PPC_COPY)
+    {
+      /* Memcpy is safe to use here, because ld.so doesn't have any
+	 COPY relocs (it's self-contained).  */
+      memcpy (reloc_addr, (char *) finaladdr, sym->st_size);
+    }
+  else if (rinfo == R_PPC_REL32)
+    {
       *reloc_addr = finaladdr - (Elf32_Word) (char *) reloc_addr;
-      break;
-
-    case R_PPC_JMP_SLOT:
-      if (finaladdr <= 0x01fffffc || finaladdr >= 0xfe000000)
-	*reloc_addr = OPCODE_BA (finaladdr);
+    }
+  else if (rinfo == R_PPC_JMP_SLOT)
+    {
+      Elf32_Sword delta = finaladdr - (Elf32_Word) (char *) reloc_addr;
+      if (delta << 6 >> 6 == delta)
+	*reloc_addr = OPCODE_B(delta);
+      else if (finaladdr <= 0x01fffffc || finaladdr >= 0xfe000000)
+	*reloc_addr = OPCODE_BA(finaladdr);
       else
 	{
-	  Elf32_Sword delta = finaladdr - (Elf32_Word) (char *) reloc_addr;
-	  if (delta <= 0x01fffffc && delta >= 0xfe000000)
-	    *reloc_addr = OPCODE_B (delta);
+	  Elf32_Word *plt = (Elf32_Word *)((char *)map->l_addr +
+					   map->l_info[DT_PLTGOT]->d_un.d_val);
+	  Elf32_Word index = (reloc_addr - plt - PLT_INITIAL_ENTRY_WORDS)/2;
+	  Elf32_Word offset = index * 2 + PLT_INITIAL_ENTRY_WORDS;
+
+	  if (index >= PLT_DOUBLE_SIZE)
+	    {
+	     /* Slots greater than or equal to 2^13 have 4 words
+		available instead of two.  */
+	      plt[offset  ] = OPCODE_LI (11,finaladdr);
+	      plt[offset+1] = OPCODE_ADDIS (11,11,finaladdr + 0x8000 >> 16);
+	      plt[offset+2] = OPCODE_MTCTR (11);
+	      plt[offset+3] = OPCODE_BCTR ();
+	    }
 	  else
 	    {
-	      Elf32_Word *plt =
-		(Elf32_Word *) ((char *) map->l_addr
-				+ map->l_info[DT_PLTGOT]->d_un.d_val);
-	      Elf32_Word index =((reloc_addr - plt - PLT_INITIAL_ENTRY_WORDS)
-				 / 2);
-	      int num_plt_entries = (map->l_info[DT_PLTRELSZ]->d_un.d_val
-				     / sizeof (Elf32_Rela));
-	      int rel_offset_words = (PLT_INITIAL_ENTRY_WORDS
-				      + num_plt_entries * 2);
-
-	      if (index >= (1 << 13))
-		{
-		  /* Indexes greater than or equal to 2^13 have 4
-		     words available instead of two.  */
-		  plt[index * 2 + PLT_INITIAL_ENTRY_WORDS] =
-		    OPCODE_LI (11, finaladdr);
-		  plt[index * 2 + 1 + PLT_INITIAL_ENTRY_WORDS] =
-		    OPCODE_ADDIS (11, 11, finaladdr + 0x8000 >> 16);
-		  plt[index * 2 + 2 + PLT_INITIAL_ENTRY_WORDS] =
-		    OPCODE_MTCTR (11);
-		  plt[index * 2 + 2 + PLT_INITIAL_ENTRY_WORDS] =
-		    OPCODE_BCTR ();
-		}
-	      else
-		{
-		  plt[index * 2 + PLT_INITIAL_ENTRY_WORDS] =
-		    OPCODE_LI (11, index * 4);
-		  plt[index * 2 + 1 + PLT_INITIAL_ENTRY_WORDS] =
-		    OPCODE_B(-(4 * (index * 2 + 1 + PLT_INITIAL_ENTRY_WORDS
-				    + PLT_LONGBRANCH_ENTRY_WORDS)));
-		  plt[index + rel_offset_words] = finaladdr;
-		}
+	      Elf32_Word num_plt_entries;
+	      Elf32_Word rel_offset_words;
+
+	      num_plt_entries = (map->l_info[DT_PLTRELSZ]->d_un.d_val
+				 / sizeof(Elf32_Rela));
+	      rel_offset_words = PLT_DATA_START_WORDS (num_plt_entries);
+
+	      plt[offset  ] = OPCODE_LI (11,index * 4);
+	      plt[offset+1] = OPCODE_B (-(4 * (offset + 1
+					       - PLT_LONGBRANCH_ENTRY_WORDS)));
+	      plt[index + rel_offset_words] = finaladdr;
 	    }
 	}
-      break;
-
-    default:
-      assert (! "unexpected dynamic reloc type");
+      MODIFIED_CODE(reloc_addr);
     }
+  else
+    assert (! "unexpected dynamic reloc type");
+
+  if (rinfo == R_PPC_ADDR16_LO ||
+      rinfo == R_PPC_ADDR16_HI ||
+      rinfo == R_PPC_ADDR16_HA ||
+      rinfo == R_PPC_REL24 ||
+      rinfo == R_PPC_ADDR24)
+    MODIFIED_CODE_NOQUEUE (reloc_addr);
 }
 
 #define ELF_MACHINE_NO_REL 1
@@ -282,64 +296,58 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
 
 /* Set up the loaded object described by L so its unrelocated PLT
    entries will jump to the on-demand fixup code in dl-runtime.c.  */
-
-/* This code does not presently work if there are more than 2^13 PLT
-   entries. */
 static inline void
 elf_machine_runtime_setup (struct link_map *map, int lazy)
 {
-  Elf32_Word *plt;
-  int i;
-  Elf32_Word num_plt_entries;
-  Elf32_Word rel_offset_words;
-  extern void _dl_runtime_resolve (void);
-
   if (map->l_info[DT_JMPREL])
     {
+      int i;
       /* Fill in the PLT. Its initial contents are directed to a
 	 function earlier in the PLT which arranges for the dynamic
 	 linker to be called back.  */
-      plt = (Elf32_Word *) ((char *) map->l_addr +
-			    map->l_info[DT_PLTGOT]->d_un.d_val);
-      num_plt_entries = (map->l_info[DT_PLTRELSZ]->d_un.d_val
-			 / sizeof (Elf32_Rela));
-      rel_offset_words = PLT_INITIAL_ENTRY_WORDS + num_plt_entries * 2;
+      Elf32_Word *plt = (Elf32_Word *) ((char *) map->l_addr
+					+ map->l_info[DT_PLTGOT]->d_un.d_val);
+      Elf32_Word num_plt_entries = (map->l_info[DT_PLTRELSZ]->d_un.d_val
+				    / sizeof (Elf32_Rela));
+      Elf32_Word rel_offset_words = PLT_DATA_START_WORDS (num_plt_entries);
+      extern void _dl_runtime_resolve (void);
+      Elf32_Word size_modified;
 
       if (lazy)
 	for (i = 0; i < num_plt_entries; i++)
-	  if (i >= (1 << 13))
-	  {
-	    plt[i * 2 + (i - (1 << 13)) * 2 + PLT_INITIAL_ENTRY_WORDS] =
-	      OPCODE_LI (11, i * 4);
-	    plt[i * 2 + (i - (1 << 13)) * 2 + 1 + PLT_INITIAL_ENTRY_WORDS] =
-	      OPCODE_ADDIS (11, 11, i * 4 + 0x8000 >> 16);
-	    plt[i * 2 + (i - (1 << 13)) * 2 + 2 + PLT_INITIAL_ENTRY_WORDS] =
-	      OPCODE_B (-(4 * ( i * 2 + 1 + PLT_INITIAL_ENTRY_WORDS)));
-	  }
-	  else
-	  {
-	    plt[i * 2 + PLT_INITIAL_ENTRY_WORDS] = OPCODE_LI (11, i * 4);
-	    plt[i * 2 + 1 + PLT_INITIAL_ENTRY_WORDS] =
-	      OPCODE_B (-(4 * (i * 2 + 1 + PLT_INITIAL_ENTRY_WORDS)));
-	  }
-
-      /* Multiply index of entry, by 0xC.  */
-      plt[0] = OPCODE_SLWI (12, 11, 1);
-      plt[1] = OPCODE_ADD (11, 12, 11);
-      if ((Elf32_Word) (char *) _dl_runtime_resolve <= 0x01fffffc ||
-	  (Elf32_Word) (char *) _dl_runtime_resolve >= 0xfe000000)
 	{
-	  plt[2] = OPCODE_LI (12, (Elf32_Word) (char *) map);
-	  plt[3] = OPCODE_ADDIS (12, 12,
-				 (Elf32_Word) (char *) map + 0x8000 >> 16);
-	  plt[4] = OPCODE_BA ((Elf32_Word) (char *) _dl_runtime_resolve);
+	  Elf32_Word offset = PLT_ENTRY_START_WORDS(i);
+
+	  if (i >= PLT_DOUBLE_SIZE)
+	    {
+	      plt[offset	] = OPCODE_LI (11, i * 4);
+	      plt[offset+1] = OPCODE_ADDIS (11, 11, i * 4 + 0x8000 >> 16);
+	      plt[offset+2] = OPCODE_B (-(4 * (offset + 2)));
+	    }
+	  else
+	    {
+	      plt[offset	] = OPCODE_LI (11, i * 4);
+	      plt[offset+1] = OPCODE_B(-(4 * (offset + 1)));
+	    }
+
+	  /* Multiply index of entry, by 0xC.  */
+	  plt[0] = OPCODE_SLWI (12, 11, 1);
+	  plt[1] = OPCODE_ADD (11, 12, 11);
+	  if ((Elf32_Word) (char *) _dl_runtime_resolve <= 0x01fffffc
+	      || (Elf32_Word) (char *) _dl_runtime_resolve >= 0xfe000000)
+	    {
+	      plt[2] = OPCODE_LI (12, (Elf32_Word) (char *) map);
+	      plt[3] = OPCODE_ADDIS (12, 12,
+				     (Elf32_Word) (char *) map + 0x8000 >> 16);
+	      plt[4] = OPCODE_BA ((Elf32_Word) (char *) _dl_runtime_resolve);
+	    }
 	}
       else
 	{
 	  plt[2] = OPCODE_LI (12, (Elf32_Word) (char *) _dl_runtime_resolve);
-	  plt[3] = OPCODE_ADDIS (12, 12, 0x8000 +
-				 ((Elf32_Word) (char *) _dl_runtime_resolve
-				  >> 16));
+	  plt[3] = OPCODE_ADDIS(12, 12, 0x8000 +
+				((Elf32_Word) (char *) _dl_runtime_resolve
+				 >> 16));
 	  plt[4] = OPCODE_MTCTR (12);
 	  plt[5] = OPCODE_LI (12, (Elf32_Word) (char *) map);
 	  plt[6] = OPCODE_ADDIS (12, 12, ((Elf32_Word) (char *) map
@@ -347,21 +355,28 @@ elf_machine_runtime_setup (struct link_map *map, int lazy)
 	  plt[7] = OPCODE_BCTR ();
 	}
       plt[PLT_LONGBRANCH_ENTRY_WORDS] =
-	OPCODE_ADDIS (11, 11, ((Elf32_Word) (char*) (plt+rel_offset_words)
-			       + 0x8000 >> 16));
+	OPCODE_ADDIS (11, 11, (Elf32_Word) (char*) (plt + rel_offset_words)
+		      + 0x8000 >> 16);
       plt[PLT_LONGBRANCH_ENTRY_WORDS+1] =
-	OPCODE_LWZ (11, (Elf32_Word) (char*) (plt + rel_offset_words), 11);
+	OPCODE_LWZ(11,(Elf32_Word)(char*)(plt+rel_offset_words),11);
       plt[PLT_LONGBRANCH_ENTRY_WORDS+2] = OPCODE_MTCTR (11);
       plt[PLT_LONGBRANCH_ENTRY_WORDS+3] = OPCODE_BCTR ();
+
+      size_modified = lazy ? rel_offset_words : PLT_INITIAL_ENTRY_WORDS;
+      /* Now we need to keep the caches in sync.  */
+      for (i = 0; i < size_modified; i+=8)
+	PPC_DCBST (plt + i);
+      PPC_SYNC;
+      for (i = 0; i < size_modified; i+=8)
+	PPC_ICBI (plt + i);
+      PPC_ISYNC;
     }
 }
 
 static inline void
 elf_machine_lazy_rel (struct link_map *map, const Elf32_Rela *reloc)
 {
-  if (ELF32_R_TYPE (reloc->r_info) != R_PPC_JMP_SLOT)
-      assert (! "unexpected PLT reloc type");
-
+  assert (ELF32_R_TYPE (reloc->r_info) == R_PPC_JMP_SLOT);
   /* elf_machine_runtime_setup handles this. */
 }
 
@@ -369,17 +384,23 @@ elf_machine_lazy_rel (struct link_map *map, const Elf32_Rela *reloc)
 #define elf_machine_relplt elf_machine_rela
 
   /* This code is used in dl-runtime.c to call the `fixup' function
-     and then redirect to the address it returns.  */
+     and then redirect to the address it returns. It is called
+     from code built in the PLT by elf_machine_runtime_setup. */
 #define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\
 	.section \".text\"
+	.align 2
 	.globl _dl_runtime_resolve
+	.type _dl_runtime_resolve,@function
 _dl_runtime_resolve:
+ # We need to save the registers used to pass parameters.
+ # We build a stack frame to put them in.
 	stwu 1,-48(1)
 	mflr 0
 	stw 3,16(1)
 	stw 4,20(1)
 	stw 0,52(1)
 	stw 5,24(1)
+ # We also need to save some of the condition register fields.
 	mfcr 0
 	stw 6,28(1)
 	stw 7,32(1)
@@ -387,10 +408,13 @@ _dl_runtime_resolve:
 	stw 9,40(1)
 	stw 10,44(1)
 	stw 0,12(1)
+ # The code that calls this has put parameters for `fixup' in r12 and r11.
 	mr 3,12
 	mr 4,11
 	bl fixup
+ # 'fixup' returns the address we want to branch to.
 	mtctr 3
+ # Put the registers back...
 	lwz 0,52(1)
 	lwz 10,44(1)
 	lwz 9,40(1)
@@ -403,37 +427,40 @@ _dl_runtime_resolve:
 	lwz 5,24(1)
 	lwz 4,20(1)
 	lwz 3,16(1)
+ # ...unwind the stack frame, and jump to the PLT entry we updated.
 	addi 1,1,48
 	bctr
+0:
+	.size	 _dl_runtime_resolve,0b-_dl_runtime_resolve
+ # undo '.section text'.
+	.previous
 ");
 
 /* Initial entry point code for the dynamic linker.
    The C function `_dl_start' is the real entry point;
-   its return value is the user program's entry point.  */
-
-/* FIXME! We don't make provision for calling _dl_fini,
-   because Linux/PPC is somewhat broken. */
+   its return value is the user program's entry point.	*/
 #define RTLD_START \
 asm ("\
 	.text
-        .align 2
+	.align 2
 	.globl _start
-        .type _start,@function
+	.type _start,@function
 _start:
  # We start with the following on the stack, from top:
  # argc (4 bytes)
  # arguments for program (terminated by NULL)
  # environment variables (terminated by NULL)
  # arguments for the program loader
+ # FIXME: perhaps this should do the same trick as elf/start.c?
 
  # Call _dl_start with one parameter pointing at argc
-        mr 3,1
+	mr 3,1
  #  (we have to frob the stack pointer a bit to allow room for
  #   _dl_start to save the link register)
-        li 4,0
-        addi 1,1,-16
-        stw 4,0(1)
-        bl _dl_start@local
+	li 4,0
+	addi 1,1,-16
+	stw 4,0(1)
+	bl _dl_start@local
 
  # Now, we do our main work of calling initialisation procedures.
  # The ELF ABI doesn't say anything about parameters for these,
@@ -442,10 +469,10 @@ _start:
  # passed by value!).
 
  #  put our GOT pointer in r31
-        bl _GLOBAL_OFFSET_TABLE_-4@local
-        mflr 31
+	bl _GLOBAL_OFFSET_TABLE_-4@local
+	mflr 31
  #  the address of _start in r30
-        mr 30,3
+	mr 30,3
  #  &_dl_argc in 29, &_dl_argv in 27, and _dl_default_scope in 28
 	lwz 28,_dl_default_scope@got(31)
 	lwz 29,_dl_argc@got(31)
@@ -499,13 +526,19 @@ _start:
 	mtlr 0
  # and also clear _dl_starting_up
 	lwz 26,_dl_starting_up@got(31)
-	stw 0,0(3)
+	stw 0,0(26)
  # go do it!
 	bctr
+0:
+	.size	 _start,0b-_start
+ # undo '.section text'.
+	.previous
 ");
 
-#define ELF_PREFERRED_ADDRESS_DATA static ElfW(Addr) _dl_preferred_address = 0;
-#define ELF_PREFERRED_ADDRESS(loader, maplength, mapstartpref) \
+#define ELF_PREFERRED_ADDRESS_DATA					      \
+static ElfW(Addr) _dl_preferred_address = 0;
+
+#define ELF_PREFERRED_ADDRESS(loader, maplength, mapstartpref)		      \
 ( {									      \
    ElfW(Addr) prefd;							      \
    if (mapstartpref != 0 && _dl_preferred_address == 0)			      \
@@ -516,13 +549,14 @@ _start:
      prefd = 0;								      \
    else									      \
      prefd = _dl_preferred_address =					      \
-	  (_dl_preferred_address - maplength - 0x10000) &		      \
-           ~(_dl_pagesize - 1);						      \
+       ((_dl_preferred_address - maplength - 0x10000)			      \
+	& ~(_dl_pagesize - 1));						      \
    prefd;								      \
 } )
-#define ELF_FIXED_ADDRESS(loader, mapstart) \
+
+#define ELF_FIXED_ADDRESS(loader, mapstart)				      \
 ( {									      \
-   if (mapstart != 0 && _dl_preferred_address == 0)			      \
+   if (mapstart != 0 && _dl_preferred_address < mapstart)		      \
      _dl_preferred_address = mapstart;					      \
 } )
 
diff --git a/sysdeps/powerpc/elf/start.c b/sysdeps/powerpc/elf/start.c
index 9b1cf1c026..001d6aa97c 100644
--- a/sysdeps/powerpc/elf/start.c
+++ b/sysdeps/powerpc/elf/start.c
@@ -26,22 +26,27 @@
 /* Just a little assembler stub before gcc gets its hands on our
    stack pointer... */
 asm ("\
-	.text
+	.section \".text\"
+	.align 2
 	.globl _start
 _start:
  # save the stack pointer, in case we're statically linked under Linux
-        mr 8,1
+	mr 8,1
  # set up an initial stack frame, and clear the LR
-        addi 1,1,-16
-        clrrwi 1,1,4
-        li 0,0
-        stw 0,0(1)
-        mtlr 0
+	addi 1,1,-16
+	clrrwi 1,1,4
+	li 0,0
+	stw 0,0(1)
+	mtlr 0
  # set r13 to point at the 'small data area'
-        lis 13,_SDA_BASE_@ha
-        addi 13,13,_SDA_BASE_@l
+	lis 13,_SDA_BASE_@ha
+	addi 13,13,_SDA_BASE_@l
  # and continue below.
-        b __start1
+	b __start1
+0:
+	.size	 _start,0b-_start
+ # undo '.section text'.
+	.previous
 ");
 
 /* Define a symbol for the first piece of initialized data.  */
@@ -53,38 +58,46 @@ weak_alias (__data_start, data_start)
 void (*_mach_init_routine) (void);
 void (*_thread_init_routine) (void);
 
-void __libc_init_first (int argc, char **argv, char **envp);
-int main (int argc, char **argv, char **envp, void *auxvec);
+extern void __libc_init_first (int argc, char **argv, char **envp);
+extern int main (int argc, char **argv, char **envp, void *auxvec);
 #ifdef HAVE_INITFINI
-void _init (void);
-void _fini (void);
+extern void _init (void);
+extern void _fini (void);
 #endif
 
-
+#if 0
+/* I'd like to say this, but it causes GCC to strip the whole procedure
+   from the object file (this is sort of reasonable, because you've told
+   GCC that the procedure is unused). :-( */
 static void __start1(int argc, char **argv, char **envp,
-		     void *auxvec, void (*exitfn) (void), char **arguments)
+		     void *auxvec, void (*exitfn) (void),
+		     char **stack_on_entry)
      __attribute__ ((unused));
-static void
+
+static
+#endif
+void
 __start1(int argc, char **argv, char **envp,
 	 void *auxvec, void (*exitfn) (void),
-	 char **arguments)
+	 char **stack_on_entry)
 {
   /* the PPC SVR4 ABI says that the top thing on the stack will
      be a NULL pointer, so if not we assume that we're being called
-     as a statically-linked program by Linux. */
-  int abi_compliant_startup = *arguments == NULL;
-
-  if (!abi_compliant_startup)
-  {
-    argc = *(int *) arguments;
-    argv = arguments+1;
-    envp = argv+argc+1;
-    auxvec = envp;
-    while (auxvec != NULL)
-      auxvec++;
-    auxvec++;
-    exitfn = NULL;
-  }
+     as a statically-linked program by Linux...	 */
+  if (*stack_on_entry != NULL)
+    {
+      /* ...in which case, we have argc as the top thing on the
+	 stack, followed by argv (NULL-terminated), envp (likewise),
+	 and the auxilary vector.  */
+      argc = *(int *) stack_on_entry;
+      argv = stack_on_entry + 1;
+      envp = argv + argc + 1;
+      auxvec = envp;
+      while (*(char **) auxvec != NULL)
+	++auxvec;
+      ++auxvec;
+      exitfn = NULL;
+    }
 
   if (exitfn != NULL)
     atexit (exitfn);
diff --git a/sysdeps/powerpc/setjmp.S b/sysdeps/powerpc/setjmp.S
index a2c0b8c53d..755ef6504c 100644
--- a/sysdeps/powerpc/setjmp.S
+++ b/sysdeps/powerpc/setjmp.S
@@ -62,5 +62,9 @@ ENTRY (__sigsetjmp)
 	stfd 30,((JB_FPRS+16*2)*4)(3)
 	stw 31,((JB_GPRS+17)*4)(3)
 	stfd 31,((JB_FPRS+17*2)*4)(3)
+#ifdef PIC
+	b __sigjmp_save@plt
+#else
 	b __sigjmp_save
+#endif
 END (__sigsetjmp)
diff --git a/sysdeps/unix/bsd/Dist b/sysdeps/unix/bsd/Dist
index 9e0e553aa7..ab3c4f491e 100644
--- a/sysdeps/unix/bsd/Dist
+++ b/sysdeps/unix/bsd/Dist
@@ -1 +1,4 @@
-bsdtty.h 
+setrgid.c
+setruid.c
+bsdstat.h
+bsdtty.h
diff --git a/sysdeps/unix/sysv/Dist b/sysdeps/unix/sysv/Dist
index 14343b6b6f..6ad8e0f653 100644
--- a/sysdeps/unix/sysv/Dist
+++ b/sysdeps/unix/sysv/Dist
@@ -1 +1,2 @@
+direct.h
 sysv_termio.h
diff --git a/sysdeps/unix/sysv/linux/Dist b/sysdeps/unix/sysv/linux/Dist
index 7b94300c6a..d4b6bac217 100644
--- a/sysdeps/unix/sysv/linux/Dist
+++ b/sysdeps/unix/sysv/linux/Dist
@@ -21,6 +21,7 @@ netinet/igmp.h
 netinet/in_systm.h
 netinet/ip_fw.h
 netinet/ip_icmp.h
+netinet/tcp.h
 netinet/udp.h
 netipx/ipx.h
 nfs/nfs.h
diff --git a/sysdeps/unix/sysv/linux/alpha/fcntlbits.h b/sysdeps/unix/sysv/linux/alpha/fcntlbits.h
index faf198393f..6e1c843ccb 100644
--- a/sysdeps/unix/sysv/linux/alpha/fcntlbits.h
+++ b/sysdeps/unix/sysv/linux/alpha/fcntlbits.h
@@ -27,7 +27,6 @@
 #ifdef __USE_GNU
 #define	O_READ		O_RDONLY /* Open for reading.  */
 #define O_WRITE		O_WRONLY /* Open for writing.  */
-#define O_NORW		0	/* Open without R/W access.  */
 #endif
 /* open/fcntl - O_SYNC is only implemented on blocks devices and on files
    located on an ext2 file system */
diff --git a/sysdeps/unix/sysv/linux/fcntlbits.h b/sysdeps/unix/sysv/linux/fcntlbits.h
index fdc67ce4eb..f6ba880459 100644
--- a/sysdeps/unix/sysv/linux/fcntlbits.h
+++ b/sysdeps/unix/sysv/linux/fcntlbits.h
@@ -27,7 +27,6 @@
 #ifdef __USE_GNU
 #define	O_READ		O_RDONLY /* Open for reading.  */
 #define O_WRITE		O_WRONLY /* Open for writing.  */
-#define O_NORW		0	/* Open without R/W access.  */
 #endif
 /* open/fcntl - O_SYNC is only implemented on blocks devices and on files
    located on an ext2 file system */
diff --git a/sysdeps/unix/sysv/linux/net/if_ppp.h b/sysdeps/unix/sysv/linux/net/if_ppp.h
index 567dccebe3..0f2a979cd6 100644
--- a/sysdeps/unix/sysv/linux/net/if_ppp.h
+++ b/sysdeps/unix/sysv/linux/net/if_ppp.h
@@ -51,7 +51,7 @@ __BEGIN_DECLS
 
 #define	PPP_MTU		1500	/* Default MTU (size of Info field) */
 #define PPP_MAXMRU	65000	/* Largest MRU we allow */
-#define PPP_VERSION	"2.3.0"
+#define PPP_VERSION	"2.2.0"
 #define PPP_MAGIC	0x5002	/* Magic value for the ppp structure */
 #define PROTO_IPX	0x002b	/* protocol numbers */
 #define PROTO_DNA_RT    0x0027  /* DNA Routing */
diff --git a/sysdeps/unix/sysv/linux/powerpc/clone.S b/sysdeps/unix/sysv/linux/powerpc/clone.S
index e5fa16d8c5..0afd0717f4 100644
--- a/sysdeps/unix/sysv/linux/powerpc/clone.S
+++ b/sysdeps/unix/sysv/linux/powerpc/clone.S
@@ -71,4 +71,8 @@ child:
 badargs:
 	li 3,-EINVAL
 error:
+#ifdef PIC
+	b __syscall_error@plt
+#else
 	b __syscall_error
+#endif
diff --git a/sysdeps/unix/sysv/linux/powerpc/dl-sysdep.c b/sysdeps/unix/sysv/linux/powerpc/dl-sysdep.c
new file mode 100644
index 0000000000..eb732d6fb1
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/dl-sysdep.c
@@ -0,0 +1,237 @@
+/* Operating system support for run-time dynamic linker.  Linux/PPC version.
+   Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <elf.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <link.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <string.h>
+
+
+extern int _dl_argc;
+extern char **_dl_argv;
+extern char **_environ;
+extern size_t _dl_pagesize;
+extern void _end;
+extern void _start (void);
+
+int __libc_enable_secure;
+int __libc_multiple_libcs;	/* Defining this here avoids the inclusion
+				   of init-first.  */
+
+ElfW(Addr)
+_dl_sysdep_start (void **start_argptr,
+		  void (*dl_main) (const ElfW(Phdr) *phdr, ElfW(Word) phnum,
+				   ElfW(Addr) *user_entry))
+{
+  const ElfW(Phdr) *phdr = NULL;
+  ElfW(Word) phnum = 0;
+  ElfW(Addr) user_entry;
+  ElfW(auxv_t) *av;
+  uid_t uid = 0;
+  uid_t euid = 0;
+  gid_t gid = 0;
+  gid_t egid = 0;
+  unsigned int seen;
+
+  user_entry = (ElfW(Addr)) &_start;
+  _dl_argc = *(long *) start_argptr;
+  _dl_argv = (char **) start_argptr + 1;
+  _environ = &_dl_argv[_dl_argc + 1];
+  start_argptr = (void **) _environ;
+  while (*start_argptr)
+    ++start_argptr;
+  ++start_argptr;
+
+  if (*start_argptr == 0 &&
+      ((unsigned)(char *)start_argptr & 0xF) != 0)
+    {
+      unsigned test_sap = (int)(char *)start_argptr;
+      test_sap = test_sap + 0xF & ~0xF;
+      if (*(long *)(char *)test_sap == AT_PHDR)
+	start_argptr = (void **)(char *)test_sap;
+    }
+
+  seen = 0;
+#define M(type) (1 << (type))
+
+  for (av = (void *) start_argptr;
+       av->a_type != AT_NULL;
+       seen |= M ((++av)->a_type))
+    switch (av->a_type)
+      {
+      case AT_PHDR:
+	phdr = av->a_un.a_ptr;
+	break;
+      case AT_PHNUM:
+	phnum = av->a_un.a_val;
+	break;
+      case AT_PAGESZ:
+	_dl_pagesize = av->a_un.a_val;
+	break;
+      case AT_ENTRY:
+	user_entry = av->a_un.a_val;
+	break;
+      case AT_UID:
+	uid = av->a_un.a_val;
+	break;
+      case AT_GID:
+	gid = av->a_un.a_val;
+	break;
+      case AT_EUID:
+	euid = av->a_un.a_val;
+	break;
+      case AT_EGID:
+	egid = av->a_un.a_val;
+	break;
+      }
+
+  /* Linux doesn't provide us with any of these values on the stack
+     when the dynamic linker is run directly as a program.  */
+
+#define SEE(UID, uid) if ((seen & M (AT_##UID)) == 0) uid = __get##uid ()
+  SEE (UID, uid);
+  SEE (GID, gid);
+  SEE (EUID, euid);
+  SEE (EGID, egid);
+
+
+  __libc_enable_secure = uid != euid || gid != egid;
+
+  __brk (0);			/* Initialize the break.  */
+
+  if (__sbrk (0) == &_end)
+    {
+      /* The dynamic linker was run as a program, and so the initial break
+	 starts just after our bss, at &_end.  The malloc in dl-minimal.c
+	 will consume the rest of this page, so tell the kernel to move the
+	 break up that far.  When the user program examines its break, it
+	 will see this new value and not clobber our data.  */
+      size_t pg = __getpagesize ();
+
+      __sbrk (pg - ((&_end - (void *) 0) & pg));
+      __sbrk (pg - ((&_end - (void *) 0) & (pg - 1)));
+    }
+
+  (*dl_main) (phdr, phnum, &user_entry);
+  return user_entry;
+}
+
+void
+_dl_sysdep_start_cleanup (void)
+{
+}
+
+#ifndef MAP_ANON
+/* This is only needed if the system doesn't support MAP_ANON.  */
+
+int
+_dl_sysdep_open_zero_fill (void)
+{
+  return __open ("/dev/zero", O_RDONLY);
+}
+#endif
+
+/* Read the whole contents of FILE into new mmap'd space with given
+   protections.  *SIZEP gets the size of the file.  */
+
+void *
+_dl_sysdep_read_whole_file (const char *file, size_t *sizep, int prot)
+{
+  void *result;
+  struct stat st;
+  int fd = __open (file, O_RDONLY);
+  if (fd < 0)
+    return NULL;
+  if (__fstat (fd, &st) < 0)
+    result = NULL;
+  else
+    {
+      /* Map a copy of the file contents.  */
+      result = __mmap (0, st.st_size, prot,
+#ifdef MAP_COPY
+		       MAP_COPY
+#else
+		       MAP_PRIVATE
+#endif
+#ifdef MAP_FILE
+		       | MAP_FILE
+#endif
+		       , fd, 0);
+      if (result == (void *) -1)
+	result = NULL;
+      else
+	*sizep = st.st_size;
+    }
+  __close (fd);
+  return result;
+}
+
+void
+_dl_sysdep_fatal (const char *msg, ...)
+{
+  va_list ap;
+
+  va_start (ap, msg);
+  do
+    {
+      size_t len = strlen (msg);
+      __write (STDERR_FILENO, msg, len);
+      msg = va_arg (ap, const char *);
+    } while (msg);
+  va_end (ap);
+
+  _exit (127);
+}
+
+
+void
+_dl_sysdep_error (const char *msg, ...)
+{
+  va_list ap;
+
+  va_start (ap, msg);
+  do
+    {
+      size_t len = strlen (msg);
+      __write (STDERR_FILENO, msg, len);
+      msg = va_arg (ap, const char *);
+    } while (msg);
+  va_end (ap);
+}
+
+
+void
+_dl_sysdep_message (const char *msg, ...)
+{
+  va_list ap;
+
+  va_start (ap, msg);
+  do
+    {
+      size_t len = strlen (msg);
+      __write (STDOUT_FILENO, msg, len);
+      msg = va_arg (ap, const char *);
+    } while (msg);
+  va_end (ap);
+}
diff --git a/sysdeps/unix/sysv/linux/powerpc/kernel_termios.h b/sysdeps/unix/sysv/linux/powerpc/kernel_termios.h
new file mode 100644
index 0000000000..acf62a42ca
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/kernel_termios.h
@@ -0,0 +1,25 @@
+#ifndef _SYS_KERNEL_TERMIOS_H
+#define _SYS_KERNEL_TERMIOS_H 1
+/* The following corresponds to the values from the Linux 2.0.28 kernel.  */
+
+/* We need the definition of tcflag_t, cc_t, and speed_t.  */
+#include <termbits.h>
+
+#define __KERNEL_NCCS 19
+
+struct __kernel_termios
+  {
+    tcflag_t c_iflag;		/* input mode flags */
+    tcflag_t c_oflag;		/* output mode flags */
+    tcflag_t c_cflag;		/* control mode flags */
+    tcflag_t c_lflag;		/* local mode flags */
+    cc_t c_cc[__KERNEL_NCCS];	/* control characters */
+    cc_t c_line;		/* line discipline */
+    int c_ispeed;               /* input speed */
+    int c_ospeed;               /* output speed */
+  };
+
+#define _HAVE_C_ISPEED 1
+#define _HAVE_C_OSPEED 1
+
+#endif /* sys/kernel_termios.h */
diff --git a/sysdeps/unix/sysv/linux/powerpc/socket.S b/sysdeps/unix/sysv/linux/powerpc/socket.S
index 32bb8f64cd..12417faac6 100644
--- a/sysdeps/unix/sysv/linux/powerpc/socket.S
+++ b/sysdeps/unix/sysv/linux/powerpc/socket.S
@@ -76,7 +76,11 @@ ENTRY(P(__,socket))
 	DO_CALL(SYS_ify(socketcall))
 	addi 1,1,48
 	bnslr
+#ifdef PIC
+	b __syscall_error@plt
+#else
 	b __syscall_error
+#endif
 
 PSEUDO_END (P(__,socket))
 
diff --git a/sysdeps/unix/sysv/linux/powerpc/statbuf.h b/sysdeps/unix/sysv/linux/powerpc/statbuf.h
new file mode 100644
index 0000000000..5be5736931
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/statbuf.h
@@ -0,0 +1,79 @@
+/* Copyright (C) 1992, 1995, 1996, 1997 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	_STATBUF_H
+#define	_STATBUF_H	1
+
+/* Versions of the `struct stat' data structure.  */
+#define _STAT_VER_LINUX		1
+#define _STAT_VER_SVR4		2
+#define _STAT_VER		_STAT_VER_LINUX	/* The one defined below.  */
+
+/* Versions of the `xmknod' interface.  */
+#define _MKNOD_VER_LINUX	1
+#define _MKNOD_VER_SVR4		2
+#define _MKNOD_VER		_MKNOD_VER_LINUX /* The bits defined below.  */
+
+
+struct stat
+  {
+    unsigned int st_dev;		/* Device.  */
+    unsigned int st_ino;		/* File serial number.	*/
+    unsigned int st_mode;		/* File mode.  */
+    unsigned short int st_nlink;	/* Link count.  */
+    unsigned int st_uid;		/* User ID of the file's owner.	*/
+    unsigned int st_gid;		/* Group ID of the file's group.*/
+    unsigned int st_rdev;		/* Device number, if device.  */
+    long int st_size;			/* Size of file, in bytes.  */
+    unsigned long int st_blksize;	/* Optimal block size for I/O.  */
+#define	_STATBUF_ST_BLKSIZE		/* Tell code we have this member.  */
+
+    unsigned long int st_blocks;	/* Number of 512-byte blocks allocated.  */
+    unsigned long int st_atime;		/* Time of last access.  */
+    unsigned long int __unused1;
+    unsigned long int st_mtime;		/* Time of last modification.  */
+    unsigned long int __unused2;
+    unsigned long int st_ctime;		/* Time of last status change.  */
+    unsigned long int __unused3;
+    unsigned long int __unused4;
+    unsigned long int __unused5;
+  };
+
+/* Encoding of the file mode.  */
+
+#define	__S_IFMT	0170000	/* These bits determine file type.  */
+
+/* File types.  */
+#define	__S_IFDIR	0040000	/* Directory.  */
+#define	__S_IFCHR	0020000	/* Character device.  */
+#define	__S_IFBLK	0060000	/* Block device.  */
+#define	__S_IFREG	0100000	/* Regular file.  */
+#define	__S_IFIFO	0010000	/* FIFO.  */
+#define	__S_IFLNK	0120000	/* Symbolic link.  */
+#define	__S_IFSOCK	0140000	/* Socket.  */
+
+/* Protection bits.  */
+
+#define	__S_ISUID	04000	/* Set user ID on execution.  */
+#define	__S_ISGID	02000	/* Set group ID on execution.  */
+#define	__S_ISVTX	01000	/* Save swapped text after use (sticky).  */
+#define	__S_IREAD	0400	/* Read by owner.  */
+#define	__S_IWRITE	0200	/* Write by owner.  */
+#define	__S_IEXEC	0100	/* Execute by owner.  */
+
+#endif	/* statbuf.h */
diff --git a/sysdeps/unix/sysv/linux/powerpc/syscall.S b/sysdeps/unix/sysv/linux/powerpc/syscall.S
index 9b3f66682e..441dd5d433 100644
--- a/sysdeps/unix/sysv/linux/powerpc/syscall.S
+++ b/sysdeps/unix/sysv/linux/powerpc/syscall.S
@@ -28,5 +28,9 @@ ENTRY (syscall)
 	mr	7,8
 	sc
 	bnslr
+#ifdef PIC
+	b __syscall_error@plt
+#else
 	b __syscall_error
+#endif
 PSEUDO_END (syscall)
diff --git a/sysdeps/unix/sysv/linux/powerpc/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/sysdep.h
index c08e3d8060..d6d33bf7af 100644
--- a/sysdeps/unix/sysv/linux/powerpc/sysdep.h
+++ b/sysdeps/unix/sysv/linux/powerpc/sysdep.h
@@ -41,13 +41,21 @@
     li 0,syscall;						              \
     sc
 
+#ifdef PIC
+#define PSEUDO(name, syscall_name, args)				      \
+  .text;								      \
+  ENTRY (name)								      \
+    DO_CALL (SYS_ify (syscall_name));					      \
+    bnslr;								      \
+    b __syscall_error@plt
+#else
 #define PSEUDO(name, syscall_name, args)                                      \
   .text;								      \
   ENTRY (name)                                                                \
     DO_CALL (SYS_ify (syscall_name));				              \
-    bnslr; \
+    bnslr;                                                                    \
     b __syscall_error
-
+#endif
 #define ret	/* Nothing (should be 'blr', but never reached).  */
 
 #endif	/* ASSEMBLER */
diff --git a/sysdeps/unix/sysv/linux/powerpc/termbits.h b/sysdeps/unix/sysv/linux/powerpc/termbits.h
index d1b0a3e3cb..4c6073bfc2 100644
--- a/sysdeps/unix/sysv/linux/powerpc/termbits.h
+++ b/sysdeps/unix/sysv/linux/powerpc/termbits.h
@@ -17,9 +17,7 @@
    Boston, MA 02111-1307, USA.  */
 
 #ifndef _TERMBITS_H
-#define _TERMBITS_H
-
-#include <linux/posix_types.h>
+#define _TERMBITS_H	1
 
 typedef unsigned char	cc_t;
 typedef unsigned int	speed_t;
@@ -31,14 +29,14 @@ typedef unsigned int	tcflag_t;
  * concerning namespace pollution.
  */
 
-#define NCCS 19
+#define NCCS 32
 struct termios {
 	tcflag_t c_iflag;		/* input mode flags */
 	tcflag_t c_oflag;		/* output mode flags */
 	tcflag_t c_cflag;		/* control mode flags */
 	tcflag_t c_lflag;		/* local mode flags */
-	cc_t c_cc[NCCS];		/* control characters */
 	cc_t c_line;			/* line discipline (== c_cc[19]) */
+	cc_t c_cc[NCCS];		/* control characters */
 	speed_t c_ispeed;		/* input speed */
 	speed_t c_ospeed;		/* output speed */
 };
@@ -219,80 +217,6 @@ struct ltchars {
 	char	t_lnextc;
 };
 
-#define FIOCLEX		_IO('f', 1)
-#define FIONCLEX	_IO('f', 2)
-#define FIOASYNC	_IOW('f', 125, int)
-#define FIONBIO		_IOW('f', 126, int)
-#define FIONREAD	_IOR('f', 127, int)
-#define TIOCINQ		FIONREAD
-
-#define TIOCGETP	_IOR('t', 8, struct sgttyb)
-#define TIOCSETP	_IOW('t', 9, struct sgttyb)
-#define TIOCSETN	_IOW('t', 10, struct sgttyb)	/* TIOCSETP wo flush */
-
-#define TIOCSETC	_IOW('t', 17, struct tchars)
-#define TIOCGETC	_IOR('t', 18, struct tchars)
-#define TCGETS		_IOR('t', 19, struct termios)
-#define TCSETS		_IOW('t', 20, struct termios)
-#define TCSETSW		_IOW('t', 21, struct termios)
-#define TCSETSF		_IOW('t', 22, struct termios)
-
-#define TCGETA		_IOR('t', 23, struct termio)
-#define TCSETA		_IOW('t', 24, struct termio)
-#define TCSETAW		_IOW('t', 25, struct termio)
-#define TCSETAF		_IOW('t', 28, struct termio)
-
-#define TCSBRK		_IO('t', 29)
-#define TCXONC		_IO('t', 30)
-#define TCFLSH		_IO('t', 31)
-
-#define TIOCSWINSZ	_IOW('t', 103, struct winsize)
-#define TIOCGWINSZ	_IOR('t', 104, struct winsize)
-#define	TIOCSTART	_IO('t', 110)		/* start output, like ^Q */
-#define	TIOCSTOP	_IO('t', 111)		/* stop output, like ^S */
-#define TIOCOUTQ        _IOR('t', 115, int)     /* output queue size */
-
-#define TIOCGLTC	_IOR('t', 116, struct ltchars)
-#define TIOCSLTC	_IOW('t', 117, struct ltchars)
-#define TIOCSPGRP	_IOW('t', 118, int)
-#define TIOCGPGRP	_IOR('t', 119, int)
-
-#define TIOCEXCL	0x540C
-#define TIOCNXCL	0x540D
-#define TIOCSCTTY	0x540E
-
-#define TIOCSTI		0x5412
-#define TIOCMGET	0x5415
-#define TIOCMBIS	0x5416
-#define TIOCMBIC	0x5417
-#define TIOCMSET	0x5418
-#define TIOCGSOFTCAR	0x5419
-#define TIOCSSOFTCAR	0x541A
-#define TIOCLINUX	0x541C
-#define TIOCCONS	0x541D
-#define TIOCGSERIAL	0x541E
-#define TIOCSSERIAL	0x541F
-#define TIOCPKT		0x5420
-
-#define TIOCNOTTY	0x5422
-#define TIOCSETD	0x5423
-#define TIOCGETD	0x5424
-#define TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */
-#define TIOCTTYGSTRUCT	0x5426  /* For debugging only */
-
-#define TIOCSERCONFIG	0x5453
-#define TIOCSERGWILD	0x5454
-#define TIOCSERSWILD	0x5455
-#define TIOCGLCKTRMIOS	0x5456
-#define TIOCSLCKTRMIOS	0x5457
-#define TIOCSERGSTRUCT	0x5458 /* For debugging only */
-#define TIOCSERGETLSR   0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
-#define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
-
 /* Used for packet mode */
 #define TIOCPKT_DATA		 0
 #define TIOCPKT_FLUSHREAD	 1
diff --git a/sysdeps/unix/sysv/linux/readv.c b/sysdeps/unix/sysv/linux/readv.c
new file mode 100644
index 0000000000..458e8ffb38
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/readv.c
@@ -0,0 +1,71 @@
+/* readv supports all Linux kernels >= 2.0.
+   Copyright (C) 1997 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,
+   read to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <errno.h>
+#include <stddef.h>
+#include <sys/param.h>
+#include <sys/uio.h>
+
+extern ssize_t __syscall_readv __P ((int, __const struct iovec *, int));
+
+
+/* Not all versions of the kernel support the large number of records.  */
+#undef MAX_IOVEC
+#ifdef UIO_FASTIOV
+# define MAX_IOVEC	UIO_FASTIOV
+#else
+# define MAX_IOVEC	8	/* 8 is a safe number. */
+#endif
+
+
+/* We should deal with kernel which have a smaller UIO_MAXIOV as well
+   as a very big count.  */
+ssize_t
+readv (fd, vector, count)
+     int fd;
+     const struct iovec *vector;
+     int count;
+{
+  int errno_saved = errno;
+  ssize_t bytes_read;
+
+  bytes_read = __syscall_readv (fd, vector, count);
+
+  if (bytes_read < 0 && errno == EINVAL && count > MAX_IOVEC)
+    {
+      int i;
+
+      /* Restore the old error value as if nothing happened.  */
+      __set_errno (errno_saved);
+
+      bytes_read = 0;
+      for (i = 0; i < count; i += MAX_IOVEC)
+	{
+	  ssize_t bytes = __syscall_readv (fd, vector + i,
+					   MIN (count - i, MAX_IOVEC));
+
+	  if (bytes < 0)
+	    return bytes;
+
+	  bytes_read += bytes;
+	}
+    }
+
+  return bytes_read;
+}
diff --git a/sysdeps/unix/sysv/linux/syscalls.list b/sysdeps/unix/sysv/linux/syscalls.list
index 4e92f6d35c..f8644c2705 100644
--- a/sysdeps/unix/sysv/linux/syscalls.list
+++ b/sysdeps/unix/sysv/linux/syscalls.list
@@ -56,7 +56,12 @@ setresuid	EXTRA	setresuid	3	setresuid
 sigpending	-	sigpending	1	sigpending
 sigprocmask	-	sigprocmask	3	__sigprocmask	sigprocmask
 sigreturn	-	sigreturn	1	__sigreturn	sigreturn
+sys_fstat	fxstat	fstat		2	__syscall_fstat
 sys_mknod	xmknod	mknod		3	__syscall_mknod
+sys_lstat	lxstat	lstat		2	__syscall_lstat
+sys_readv	readv	readv		3	__syscall_readv
+sys_stat	xstat	stat		2	__syscall_stat
+sys_writev	writev	writev		3	__syscall_writev
 sysinfo		EXTRA	sysinfo		1	sysinfo
 swapon		-	swapon		2	swapon
 umount		EXTRA	umount		1	__umount	umount
diff --git a/sysdeps/unix/sysv/linux/writev.c b/sysdeps/unix/sysv/linux/writev.c
new file mode 100644
index 0000000000..11afd81d2e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/writev.c
@@ -0,0 +1,68 @@
+/* writev supports all Linux kernels >= 2.0.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <errno.h>
+#include <stddef.h>
+#include <sys/param.h>
+#include <sys/uio.h>
+
+extern ssize_t __syscall_writev __P ((int, const struct iovec *, int));
+
+/* Not all versions of the kernel support the large number of records.  */
+#undef MAX_IOVEC
+#ifdef UIO_FASTIOV
+# define MAX_IOVEC	UIO_FASTIOV
+#else
+# define MAX_IOVEC	8	/* 8 is a safe number. */
+#endif
+
+
+/* We should deal with kernel which have a smaller UIO_MAXIOV as well
+   as a very big count.  */
+ssize_t
+writev (fd, vector, count)
+     int fd;
+     const struct iovec *vector;
+     int count;
+{
+  int errno_saved = errno;
+  ssize_t bytes_written;
+
+  bytes_written = __syscall_writev (fd, vector, count);
+
+  if (bytes_written < 0 && errno == EINVAL && count > MAX_IOVEC)
+    {
+      int i;
+
+      /* Restore the old error value as if nothing happened.  */
+      __set_errno (errno_saved);
+
+      bytes_written = 0;
+      for (i = 0; i < count; i += MAX_IOVEC)
+	{
+	  ssize_t bytes = __syscall_writev (fd, vector + i,
+					    MIN (count - i, MAX_IOVEC));
+
+	  if (bytes < 0)
+	    return bytes_written > 0 ? bytes_written : bytes;
+	}
+    }
+
+  return bytes_written;
+}
diff --git a/sysdeps/unix/sysv/sco3.2.4/Dist b/sysdeps/unix/sysv/sco3.2.4/Dist
new file mode 100644
index 0000000000..984b473349
--- /dev/null
+++ b/sysdeps/unix/sysv/sco3.2.4/Dist
@@ -0,0 +1 @@
+__setpgid.c
diff --git a/sysdeps/unix/sysv/sysv4/Dist b/sysdeps/unix/sysv/sysv4/Dist
index da3d7e58e1..6395064504 100644
--- a/sysdeps/unix/sysv/sysv4/Dist
+++ b/sysdeps/unix/sysv/sysv4/Dist
@@ -1,2 +1,4 @@
+__getpgid.c
+__setpgid.c
 sysconfig.h
 siginfo.h
diff --git a/time/offtime.c b/time/offtime.c
index 1469029bc0..f13c8a38ae 100644
--- a/time/offtime.c
+++ b/time/offtime.c
@@ -64,7 +64,7 @@ __offtime (t, offset, tp)
   while (days < 0 || days >= (__isleap (y) ? 366 : 365))
     {
       /* Guess a corrected year, assuming 365 days per year.  */
-      int yg = y + days / 365 - (days % 365 < 0);
+      long int yg = y + days / 365 - (days % 365 < 0);
 
       /* Adjust DAYS and Y to match the guessed year.  */
       days -= ((yg - y) * 365