about summary refs log tree commit diff
path: root/REORG.TODO/nis
diff options
context:
space:
mode:
Diffstat (limited to 'REORG.TODO/nis')
-rw-r--r--REORG.TODO/nis/Depend1
-rw-r--r--REORG.TODO/nis/Makefile102
-rw-r--r--REORG.TODO/nis/Versions131
-rw-r--r--REORG.TODO/nis/libnsl.h40
-rw-r--r--REORG.TODO/nis/nis_add.c75
-rw-r--r--REORG.TODO/nis/nis_addmember.c94
-rw-r--r--REORG.TODO/nis/nis_call.c845
-rw-r--r--REORG.TODO/nis/nis_callback.c380
-rw-r--r--REORG.TODO/nis/nis_checkpoint.c80
-rw-r--r--REORG.TODO/nis/nis_clone_dir.c75
-rw-r--r--REORG.TODO/nis/nis_clone_obj.c68
-rw-r--r--REORG.TODO/nis/nis_clone_res.c75
-rw-r--r--REORG.TODO/nis/nis_creategroup.c85
-rw-r--r--REORG.TODO/nis/nis_defaults.c456
-rw-r--r--REORG.TODO/nis/nis_destroygroup.c53
-rw-r--r--REORG.TODO/nis/nis_domain_of.c43
-rw-r--r--REORG.TODO/nis/nis_domain_of_r.c62
-rw-r--r--REORG.TODO/nis/nis_error.c101
-rw-r--r--REORG.TODO/nis/nis_error.h48
-rw-r--r--REORG.TODO/nis/nis_file.c106
-rw-r--r--REORG.TODO/nis/nis_findserv.c218
-rw-r--r--REORG.TODO/nis/nis_free.c76
-rw-r--r--REORG.TODO/nis/nis_getservlist.c171
-rw-r--r--REORG.TODO/nis/nis_hash.c76
-rw-r--r--REORG.TODO/nis/nis_intern.h83
-rw-r--r--REORG.TODO/nis/nis_ismember.c150
-rw-r--r--REORG.TODO/nis/nis_local_names.c178
-rw-r--r--REORG.TODO/nis/nis_lookup.c219
-rw-r--r--REORG.TODO/nis/nis_mkdir.c44
-rw-r--r--REORG.TODO/nis/nis_modify.c75
-rw-r--r--REORG.TODO/nis/nis_ping.c71
-rw-r--r--REORG.TODO/nis/nis_print.c382
-rw-r--r--REORG.TODO/nis/nis_print_group_entry.c175
-rw-r--r--REORG.TODO/nis/nis_remove.c59
-rw-r--r--REORG.TODO/nis/nis_removemember.c93
-rw-r--r--REORG.TODO/nis/nis_rmdir.c42
-rw-r--r--REORG.TODO/nis/nis_server.c89
-rw-r--r--REORG.TODO/nis/nis_subr.c354
-rw-r--r--REORG.TODO/nis/nis_table.c813
-rw-r--r--REORG.TODO/nis/nis_util.c52
-rw-r--r--REORG.TODO/nis/nis_verifygroup.c52
-rw-r--r--REORG.TODO/nis/nis_xdr.c460
-rw-r--r--REORG.TODO/nis/nis_xdr.h43
-rw-r--r--REORG.TODO/nis/nisplus-parser.h35
-rw-r--r--REORG.TODO/nis/nss37
-rw-r--r--REORG.TODO/nis/nss-default.c127
-rw-r--r--REORG.TODO/nis/nss-nis.c44
-rw-r--r--REORG.TODO/nis/nss-nis.h58
-rw-r--r--REORG.TODO/nis/nss-nisplus.c78
-rw-r--r--REORG.TODO/nis/nss-nisplus.h40
-rw-r--r--REORG.TODO/nis/nss_compat/compat-grp.c683
-rw-r--r--REORG.TODO/nis/nss_compat/compat-initgroups.c576
-rw-r--r--REORG.TODO/nis/nss_compat/compat-pwd.c1132
-rw-r--r--REORG.TODO/nis/nss_compat/compat-spwd.c858
-rw-r--r--REORG.TODO/nis/nss_nis/nis-alias.c281
-rw-r--r--REORG.TODO/nis/nss_nis/nis-ethers.c292
-rw-r--r--REORG.TODO/nis/nss_nis/nis-grp.c359
-rw-r--r--REORG.TODO/nis/nss_nis/nis-hosts.c567
-rw-r--r--REORG.TODO/nis/nss_nis/nis-initgroups.c336
-rw-r--r--REORG.TODO/nis/nss_nis/nis-netgrp.c98
-rw-r--r--REORG.TODO/nis/nss_nis/nis-network.c315
-rw-r--r--REORG.TODO/nis/nss_nis/nis-proto.c278
-rw-r--r--REORG.TODO/nis/nss_nis/nis-publickey.c234
-rw-r--r--REORG.TODO/nis/nss_nis/nis-pwd.c581
-rw-r--r--REORG.TODO/nis/nss_nis/nis-rpc.c279
-rw-r--r--REORG.TODO/nis/nss_nis/nis-service.c438
-rw-r--r--REORG.TODO/nis/nss_nis/nis-spwd.c235
-rw-r--r--REORG.TODO/nis/nss_nisplus/nisplus-alias.c337
-rw-r--r--REORG.TODO/nis/nss_nisplus/nisplus-ethers.c356
-rw-r--r--REORG.TODO/nis/nss_nisplus/nisplus-grp.c401
-rw-r--r--REORG.TODO/nis/nss_nisplus/nisplus-hosts.c619
-rw-r--r--REORG.TODO/nis/nss_nisplus/nisplus-initgroups.c148
-rw-r--r--REORG.TODO/nis/nss_nisplus/nisplus-netgrp.c191
-rw-r--r--REORG.TODO/nis/nss_nisplus/nisplus-network.c494
-rw-r--r--REORG.TODO/nis/nss_nisplus/nisplus-parser.c375
-rw-r--r--REORG.TODO/nis/nss_nisplus/nisplus-proto.c441
-rw-r--r--REORG.TODO/nis/nss_nisplus/nisplus-publickey.c411
-rw-r--r--REORG.TODO/nis/nss_nisplus/nisplus-pwd.c408
-rw-r--r--REORG.TODO/nis/nss_nisplus/nisplus-rpc.c444
-rw-r--r--REORG.TODO/nis/nss_nisplus/nisplus-service.c461
-rw-r--r--REORG.TODO/nis/nss_nisplus/nisplus-spwd.c220
-rw-r--r--REORG.TODO/nis/rpcsvc/nis.h616
-rw-r--r--REORG.TODO/nis/rpcsvc/nis.x474
-rw-r--r--REORG.TODO/nis/rpcsvc/nis_callback.h72
-rw-r--r--REORG.TODO/nis/rpcsvc/nis_callback.x63
-rw-r--r--REORG.TODO/nis/rpcsvc/nis_object.x328
-rw-r--r--REORG.TODO/nis/rpcsvc/nis_tags.h129
-rw-r--r--REORG.TODO/nis/rpcsvc/nislib.h286
-rw-r--r--REORG.TODO/nis/rpcsvc/yp.h339
-rw-r--r--REORG.TODO/nis/rpcsvc/yp.x311
-rw-r--r--REORG.TODO/nis/rpcsvc/yp_prot.h366
-rw-r--r--REORG.TODO/nis/rpcsvc/ypclnt.h88
-rw-r--r--REORG.TODO/nis/rpcsvc/ypupd.h88
-rw-r--r--REORG.TODO/nis/yp_xdr.c330
-rw-r--r--REORG.TODO/nis/ypclnt.c1030
-rw-r--r--REORG.TODO/nis/ypupdate_xdr.c61
96 files changed, 24743 insertions, 0 deletions
diff --git a/REORG.TODO/nis/Depend b/REORG.TODO/nis/Depend
new file mode 100644
index 0000000000..5eb2ea41b9
--- /dev/null
+++ b/REORG.TODO/nis/Depend
@@ -0,0 +1 @@
+nss
diff --git a/REORG.TODO/nis/Makefile b/REORG.TODO/nis/Makefile
new file mode 100644
index 0000000000..6b6f5ee72c
--- /dev/null
+++ b/REORG.TODO/nis/Makefile
@@ -0,0 +1,102 @@
+# Copyright (C) 1996-2017 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 Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 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
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <http://www.gnu.org/licenses/>.
+
+#
+#	Makefile for NIS/NIS+ part.
+#
+subdir	:= nis
+
+include ../Makeconfig
+
+aux			:= nis_hash
+
+ifeq ($(build-obsolete-nsl),yes)
+headers			:= $(wildcard rpcsvc/*.[hx])
+
+# 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 publickey
+
+# Specify rules for the nss_* modules.
+services		:= nis nisplus compat
+endif
+
+extra-libs		= libnsl
+ifeq ($(build-obsolete-nsl),yes)
+extra-libs += $(services:%=libnss_%)
+endif
+# These libraries will be built in the `others' pass rather than
+# the `lib' pass, because they depend on libc.so being built already.
+extra-libs-others	= $(extra-libs)
+
+ifeq ($(build-obsolete-nsl),yes)
+# The sources are found in the appropriate subdir.
+subdir-dirs = $(services:%=nss_%)
+vpath %.c $(subdir-dirs)
+endif
+
+libnsl-routines = yp_xdr ypclnt ypupdate_xdr \
+		  nis_subr nis_local_names nis_free nis_file \
+		  nis_print nis_error nis_call nis_lookup\
+		  nis_table nis_xdr nis_server nis_ping \
+		  nis_checkpoint nis_mkdir nis_rmdir nis_getservlist\
+		  nis_verifygroup nis_ismember nis_addmember nis_util\
+		  nis_removemember nis_creategroup nis_destroygroup\
+		  nis_print_group_entry nis_domain_of nis_domain_of_r\
+		  nis_modify nis_remove nis_add nis_defaults\
+		  nis_findserv nis_callback nis_clone_dir nis_clone_obj\
+		  nis_clone_res nss-default
+
+ifeq ($(build-obsolete-nsl),yes)
+libnss_compat-routines	:= $(addprefix compat-,grp pwd spwd initgroups)
+libnss_compat-inhibit-o	= $(filter-out .os,$(object-suffixes))
+
+libnss_nis-routines	:= $(addprefix nis-,$(databases)) nis-initgroups \
+			   nss-nis
+libnss_nis-inhibit-o	= $(filter-out .os,$(object-suffixes))
+
+libnss_nisplus-routines	:= $(addprefix nisplus-,$(databases)) nisplus-parser \
+			   nss-nisplus nisplus-initgroups
+libnss_nisplus-inhibit-o = $(filter-out .os,$(object-suffixes))
+endif
+
+include ../Rules
+
+
+ifeq ($(build-obsolete-nsl),yes)
+$(objpfx)libnss_compat.so: $(objpfx)libnsl.so$(libnsl.so-version)
+$(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)
+endif
+
+libnsl-libc = $(common-objpfx)linkobj/libc.so
+# Target-specific variable setting to link objects using deprecated
+# RPC interfaces with the version of libc.so that makes them available
+# for new links:
+$(services:%=$(objpfx)libnss_%.so) $(objpfx)libnsl.so: \
+  libc-for-link = $(libnsl-libc)
+
+
+ifeq ($(build-shared),yes)
+$(others:%=$(objpfx)%): $(objpfx)libnsl.so$(libnsl.so-version)
+else
+ifeq ($(build-obsolete-nsl),yes)
+$(others:%=$(objpfx)%): $(objpfx)libnsl.a
+endif
+endif
diff --git a/REORG.TODO/nis/Versions b/REORG.TODO/nis/Versions
new file mode 100644
index 0000000000..ef9a512417
--- /dev/null
+++ b/REORG.TODO/nis/Versions
@@ -0,0 +1,131 @@
+libnsl {
+  GLIBC_2.0 {
+    # Many programs expect this, but every user program should
+    # have it's own version, since the interface is different on
+    # various platforms.
+    xdr_domainname;       xdr_keydat;          xdr_mapname;
+    xdr_peername;         xdr_valdat;          xdr_yp_buf;
+    xdr_ypbind_binding;   xdr_ypbind_resp;     xdr_ypbind_resptype;
+    xdr_ypbind_setdom;    xdr_ypdelete_args;   xdr_ypmap_parms;
+    xdr_ypmaplist;        xdr_yppush_status;   xdr_yppushresp_xfr;
+    xdr_ypreq_key;        xdr_ypreq_nokey;     xdr_ypreq_xfr;
+    xdr_ypresp_all;       xdr_ypresp_key_val;  xdr_ypresp_maplist;
+    xdr_ypresp_master;    xdr_ypresp_order;    xdr_ypresp_val;
+    xdr_ypresp_xfr;       xdr_ypstat;          xdr_ypupdate_args;
+    xdr_ypxfrstat;
+
+    __yp_check;
+    yp_all;               yp_bind;             yp_first;
+    yp_get_default_domain; yp_maplist;         yp_master;
+    yp_match;             yp_next;             yp_order;
+    yp_unbind;            yp_update;           ypbinderr_string;
+    yperr_string;         ypprot_err;
+  }
+  GLIBC_2.1 {
+    nis_add;              nis_add_entry;       nis_addmember;
+    nis_checkpoint;       nis_clone_directory; nis_clone_object;
+    nis_clone_result;     nis_creategroup;     nis_destroy_object;
+    nis_destroygroup;     nis_dir_cmp;         nis_domain_of;
+    nis_domain_of_r;      nis_first_entry;     nis_free_directory;
+    nis_free_object;      nis_free_request;    nis_freenames;
+    nis_freeresult;       nis_freeservlist;    nis_freetags;
+    nis_getnames;         nis_getservlist;     nis_ismember;
+    nis_leaf_of;          nis_leaf_of_r;       nis_lerror;
+    nis_list;             nis_local_directory; nis_local_group;
+    nis_local_host;       nis_local_principal; nis_lookup;
+    nis_mkdir;            nis_modify;          nis_modify_entry;
+    nis_name_of;          nis_name_of_r;       nis_next_entry;
+    nis_perror;           nis_ping;            nis_print_directory;
+    nis_print_entry;      nis_print_group;     nis_print_group_entry;
+    nis_print_link;       nis_print_object;    nis_print_result;
+    nis_print_rights;     nis_print_table;     nis_read_obj;
+    nis_remove;           nis_remove_entry;    nis_removemember;
+    nis_rmdir;            nis_servstate;       nis_sperrno;
+    nis_sperror;          nis_sperror_r;       nis_stats;
+    nis_verifygroup;      nis_write_obj;
+
+    xdr_cback_data;       xdr_obj_p;
+
+    # This functions are needed by the NIS+ tools and rpc.nisd,
+    # they should never be used in a normal user program !
+    __free_fdresult;      __nis_default_access; __nis_default_group;
+    __nis_default_owner;  __nis_default_ttl;   __nis_finddirectory;
+    __nis_hash;           __nisbind_connect;   __nisbind_create;
+    __nisbind_destroy;    __nisbind_next;
+    readColdStartFile;    writeColdStartFile;
+  }
+  GLIBC_2.2 {
+    xdr_ypall;
+  }
+  GLIBC_PRIVATE {
+    _nsl_default_nss; __prepare_niscall; __follow_path; __do_niscall3;
+    __create_ib_request; _xdr_ib_request; _xdr_nis_result;
+  }
+}
+
+libnss_compat {
+  GLIBC_PRIVATE {
+    _nss_compat_endgrent; _nss_compat_endpwent; _nss_compat_endspent;
+    _nss_compat_getgrent_r; _nss_compat_getgrgid_r; _nss_compat_getgrnam_r;
+    _nss_compat_getpwent_r; _nss_compat_getpwnam_r; _nss_compat_getpwuid_r;
+    _nss_compat_getspent_r; _nss_compat_getspnam_r;
+    _nss_compat_setgrent; _nss_compat_setpwent; _nss_compat_setspent;
+    _nss_compat_initgroups_dyn;
+  }
+}
+
+libnss_nis {
+  GLIBC_PRIVATE {
+    _nss_nis_endaliasent; _nss_nis_endetherent; _nss_nis_endgrent;
+    _nss_nis_endhostent; _nss_nis_endnetent; _nss_nis_endnetgrent;
+    _nss_nis_endprotoent; _nss_nis_endpwent; _nss_nis_endrpcent;
+    _nss_nis_endservent; _nss_nis_endspent; _nss_nis_getaliasbyname_r;
+    _nss_nis_getaliasent_r; _nss_nis_getetherent_r; _nss_nis_getgrent_r;
+    _nss_nis_getgrgid_r; _nss_nis_getgrnam_r; _nss_nis_gethostbyaddr_r;
+    _nss_nis_gethostbyname2_r; _nss_nis_gethostbyname_r; _nss_nis_gethostent_r;
+    _nss_nis_gethostton_r; _nss_nis_getnetbyaddr_r; _nss_nis_getnetbyname_r;
+    _nss_nis_getnetent_r; _nss_nis_getnetgrent_r; _nss_nis_getntohost_r;
+    _nss_nis_getprotobyname_r; _nss_nis_getprotobynumber_r;
+    _nss_nis_getprotoent_r; _nss_nis_getpublickey; _nss_nis_getpwent_r;
+    _nss_nis_getpwnam_r; _nss_nis_getpwuid_r; _nss_nis_getrpcbyname_r;
+    _nss_nis_getrpcbynumber_r; _nss_nis_getrpcent_r; _nss_nis_getsecretkey;
+    _nss_nis_getservbyname_r; _nss_nis_getservbyport_r; _nss_nis_getservent_r;
+    _nss_nis_getspent_r; _nss_nis_getspnam_r;
+    _nss_nis_netname2user; _nss_nis_setaliasent; _nss_nis_setetherent;
+    _nss_nis_setgrent; _nss_nis_sethostent; _nss_nis_setnetent;
+    _nss_nis_setnetgrent; _nss_nis_setprotoent; _nss_nis_setpwent;
+    _nss_nis_setrpcent; _nss_nis_setservent; _nss_nis_setspent;
+    _nss_nis_initgroups_dyn; _nss_nis_gethostbyname4_r;
+  }
+}
+
+libnss_nisplus {
+  GLIBC_PRIVATE {
+    _nss_nisplus_endaliasent; _nss_nisplus_endetherent; _nss_nisplus_endgrent;
+    _nss_nisplus_endhostent; _nss_nisplus_endnetent; _nss_nisplus_endnetgrent;
+    _nss_nisplus_endprotoent; _nss_nisplus_endpwent; _nss_nisplus_endrpcent;
+    _nss_nisplus_endservent; _nss_nisplus_endspent;
+    _nss_nisplus_getaliasbyname_r; _nss_nisplus_getaliasent_r;
+    _nss_nisplus_getetherent_r; _nss_nisplus_getgrent_r;
+    _nss_nisplus_getgrgid_r; _nss_nisplus_getgrnam_r;
+    _nss_nisplus_gethostbyaddr_r; _nss_nisplus_gethostbyname2_r;
+    _nss_nisplus_gethostbyname_r; _nss_nisplus_gethostent_r;
+    _nss_nisplus_gethostton_r; _nss_nisplus_getnetbyaddr_r;
+    _nss_nisplus_getnetbyname_r; _nss_nisplus_getnetent_r;
+    _nss_nisplus_getnetgrent_r; _nss_nisplus_getntohost_r;
+    _nss_nisplus_getprotobyname_r; _nss_nisplus_getprotobynumber_r;
+    _nss_nisplus_getprotoent_r; _nss_nisplus_getpublickey;
+    _nss_nisplus_getpwent_r; _nss_nisplus_getpwnam_r; _nss_nisplus_getpwuid_r;
+    _nss_nisplus_getrpcbyname_r; _nss_nisplus_getrpcbynumber_r;
+    _nss_nisplus_getrpcent_r; _nss_nisplus_getsecretkey;
+    _nss_nisplus_getservbyname_r; _nss_nisplus_getservbynumber_r;
+    _nss_nisplus_getservent_r; _nss_nisplus_getspent_r;
+    _nss_nisplus_getspnam_r; _nss_nisplus_netname2user;
+    _nss_nisplus_setaliasent;
+    _nss_nisplus_setetherent; _nss_nisplus_setgrent; _nss_nisplus_sethostent;
+    _nss_nisplus_setnetent; _nss_nisplus_setnetgrent; _nss_nisplus_setprotoent;
+    _nss_nisplus_setpwent; _nss_nisplus_setrpcent; _nss_nisplus_setservent;
+    _nss_nisplus_setspent; _nss_nisplus_initgroups_dyn;
+    _nss_nisplus_gethostbyname4_r;
+  }
+}
diff --git a/REORG.TODO/nis/libnsl.h b/REORG.TODO/nis/libnsl.h
new file mode 100644
index 0000000000..4d14458f86
--- /dev/null
+++ b/REORG.TODO/nis/libnsl.h
@@ -0,0 +1,40 @@
+/* Copyright (C) 2005-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <rpcsvc/nis.h>
+
+#define NSS_FLAG_NETID_AUTHORITATIVE	1
+#define NSS_FLAG_SERVICES_AUTHORITATIVE	2
+#define NSS_FLAG_SETENT_BATCH_READ	4
+#define NSS_FLAG_ADJUNCT_AS_SHADOW	8
+
+
+/* Get current set of default flags.  */
+extern int _nsl_default_nss (void);
+
+/* Set up everything for a call to __do_niscall3.  */
+extern nis_error __prepare_niscall (const_nis_name name, directory_obj **dirp,
+				    dir_binding *bptrp, unsigned int flags);
+libnsl_hidden_proto (__prepare_niscall)
+
+extern struct ib_request *__create_ib_request (const_nis_name name,
+					       unsigned int flags);
+libnsl_hidden_proto (__create_ib_request)
+
+extern nis_error __follow_path (char **tablepath, char **tableptr,
+				struct ib_request *ibreq, dir_binding *bptr);
+libnsl_hidden_proto (__follow_path)
diff --git a/REORG.TODO/nis/nis_add.c b/REORG.TODO/nis/nis_add.c
new file mode 100644
index 0000000000..a440252292
--- /dev/null
+++ b/REORG.TODO/nis/nis_add.c
@@ -0,0 +1,75 @@
+/* Copyright (C) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <string.h>
+#include <rpcsvc/nis.h>
+#include <shlib-compat.h>
+
+#include "nis_xdr.h"
+#include "nis_intern.h"
+
+nis_result *
+nis_add (const_nis_name name, const nis_object *obj2)
+{
+  nis_object obj;
+  nis_result *res;
+  nis_error status;
+  struct ns_request req;
+  size_t namelen = strlen (name);
+  char buf1 [namelen + 20];
+  char buf4 [namelen + 20];
+
+  res = calloc (1, sizeof (nis_result));
+  if (res == NULL)
+    return NULL;
+
+  req.ns_name = (char *)name;
+
+  memcpy (&obj, obj2, sizeof (nis_object));
+
+  if (obj.zo_name == NULL || obj.zo_name[0] == '\0')
+    obj.zo_name = nis_leaf_of_r (name, buf1, sizeof (buf1));
+
+  if (obj.zo_owner == NULL || obj.zo_owner[0] == '\0')
+    obj.zo_owner = nis_local_principal ();
+
+  if (obj.zo_group == NULL || obj.zo_group[0] == '\0')
+    obj.zo_group = nis_local_group ();
+
+  obj.zo_domain = nis_domain_of_r (name, buf4, sizeof (buf4));
+
+  req.ns_object.ns_object_val = nis_clone_object (&obj, NULL);
+  if (req.ns_object.ns_object_val == NULL)
+    {
+      NIS_RES_STATUS (res) = NIS_NOMEMORY;
+      return res;
+    }
+  req.ns_object.ns_object_len = 1;
+
+  status = __do_niscall (req.ns_object.ns_object_val[0].zo_domain,
+			 NIS_ADD, (xdrproc_t) _xdr_ns_request,
+			 (caddr_t) &req, (xdrproc_t) _xdr_nis_result,
+			 (caddr_t) res, MASTER_ONLY, NULL);
+  if (status != NIS_SUCCESS)
+    NIS_RES_STATUS (res) = status;
+
+  nis_destroy_object (req.ns_object.ns_object_val);
+
+  return res;
+}
+libnsl_hidden_nolink_def (nis_add, GLIBC_2_1)
diff --git a/REORG.TODO/nis/nis_addmember.c b/REORG.TODO/nis/nis_addmember.c
new file mode 100644
index 0000000000..d2c47ab18f
--- /dev/null
+++ b/REORG.TODO/nis/nis_addmember.c
@@ -0,0 +1,94 @@
+/* Copyright (c) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <assert.h>
+#include <string.h>
+#include <rpcsvc/nis.h>
+#include <shlib-compat.h>
+
+nis_error
+nis_addmember (const_nis_name member, const_nis_name group)
+{
+  if (group != NULL && group[0] != '\0')
+    {
+      size_t grouplen = strlen (group);
+      char buf[grouplen + 14 + NIS_MAXNAMELEN];
+      char domainbuf[grouplen + 2];
+      nis_result *res, *res2;
+      nis_error status;
+      char *cp, *cp2;
+
+      cp = rawmemchr (nis_leaf_of_r (group, buf, sizeof (buf) - 1), '\0');
+      cp = stpcpy (cp, ".groups_dir");
+      cp2 = nis_domain_of_r (group, domainbuf, sizeof (domainbuf) - 1);
+      if (cp2 != NULL && cp2[0] != '\0')
+        {
+	  *cp++ = '.';
+          stpcpy (cp, cp2);
+        }
+      res = nis_lookup (buf, FOLLOW_LINKS | EXPAND_NAME);
+      if (NIS_RES_STATUS (res) != NIS_SUCCESS)
+	{
+	  status = NIS_RES_STATUS (res);
+	  nis_freeresult (res);
+	  return status;
+	}
+      if (NIS_RES_NUMOBJ (res) != 1
+	  || __type_of (NIS_RES_OBJECT (res)) != NIS_GROUP_OBJ)
+	{
+	  nis_freeresult (res);
+	  return NIS_INVALIDOBJ;
+	}
+
+      u_int gr_members_len
+	= NIS_RES_OBJECT(res)->GR_data.gr_members.gr_members_len;
+
+      nis_name *new_gr_members_val
+	= realloc (NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_val,
+		   (gr_members_len + 1) * sizeof (nis_name));
+      if (new_gr_members_val == NULL)
+	goto nomem_out;
+
+      NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_val
+	= new_gr_members_val;
+
+      new_gr_members_val[gr_members_len] = strdup (member);
+      if (new_gr_members_val[gr_members_len] == NULL)
+	{
+	nomem_out:
+	  nis_freeresult (res);
+	  return NIS_NOMEMORY;
+	}
+      ++NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_len;
+
+      /* Check the buffer bounds are not exceeded.  */
+      assert (strlen (NIS_RES_OBJECT(res)->zo_name) + 1 < grouplen + 14);
+      cp = stpcpy (buf, NIS_RES_OBJECT(res)->zo_name);
+      *cp++ = '.';
+      strncpy (cp, NIS_RES_OBJECT (res)->zo_domain, NIS_MAXNAMELEN);
+      res2 = nis_modify (buf, NIS_RES_OBJECT (res));
+      status = NIS_RES_STATUS (res2);
+      nis_freeresult (res);
+      nis_freeresult (res2);
+
+      return status;
+    }
+  else
+    return NIS_FAIL;
+}
+libnsl_hidden_nolink_def (nis_addmember, GLIBC_2_1)
diff --git a/REORG.TODO/nis/nis_call.c b/REORG.TODO/nis/nis_call.c
new file mode 100644
index 0000000000..d4f37bfb72
--- /dev/null
+++ b/REORG.TODO/nis/nis_call.c
@@ -0,0 +1,845 @@
+/* Copyright (C) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <libintl.h>
+#include <rpc/rpc.h>
+#include <rpc/auth.h>
+#include <rpcsvc/nis.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <libc-lock.h>
+
+#include "nis_xdr.h"
+#include "nis_intern.h"
+#include <libnsl.h>
+#include <shlib-compat.h>
+
+static const struct timeval RPCTIMEOUT = {10, 0};
+static const struct timeval UDPTIMEOUT = {5, 0};
+
+extern u_short __pmap_getnisport (struct sockaddr_in *address, u_long program,
+				  u_long version, u_int protocol);
+
+unsigned long int
+inetstr2int (const char *str)
+{
+  size_t j = 0;
+  for (size_t i = 0; str[i] != '\0'; ++i)
+    if (str[i] == '.' && __builtin_expect (++j == 4, 0))
+      {
+	char buffer[i + 1];
+	buffer[i] = '\0';
+	return inet_addr (memcpy (buffer, str, i));
+      }
+
+  return inet_addr (str);
+}
+
+void
+__nisbind_destroy (dir_binding *bind)
+{
+  if (bind->clnt != NULL)
+    {
+      if (bind->use_auth)
+	auth_destroy (bind->clnt->cl_auth);
+      clnt_destroy (bind->clnt);
+    }
+}
+libnsl_hidden_nolink_def (__nisbind_destroy, GLIBC_2_1)
+
+nis_error
+__nisbind_next (dir_binding *bind)
+{
+  if (bind->clnt != NULL)
+    {
+      if (bind->use_auth)
+	auth_destroy (bind->clnt->cl_auth);
+      clnt_destroy (bind->clnt);
+      bind->clnt = NULL;
+    }
+
+  if (bind->trys >= bind->server_len)
+    return NIS_FAIL;
+
+  for (u_int j = bind->current_ep + 1;
+       j < bind->server_val[bind->server_used].ep.ep_len; ++j)
+    if (strcmp (bind->server_val[bind->server_used].ep.ep_val[j].family,
+		"inet") == 0)
+      if (bind->server_val[bind->server_used].ep.ep_val[j].proto[0] == '-')
+	{
+	  bind->current_ep = j;
+	  return NIS_SUCCESS;
+	}
+
+  ++bind->trys;
+  ++bind->server_used;
+  if (bind->server_used >= bind->server_len)
+    bind->server_used = 0;
+
+  for (u_int j = 0; j < bind->server_val[bind->server_used].ep.ep_len; ++j)
+    if (strcmp (bind->server_val[bind->server_used].ep.ep_val[j].family,
+		"inet") == 0)
+      if (bind->server_val[bind->server_used].ep.ep_val[j].proto[0] == '-')
+	{
+	  bind->current_ep = j;
+	  return NIS_SUCCESS;
+	}
+
+  return NIS_FAIL;
+}
+libnsl_hidden_nolink_def (__nisbind_next, GLIBC_2_1)
+
+static struct ckey_cache_entry
+{
+  struct in_addr inaddr;
+  in_port_t port;
+  unsigned int protocol;
+  des_block ckey;
+} *ckey_cache;
+static size_t ckey_cache_size;
+static size_t ckey_cache_allocated;
+static pid_t ckey_cache_pid;
+static uid_t ckey_cache_euid;
+__libc_lock_define_initialized (static, ckey_cache_lock)
+
+static bool_t
+get_ckey (des_block *ckey, struct sockaddr_in *addr, unsigned int protocol)
+{
+  size_t i;
+  pid_t pid = getpid ();
+  uid_t euid = geteuid ();
+  bool_t ret = FALSE;
+
+  __libc_lock_lock (ckey_cache_lock);
+
+  if (ckey_cache_pid != pid || ckey_cache_euid != euid)
+    {
+      ckey_cache_size = 0;
+      ckey_cache_pid = pid;
+      ckey_cache_euid = euid;
+    }
+
+  for (i = 0; i < ckey_cache_size; ++i)
+    if (ckey_cache[i].port == addr->sin_port
+	&& ckey_cache[i].protocol == protocol
+	&& memcmp (&ckey_cache[i].inaddr, &addr->sin_addr,
+		   sizeof (addr->sin_addr)) == 0)
+      {
+	*ckey = ckey_cache[i].ckey;
+	ret = TRUE;
+	break;
+      }
+
+  if (!ret && key_gendes (ckey) >= 0)
+    {
+      ret = TRUE;
+      /* Don't grow the cache indefinitely.  */
+      if (ckey_cache_size == 256)
+	ckey_cache_size = 0;
+      if (ckey_cache_size == ckey_cache_allocated)
+	{
+	  size_t size = ckey_cache_allocated ? ckey_cache_allocated * 2 : 16;
+	  struct ckey_cache_entry *new_cache
+	    = realloc (ckey_cache, size * sizeof (*ckey_cache));
+	  if (new_cache != NULL)
+	    {
+	      ckey_cache = new_cache;
+	      ckey_cache_allocated = size;
+	    }
+	}
+      ckey_cache[ckey_cache_size].inaddr = addr->sin_addr;
+      ckey_cache[ckey_cache_size].port = addr->sin_port;
+      ckey_cache[ckey_cache_size].protocol = protocol;
+      ckey_cache[ckey_cache_size++].ckey = *ckey;
+    }
+
+  __libc_lock_unlock (ckey_cache_lock);
+  return ret;
+}
+
+nis_error
+__nisbind_connect (dir_binding *dbp)
+{
+  nis_server *serv;
+  u_short port;
+
+  if (dbp == NULL)
+    return NIS_FAIL;
+
+  serv = &dbp->server_val[dbp->server_used];
+
+  memset (&dbp->addr, '\0', sizeof (dbp->addr));
+  dbp->addr.sin_family = AF_INET;
+
+  dbp->addr.sin_addr.s_addr =
+    inetstr2int (serv->ep.ep_val[dbp->current_ep].uaddr);
+
+  if (dbp->addr.sin_addr.s_addr == INADDR_NONE)
+    return NIS_FAIL;
+
+  /* Check, if the host is online and rpc.nisd is running. Much faster
+     then the clnt*_create functions: */
+  port = __pmap_getnisport (&dbp->addr, NIS_PROG, NIS_VERSION,
+			    dbp->use_udp ? IPPROTO_UDP : IPPROTO_TCP);
+  if (port == 0)
+    return NIS_RPCERROR;
+
+  dbp->addr.sin_port = htons (port);
+  dbp->socket = RPC_ANYSOCK;
+  if (dbp->use_udp)
+    dbp->clnt = clntudp_create (&dbp->addr, NIS_PROG, NIS_VERSION,
+				 UDPTIMEOUT, &dbp->socket);
+  else
+    dbp->clnt = clnttcp_create (&dbp->addr, NIS_PROG, NIS_VERSION,
+				 &dbp->socket, 0, 0);
+
+  if (dbp->clnt == NULL)
+    return NIS_RPCERROR;
+
+  clnt_control (dbp->clnt, CLSET_TIMEOUT, (caddr_t) &RPCTIMEOUT);
+  /* If the program exists, close the socket */
+  if (fcntl (dbp->socket, F_SETFD, 1) == -1)
+    perror ("fcntl: F_SETFD");
+
+  if (dbp->use_auth)
+    {
+      if (serv->key_type == NIS_PK_DH)
+	{
+	  char netname[MAXNETNAMELEN + 1];
+	  char *p;
+	  des_block ckey;
+
+	  p = stpcpy (netname, "unix@");
+	  strncpy (p, serv->name, MAXNETNAMELEN - 5);
+	  netname[MAXNETNAMELEN] = '\0';
+	  dbp->clnt->cl_auth = NULL;
+	  if (get_ckey (&ckey, &dbp->addr,
+			dbp->use_udp ? IPPROTO_UDP : IPPROTO_TCP))
+	    dbp->clnt->cl_auth =
+	      authdes_pk_create (netname, &serv->pkey, 300, NULL, &ckey);
+	  if (!dbp->clnt->cl_auth)
+	    dbp->clnt->cl_auth = authunix_create_default ();
+	}
+      else
+	dbp->clnt->cl_auth = authunix_create_default ();
+    }
+
+  return NIS_SUCCESS;
+}
+libnsl_hidden_nolink_def (__nisbind_connect, GLIBC_2_1)
+
+nis_error
+__nisbind_create (dir_binding *dbp, const nis_server *serv_val,
+		  unsigned int serv_len, unsigned int server_used,
+		  unsigned int current_ep, unsigned int flags)
+{
+  dbp->clnt = NULL;
+
+  dbp->server_len = serv_len;
+  dbp->server_val = (nis_server *)serv_val;
+
+  if (flags & USE_DGRAM)
+    dbp->use_udp = TRUE;
+  else
+    dbp->use_udp = FALSE;
+
+  if (flags & NO_AUTHINFO)
+    dbp->use_auth = FALSE;
+  else
+    dbp->use_auth = TRUE;
+
+  if (flags & MASTER_ONLY)
+    dbp->master_only = TRUE;
+  else
+    dbp->master_only = FALSE;
+
+  /* We try the first server */
+  dbp->trys = 1;
+
+  dbp->class = -1;
+  if (server_used == ~0)
+    {
+      if (__nis_findfastest (dbp) < 1)
+	return NIS_NAMEUNREACHABLE;
+    }
+  else
+    {
+      dbp->server_used = server_used;
+      dbp->current_ep = current_ep;
+    }
+
+  return NIS_SUCCESS;
+}
+libnsl_hidden_nolink_def (__nisbind_create, GLIBC_2_1)
+
+/* __nisbind_connect (dbp) must be run before calling this function !
+   So we could use the same binding twice */
+nis_error
+__do_niscall3 (dir_binding *dbp, u_long prog, xdrproc_t xargs, caddr_t req,
+	       xdrproc_t xres, caddr_t resp, unsigned int flags, nis_cb *cb)
+{
+  enum clnt_stat result;
+  nis_error retcode;
+
+  if (dbp == NULL)
+    return NIS_NAMEUNREACHABLE;
+
+  do
+    {
+    again:
+      result = clnt_call (dbp->clnt, prog, xargs, req, xres, resp, RPCTIMEOUT);
+
+      if (result != RPC_SUCCESS)
+	retcode = NIS_RPCERROR;
+      else
+	{
+	  switch (prog)
+	    {
+	    case NIS_IBLIST:
+	      if ((((nis_result *)resp)->status == NIS_CBRESULTS) &&
+		  (cb != NULL))
+		{
+		  __nis_do_callback (dbp, &((nis_result *) resp)->cookie, cb);
+		  break;
+		}
+	      /* Yes, the missing break is correct. If we doesn't have to
+		 start a callback, look if we have to search another server */
+	    case NIS_LOOKUP:
+	    case NIS_ADD:
+	    case NIS_MODIFY:
+	    case NIS_REMOVE:
+	    case NIS_IBADD:
+	    case NIS_IBMODIFY:
+	    case NIS_IBREMOVE:
+	    case NIS_IBFIRST:
+	    case NIS_IBNEXT:
+	      if (((nis_result *)resp)->status == NIS_SYSTEMERROR
+		  || ((nis_result *)resp)->status == NIS_NOSUCHNAME
+		  || ((nis_result *)resp)->status == NIS_NOT_ME)
+		{
+		next_server:
+		  if (__nisbind_next (dbp) == NIS_SUCCESS)
+		    {
+		      while (__nisbind_connect (dbp) != NIS_SUCCESS)
+			{
+			  if (__nisbind_next (dbp) != NIS_SUCCESS)
+			      return NIS_SUCCESS;
+			}
+		    }
+		  else
+		    break; /* No more servers to search in */
+		  goto again;
+		}
+	      break;
+	    case NIS_FINDDIRECTORY:
+	      if (((fd_result *)resp)->status == NIS_SYSTEMERROR
+		  || ((fd_result *)resp)->status == NIS_NOSUCHNAME
+		  || ((fd_result *)resp)->status == NIS_NOT_ME)
+		goto next_server;
+	      break;
+	    case NIS_DUMPLOG: /* log_result */
+	    case NIS_DUMP:
+	      if (((log_result *)resp)->lr_status == NIS_SYSTEMERROR
+		  || ((log_result *)resp)->lr_status == NIS_NOSUCHNAME
+		  || ((log_result *)resp)->lr_status == NIS_NOT_ME)
+		goto next_server;
+	      break;
+	    default:
+	      break;
+	    }
+	  retcode = NIS_SUCCESS;
+	}
+    }
+  while ((flags & HARD_LOOKUP) && retcode == NIS_RPCERROR);
+
+  return retcode;
+}
+libnsl_hidden_nolink_def (__do_niscall3, GLIBC_PRIVATE)
+
+
+nis_error
+__do_niscall2 (const nis_server *server, u_int server_len, u_long prog,
+	       xdrproc_t xargs, caddr_t req, xdrproc_t xres, caddr_t resp,
+	       unsigned int flags, nis_cb *cb)
+{
+  dir_binding dbp;
+  nis_error status;
+
+  if (flags & MASTER_ONLY)
+    server_len = 1;
+
+  status = __nisbind_create (&dbp, server, server_len, ~0, ~0, flags);
+  if (status != NIS_SUCCESS)
+    return status;
+
+  while (__nisbind_connect (&dbp) != NIS_SUCCESS)
+    if (__nisbind_next (&dbp) != NIS_SUCCESS)
+      return NIS_NAMEUNREACHABLE;
+
+  status = __do_niscall3 (&dbp, prog, xargs, req, xres, resp, flags, cb);
+
+  __nisbind_destroy (&dbp);
+
+  return status;
+
+}
+
+static directory_obj *
+rec_dirsearch (const_nis_name name, directory_obj *dir, nis_error *status)
+{
+  fd_result *fd_res;
+  XDR xdrs;
+
+  switch (nis_dir_cmp (name, dir->do_name))
+    {
+    case SAME_NAME:
+      *status = NIS_SUCCESS;
+      return dir;
+    case NOT_SEQUENTIAL:
+      /* NOT_SEQUENTIAL means, go one up and try it there ! */
+    case HIGHER_NAME:
+      { /* We need data from a parent domain */
+	directory_obj *obj;
+	const char *ndomain = __nis_domain_of (dir->do_name);
+
+	/* The root server of our domain is a replica of the parent
+	   domain ! (Now I understand why a root server must be a
+	   replica of the parent domain) */
+	fd_res = __nis_finddirectory (dir, ndomain);
+	if (fd_res == NULL)
+	  {
+	    nis_free_directory (dir);
+	    *status = NIS_NOMEMORY;
+	    return NULL;
+	  }
+	*status = fd_res->status;
+	if (fd_res->status != NIS_SUCCESS)
+	  {
+	    /* Try the current directory obj, maybe it works */
+	    __free_fdresult (fd_res);
+	    return dir;
+	  }
+	nis_free_directory (dir);
+	obj = calloc (1, sizeof (directory_obj));
+	if (obj == NULL)
+	  {
+	    __free_fdresult (fd_res);
+	    *status = NIS_NOMEMORY;
+	    return NULL;
+	  }
+	xdrmem_create (&xdrs, fd_res->dir_data.dir_data_val,
+		       fd_res->dir_data.dir_data_len, XDR_DECODE);
+	_xdr_directory_obj (&xdrs, obj);
+	xdr_destroy (&xdrs);
+	__free_fdresult (fd_res);
+
+	/* We have found a NIS+ server serving ndomain, now
+	   let us search for "name" */
+	return rec_dirsearch (name, obj, status);
+      }
+      break;
+    case LOWER_NAME:
+      {
+	directory_obj *obj;
+	size_t namelen = strlen (name);
+	char leaf[namelen + 3];
+	char domain[namelen + 3];
+	const char *ndomain;
+	char *cp;
+
+	strcpy (domain, name);
+
+	do
+	  {
+	    if (domain[0] == '\0')
+	      {
+		nis_free_directory (dir);
+		return NULL;
+	      }
+	    nis_leaf_of_r (domain, leaf, sizeof (leaf));
+	    ndomain = __nis_domain_of (domain);
+	    memmove (domain, ndomain, strlen (ndomain) + 1);
+	  }
+	while (nis_dir_cmp (domain, dir->do_name) != SAME_NAME);
+
+	cp = rawmemchr (leaf, '\0');
+	*cp++ = '.';
+	strcpy (cp, domain);
+
+	fd_res = __nis_finddirectory (dir, leaf);
+	if (fd_res == NULL)
+	  {
+	    nis_free_directory (dir);
+	    *status = NIS_NOMEMORY;
+	    return NULL;
+	  }
+	*status = fd_res->status;
+	if (fd_res->status != NIS_SUCCESS)
+	  {
+	    /* Try the current directory object, maybe it works */
+	    __free_fdresult (fd_res);
+	    return dir;
+	  }
+	nis_free_directory (dir);
+	obj = calloc (1, sizeof(directory_obj));
+	if (obj == NULL)
+	  {
+	    __free_fdresult (fd_res);
+	    *status = NIS_NOMEMORY;
+	    return NULL;
+	  }
+	xdrmem_create (&xdrs, fd_res->dir_data.dir_data_val,
+		       fd_res->dir_data.dir_data_len, XDR_DECODE);
+	_xdr_directory_obj (&xdrs, obj);
+	xdr_destroy (&xdrs);
+	__free_fdresult (fd_res);
+	/* We have found a NIS+ server serving ndomain, now
+	   let us search for "name" */
+	return rec_dirsearch (name, obj, status);
+      }
+      break;
+    case BAD_NAME:
+      nis_free_directory (dir);
+      *status = NIS_BADNAME;
+      return NULL;
+    }
+  nis_free_directory (dir);
+  *status = NIS_FAIL;
+  return NULL;
+}
+
+/* We try to query the current server for the searched object,
+   maybe he know about it ? */
+static directory_obj *
+first_shoot (const_nis_name name, directory_obj *dir)
+{
+  directory_obj *obj = NULL;
+  fd_result *fd_res;
+  XDR xdrs;
+
+  if (nis_dir_cmp (name, dir->do_name) == SAME_NAME)
+    return dir;
+
+  fd_res = __nis_finddirectory (dir, name);
+  if (fd_res == NULL)
+    return NULL;
+  if (fd_res->status == NIS_SUCCESS
+      && (obj = calloc (1, sizeof (directory_obj))) != NULL)
+    {
+      xdrmem_create (&xdrs, fd_res->dir_data.dir_data_val,
+		     fd_res->dir_data.dir_data_len, XDR_DECODE);
+      _xdr_directory_obj (&xdrs, obj);
+      xdr_destroy (&xdrs);
+
+      if (strcmp (dir->do_name, obj->do_name) != 0)
+	{
+	  nis_free_directory (obj);
+	  obj = NULL;
+	}
+    }
+
+  __free_fdresult (fd_res);
+
+  if (obj != NULL)
+    nis_free_directory (dir);
+
+  return obj;
+}
+
+static struct nis_server_cache
+{
+  int search_parent;
+  int uses;
+  unsigned int size;
+  unsigned int server_used;
+  unsigned int current_ep;
+  time_t expires;
+  char name[];
+} *nis_server_cache[16];
+static time_t nis_cold_start_mtime;
+__libc_lock_define_initialized (static, nis_server_cache_lock)
+
+static directory_obj *
+nis_server_cache_search (const_nis_name name, int search_parent,
+			 unsigned int *server_used, unsigned int *current_ep,
+			 struct timeval *now)
+{
+  directory_obj *ret = NULL;
+  int i;
+  char *addr;
+  XDR xdrs;
+  struct stat64 st;
+
+  int saved_errno = errno;
+  if (stat64 ("/var/nis/NIS_COLD_START", &st) < 0)
+    st.st_mtime = nis_cold_start_mtime + 1;
+  __set_errno (saved_errno);
+
+  __libc_lock_lock (nis_server_cache_lock);
+
+  for (i = 0; i < 16; ++i)
+    if (nis_server_cache[i] == NULL)
+      continue;
+    else if (st.st_mtime != nis_cold_start_mtime
+	     || now->tv_sec > nis_server_cache[i]->expires)
+      {
+	free (nis_server_cache[i]);
+	nis_server_cache[i] = NULL;
+      }
+    else if (nis_server_cache[i]->search_parent == search_parent
+	     && strcmp (nis_server_cache[i]->name, name) == 0)
+      {
+	ret = calloc (1, sizeof (directory_obj));
+	if (ret == NULL)
+	  break;
+
+	addr = rawmemchr (nis_server_cache[i]->name, '\0') + 8;
+	addr = (char *) ((uintptr_t) addr & ~(uintptr_t) 7);
+	xdrmem_create (&xdrs, addr, nis_server_cache[i]->size, XDR_DECODE);
+	if (!_xdr_directory_obj (&xdrs, ret))
+	  {
+	    xdr_destroy (&xdrs);
+	    free (ret);
+	    ret = NULL;
+	    free (nis_server_cache[i]);
+	    nis_server_cache[i] = NULL;
+	    break;
+	  }
+	xdr_destroy (&xdrs);
+	*server_used = nis_server_cache[i]->server_used;
+	*current_ep = nis_server_cache[i]->current_ep;
+	break;
+      }
+
+  nis_cold_start_mtime = st.st_mtime;
+
+  __libc_lock_unlock (nis_server_cache_lock);
+  return ret;
+}
+
+static void
+nis_server_cache_add (const_nis_name name, int search_parent,
+		      directory_obj *dir, unsigned int server_used,
+		      unsigned int current_ep, struct timeval *now)
+{
+  struct nis_server_cache **loc;
+  struct nis_server_cache *new;
+  struct nis_server_cache *old;
+  int i;
+  char *addr;
+  unsigned int size;
+  XDR xdrs;
+
+  if (dir == NULL)
+    return;
+
+  size = xdr_sizeof ((xdrproc_t) _xdr_directory_obj, (char *) dir);
+  new = calloc (1, sizeof (*new) + strlen (name) + 8 + size);
+  if (new == NULL)
+    return;
+  new->search_parent = search_parent;
+  new->uses = 1;
+  new->expires = now->tv_sec + dir->do_ttl;
+  new->size = size;
+  new->server_used = server_used;
+  new->current_ep = current_ep;
+  addr = stpcpy (new->name, name) + 8;
+  addr = (char *) ((uintptr_t) addr & ~(uintptr_t) 7);
+
+  xdrmem_create(&xdrs, addr, size, XDR_ENCODE);
+  if (!_xdr_directory_obj (&xdrs, dir))
+    {
+      xdr_destroy (&xdrs);
+      free (new);
+      return;
+    }
+  xdr_destroy (&xdrs);
+
+  __libc_lock_lock (nis_server_cache_lock);
+
+  /* Choose which entry should be evicted from the cache.  */
+  loc = &nis_server_cache[0];
+  if (*loc != NULL)
+    {
+      for (i = 1; i < 16; ++i)
+	if (nis_server_cache[i] == NULL)
+	  {
+	    loc = &nis_server_cache[i];
+	    break;
+	  }
+	else if ((*loc)->uses > nis_server_cache[i]->uses
+		 || ((*loc)->uses == nis_server_cache[i]->uses
+		     && (*loc)->expires > nis_server_cache[i]->expires))
+	  loc = &nis_server_cache[i];
+    }
+  old = *loc;
+  *loc = new;
+
+  __libc_lock_unlock (nis_server_cache_lock);
+  free (old);
+}
+
+nis_error
+__nisfind_server (const_nis_name name, int search_parent,
+		  directory_obj **dir, dir_binding *dbp, unsigned int flags)
+{
+  nis_error result = NIS_SUCCESS;
+  nis_error status;
+  directory_obj *obj;
+  struct timeval now;
+  unsigned int server_used = ~0;
+  unsigned int current_ep = ~0;
+
+  if (name == NULL)
+    return NIS_BADNAME;
+
+  if (*dir != NULL)
+    return NIS_SUCCESS;
+
+  (void) gettimeofday (&now, NULL);
+
+  if ((flags & NO_CACHE) == 0)
+    *dir = nis_server_cache_search (name, search_parent, &server_used,
+				    &current_ep, &now);
+  if (*dir != NULL)
+    {
+      unsigned int server_len = (*dir)->do_servers.do_servers_len;
+      if (flags & MASTER_ONLY)
+	{
+	  server_len = 1;
+	  if (server_used != 0)
+	    {
+	      server_used = ~0;
+	      current_ep = ~0;
+	    }
+	}
+      result = __nisbind_create (dbp, (*dir)->do_servers.do_servers_val,
+				 server_len, server_used, current_ep, flags);
+      if (result != NIS_SUCCESS)
+	{
+	  nis_free_directory (*dir);
+	  *dir = NULL;
+	}
+      return result;
+    }
+
+  int saved_errno = errno;
+  *dir = readColdStartFile ();
+  __set_errno (saved_errno);
+  if (*dir == NULL)
+    /* No /var/nis/NIS_COLD_START->no NIS+ installed.  */
+    return NIS_UNAVAIL;
+
+  /* Try at first, if servers in "dir" know our object */
+  const char *search_name = name;
+  if (search_parent)
+    search_name = __nis_domain_of (name);
+  obj = first_shoot (search_name, *dir);
+  if (obj == NULL)
+    {
+      obj = rec_dirsearch (search_name, *dir, &status);
+      if (obj == NULL)
+	result = status;
+    }
+
+  if (result == NIS_SUCCESS)
+    {
+      unsigned int server_len = obj->do_servers.do_servers_len;
+      if (flags & MASTER_ONLY)
+	server_len = 1;
+      result = __nisbind_create (dbp, obj->do_servers.do_servers_val,
+				 server_len, ~0, ~0, flags);
+      if (result == NIS_SUCCESS)
+	{
+	  if ((flags & MASTER_ONLY) == 0
+	      || obj->do_servers.do_servers_len == 1)
+	    {
+	      server_used = dbp->server_used;
+	      current_ep = dbp->current_ep;
+	    }
+	  if ((flags & NO_CACHE) == 0)
+	    nis_server_cache_add (name, search_parent, obj,
+				  server_used, current_ep, &now);
+	}
+      else
+	{
+	  nis_free_directory (obj);
+	  obj = NULL;
+	}
+    }
+
+  *dir = obj;
+
+  return result;
+}
+
+
+nis_error
+__prepare_niscall (const_nis_name name, directory_obj **dirp,
+		   dir_binding *bptrp, unsigned int flags)
+{
+  nis_error retcode = __nisfind_server (name, 1, dirp, bptrp, flags);
+  if (__glibc_unlikely (retcode != NIS_SUCCESS))
+    return retcode;
+
+  do
+    if (__nisbind_connect (bptrp) == NIS_SUCCESS)
+      return NIS_SUCCESS;
+  while (__nisbind_next (bptrp) == NIS_SUCCESS);
+
+  __nisbind_destroy (bptrp);
+  memset (bptrp, '\0', sizeof (*bptrp));
+
+  retcode = NIS_NAMEUNREACHABLE;
+  nis_free_directory (*dirp);
+  *dirp = NULL;
+
+  return retcode;
+}
+libnsl_hidden_nolink_def (__prepare_niscall, GLIBC_PRIVATE)
+
+
+nis_error
+__do_niscall (const_nis_name name, u_long prog, xdrproc_t xargs,
+	      caddr_t req, xdrproc_t xres, caddr_t resp, unsigned int flags,
+	      nis_cb *cb)
+{
+  dir_binding bptr;
+  directory_obj *dir = NULL;
+  int saved_errno = errno;
+
+  nis_error retcode = __prepare_niscall (name, &dir, &bptr, flags);
+  if (retcode == NIS_SUCCESS)
+    {
+      retcode = __do_niscall3 (&bptr, prog, xargs, req, xres, resp, flags, cb);
+
+      __nisbind_destroy (&bptr);
+
+      nis_free_directory (dir);
+    }
+
+  __set_errno (saved_errno);
+
+  return retcode;
+}
diff --git a/REORG.TODO/nis/nis_callback.c b/REORG.TODO/nis/nis_callback.c
new file mode 100644
index 0000000000..2ad4fc0a71
--- /dev/null
+++ b/REORG.TODO/nis/nis_callback.c
@@ -0,0 +1,380 @@
+/* Copyright (C) 1997-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <libintl.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+#include <string.h>
+#include <memory.h>
+#include <syslog.h>
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <rpc/key_prot.h>
+#include <rpcsvc/nis.h>
+#include <rpcsvc/nis_callback.h>
+#include <libc-lock.h>
+
+#include "nis_xdr.h"
+#include "nis_intern.h"
+
+/* Sorry, we are not able to make this threadsafe. Stupid. But some
+   functions doesn't send us a nis_result obj, so we don't have a
+   cookie. Maybe we could use keys for threads ? Have to learn more
+   about pthreads -- kukuk@vt.uni-paderborn.de */
+
+static nis_cb *data;
+
+__libc_lock_define_initialized (static, callback)
+
+
+#if 0
+static char *
+__nis_getpkey(const char *sname)
+{
+  char buf[(strlen (sname) + 1) * 2 + 40];
+  char pkey[HEXKEYBYTES + 1];
+  char *cp, *domain;
+  nis_result *res;
+  unsigned int len = 0;
+
+  domain = strchr (sname, '.');
+  if (domain == NULL)
+    return NULL;
+
+  /* Remove prefixing dot */
+  ++domain;
+
+  cp = stpcpy (buf, "[cname=");
+  cp = stpcpy (cp, sname);
+  cp = stpcpy (cp, ",auth_type=DES],cred.org_dir.");
+  cp = stpcpy (cp, domain);
+
+  res = nis_list (buf, USE_DGRAM|NO_AUTHINFO|FOLLOW_LINKS|FOLLOW_PATH,
+		  NULL, NULL);
+
+  if (res == NULL)
+    return NULL;
+
+  if (NIS_RES_STATUS (res) != NIS_SUCCESS)
+    {
+      nis_freeresult (res);
+      return NULL;
+    }
+
+  len = ENTRY_LEN(NIS_RES_OBJECT(res), 3);
+  strncpy (pkey, ENTRY_VAL(NIS_RES_OBJECT(res), 3), len);
+  pkey[len] = '\0';
+  cp = strchr (pkey, ':');
+  if (cp != NULL)
+    *cp = '\0';
+
+  nis_freeresult (res);
+
+  return strdup (pkey);
+}
+#endif
+
+static void
+cb_prog_1 (struct svc_req *rqstp, SVCXPRT *transp)
+{
+  union
+    {
+      cback_data cbproc_receive_1_arg;
+      nis_error cbproc_error_1_arg;
+    }
+  argument;
+  char *result;
+  xdrproc_t xdr_argument, xdr_result;
+  bool_t bool_result;
+
+  switch (rqstp->rq_proc)
+    {
+    case NULLPROC:
+      svc_sendreply (transp, (xdrproc_t) xdr_void, (char *) NULL);
+      return;
+
+    case CBPROC_RECEIVE:
+      {
+	unsigned int i;
+
+	xdr_argument = (xdrproc_t) xdr_cback_data;
+	xdr_result = (xdrproc_t) xdr_bool;
+	memset (&argument, 0, sizeof (argument));
+	if (!svc_getargs (transp, xdr_argument, (caddr_t) & argument))
+	  {
+	    svcerr_decode (transp);
+	    return;
+	  }
+	bool_result = FALSE;
+	for (i = 0; i < argument.cbproc_receive_1_arg.entries.entries_len; ++i)
+	  {
+#define cbproc_entry(a) argument.cbproc_receive_1_arg.entries.entries_val[a]
+	    char name[strlen (cbproc_entry(i)->zo_name) +
+		      strlen (cbproc_entry(i)->zo_domain) + 3];
+	    char *cp;
+
+	    cp = stpcpy (name, cbproc_entry(i)->zo_name);
+	    *cp++ = '.';
+	    cp = stpcpy (cp, cbproc_entry(i)->zo_domain);
+
+	    if ((data->callback) (name, cbproc_entry(i), data->userdata))
+	      {
+		bool_result = TRUE;
+		data->nomore = 1;
+		data->result = NIS_SUCCESS;
+		break;
+	      }
+	  }
+	result = (char *) &bool_result;
+      }
+      break;
+    case CBPROC_FINISH:
+      xdr_argument = (xdrproc_t) xdr_void;
+      xdr_result = (xdrproc_t) xdr_void;
+      memset (&argument, 0, sizeof (argument));
+      if (!svc_getargs (transp, xdr_argument, (caddr_t) & argument))
+	{
+	  svcerr_decode (transp);
+	  return;
+	}
+      data->nomore = 1;
+      data->result = NIS_SUCCESS;
+      bool_result = TRUE;	/* to make gcc happy, not necessary */
+      result = (char *) &bool_result;
+      break;
+    case CBPROC_ERROR:
+      xdr_argument = (xdrproc_t) _xdr_nis_error;
+      xdr_result = (xdrproc_t) xdr_void;
+      memset (&argument, 0, sizeof (argument));
+      if (!svc_getargs (transp, xdr_argument, (caddr_t) & argument))
+	{
+	  svcerr_decode (transp);
+	  return;
+	}
+      data->nomore = 1;
+      data->result = argument.cbproc_error_1_arg;
+      bool_result = TRUE;	/* to make gcc happy, not necessary */
+      result = (char *) &bool_result;
+      break;
+    default:
+      svcerr_noproc (transp);
+      return;
+    }
+  if (result != NULL && !svc_sendreply (transp, xdr_result, result))
+    svcerr_systemerr (transp);
+  if (!svc_freeargs (transp, xdr_argument, (caddr_t) & argument))
+    {
+      fputs (_ ("unable to free arguments"), stderr);
+      exit (1);
+    }
+  return;
+}
+
+static nis_error
+internal_nis_do_callback (struct dir_binding *bptr, netobj *cookie,
+			  struct nis_cb *cb)
+{
+  struct timeval TIMEOUT = {25, 0};
+  bool_t cb_is_running;
+
+  data = cb;
+
+  for (;;)
+    {
+      struct pollfd my_pollfd[svc_max_pollfd];
+      int i;
+
+      if (svc_max_pollfd == 0 && svc_pollfd == NULL)
+        return NIS_CBERROR;
+
+      for (i = 0; i < svc_max_pollfd; ++i)
+        {
+          my_pollfd[i].fd = svc_pollfd[i].fd;
+          my_pollfd[i].events = svc_pollfd[i].events;
+          my_pollfd[i].revents = 0;
+        }
+
+      switch (i = TEMP_FAILURE_RETRY (__poll (my_pollfd, svc_max_pollfd,
+					      25*1000)))
+        {
+	case -1:
+	  return NIS_CBERROR;
+	case 0:
+	  /* See if callback 'thread' in the server is still alive. */
+	  cb_is_running = FALSE;
+	  if (clnt_call (bptr->clnt, NIS_CALLBACK, (xdrproc_t) xdr_netobj,
+			 (caddr_t) cookie, (xdrproc_t) xdr_bool,
+			 (caddr_t) &cb_is_running, TIMEOUT) != RPC_SUCCESS)
+	    cb_is_running = FALSE;
+
+	  if (cb_is_running == FALSE)
+	    {
+	      syslog (LOG_ERR, "NIS+: callback timed out");
+	      return NIS_CBERROR;
+	    }
+	  break;
+	default:
+	  svc_getreq_poll (my_pollfd, i);
+	  if (data->nomore)
+	    return data->result;
+	}
+    }
+}
+
+nis_error
+__nis_do_callback (struct dir_binding *bptr, netobj *cookie,
+		   struct nis_cb *cb)
+{
+  nis_error result;
+
+  __libc_lock_lock (callback);
+
+  result = internal_nis_do_callback (bptr, cookie, cb);
+
+  __libc_lock_unlock (callback);
+
+  return result;
+}
+
+struct nis_cb *
+__nis_create_callback (int (*callback) (const_nis_name, const nis_object *,
+					const void *),
+		       const void *userdata, unsigned int flags)
+{
+  struct nis_cb *cb;
+  int sock = RPC_ANYSOCK;
+  struct sockaddr_in sin;
+  socklen_t len = sizeof (struct sockaddr_in);
+  unsigned short port;
+  int nomsg = 0;
+
+  cb = (struct nis_cb *) calloc (1,
+				 sizeof (struct nis_cb) + sizeof (nis_server));
+  if (__glibc_unlikely (cb == NULL))
+    goto failed;
+  cb->serv = (nis_server *) (cb + 1);
+  cb->serv->name = strdup (nis_local_principal ());
+  if (__glibc_unlikely (cb->serv->name == NULL))
+    goto failed;
+  cb->serv->ep.ep_val = (endpoint *) calloc (2, sizeof (endpoint));
+  if (__glibc_unlikely (cb->serv->ep.ep_val == NULL))
+    goto failed;
+  cb->serv->ep.ep_len = 1;
+  cb->serv->ep.ep_val[0].family = strdup ("inet");
+  if (__glibc_unlikely (cb->serv->ep.ep_val[0].family == NULL))
+    goto failed;
+  cb->callback = callback;
+  cb->userdata = userdata;
+
+  if ((flags & NO_AUTHINFO) || !key_secretkey_is_set ())
+    {
+      cb->serv->key_type = NIS_PK_NONE;
+      cb->serv->pkey.n_bytes = NULL;
+      cb->serv->pkey.n_len = 0;
+    }
+  else
+    {
+#if 0
+      if ((cb->serv->pkey.n_bytes = __nis_getpkey (cb->serv->name)) == NULL)
+	{
+	  cb->serv->pkey.n_len = 0;
+	  cb->serv->key_type = NIS_PK_NONE;
+	}
+      else
+	{
+	  cb->serv->key_type = NIS_PK_DH;
+	  cb->serv->pkey.n_len = strlen(cb->serv->pkey.n_bytes);
+	}
+#else
+      cb->serv->pkey.n_len =0;
+      cb->serv->pkey.n_bytes = NULL;
+      cb->serv->key_type = NIS_PK_NONE;
+#endif
+    }
+
+  cb->serv->ep.ep_val[0].proto = strdup ((flags & USE_DGRAM) ? "udp" : "tcp");
+  if (__glibc_unlikely (cb->serv->ep.ep_val[0].proto == NULL))
+    goto failed;
+  cb->xprt = ((flags & USE_DGRAM)
+	      ? svcudp_bufcreate (sock, 100, 8192)
+	      : svctcp_create (sock, 100, 8192));
+  if (cb->xprt == NULL)
+    {
+      nomsg = 1;
+      goto failed;
+    }
+  cb->sock = cb->xprt->xp_sock;
+  if (!svc_register (cb->xprt, CB_PROG, CB_VERS, cb_prog_1, 0))
+    {
+      xprt_unregister (cb->xprt);
+      svc_destroy (cb->xprt);
+      xdr_free ((xdrproc_t) _xdr_nis_server, (char *) cb->serv);
+      free (cb);
+      syslog (LOG_ERR, "NIS+: failed to register callback dispatcher");
+      return NULL;
+    }
+
+  if (getsockname (cb->sock, (struct sockaddr *) &sin, &len) == -1)
+    {
+      xprt_unregister (cb->xprt);
+      svc_destroy (cb->xprt);
+      xdr_free ((xdrproc_t) _xdr_nis_server, (char *) cb->serv);
+      free (cb);
+      syslog (LOG_ERR, "NIS+: failed to read local socket info");
+      return NULL;
+    }
+  port = ntohs (sin.sin_port);
+  get_myaddress (&sin);
+
+  if (asprintf (&cb->serv->ep.ep_val[0].uaddr, "%s.%d.%d",
+		inet_ntoa (sin.sin_addr), (port & 0xFF00) >> 8, port & 0x00FF)
+      < 0)
+    goto failed;
+
+  return cb;
+
+ failed:
+  if (cb)
+    {
+      if (cb->xprt)
+	svc_destroy (cb->xprt);
+      xdr_free ((xdrproc_t) _xdr_nis_server, (char *) cb->serv);
+      free (cb);
+    }
+  if (!nomsg)
+    syslog (LOG_ERR, "NIS+: out of memory allocating callback");
+  return NULL;
+}
+
+nis_error
+__nis_destroy_callback (struct nis_cb *cb)
+{
+  xprt_unregister (cb->xprt);
+  svc_destroy (cb->xprt);
+  close (cb->sock);
+  xdr_free ((xdrproc_t) _xdr_nis_server, (char *) cb->serv);
+  free (cb);
+
+  return NIS_SUCCESS;
+}
diff --git a/REORG.TODO/nis/nis_checkpoint.c b/REORG.TODO/nis/nis_checkpoint.c
new file mode 100644
index 0000000000..f148af4170
--- /dev/null
+++ b/REORG.TODO/nis/nis_checkpoint.c
@@ -0,0 +1,80 @@
+/* Copyright (c) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <string.h>
+#include <rpcsvc/nis.h>
+#include <shlib-compat.h>
+
+#include "nis_xdr.h"
+#include "nis_intern.h"
+
+nis_result *
+nis_checkpoint (const_nis_name dirname)
+{
+  nis_result *res;
+
+  res = calloc (1, sizeof (nis_result));
+  if (res == NULL)
+    return NULL;
+
+  if (dirname != NULL)
+    {
+      nis_result *res2;
+      u_int i;
+
+      res2 = nis_lookup (dirname, EXPAND_NAME);
+      if (NIS_RES_STATUS (res2) != NIS_SUCCESS)
+	{
+	  free (res);
+	  return res2;
+	}
+
+      /* Check if obj is really a diryectory object */
+      if (__type_of (NIS_RES_OBJECT (res2)) != NIS_DIRECTORY_OBJ)
+	{
+	  nis_freeresult (res2);
+	  NIS_RES_STATUS (res) = NIS_INVALIDOBJ;
+	  return res;
+	}
+
+      for (i = 0;
+	   i < NIS_RES_OBJECT (res2)->DI_data.do_servers.do_servers_len; ++i)
+	{
+	  cp_result cpres;
+
+	  memset (&cpres, '\0', sizeof (cp_result));
+	  if (__do_niscall2 (&NIS_RES_OBJECT(res2)->DI_data.do_servers.do_servers_val[i],
+			     1, NIS_CHECKPOINT, (xdrproc_t) _xdr_nis_name,
+			     (caddr_t) &dirname, (xdrproc_t) _xdr_cp_result,
+			     (caddr_t) &cpres, 0, NULL) != NIS_SUCCESS)
+	    NIS_RES_STATUS (res) = NIS_RPCERROR;
+	  else
+	    {
+	      NIS_RES_STATUS (res) = cpres.cp_status;
+	      res->zticks += cpres.cp_zticks;
+	      res->dticks += cpres.cp_dticks;
+	    }
+	}
+      nis_freeresult (res2);
+    }
+  else
+    NIS_RES_STATUS (res) = NIS_NOSUCHNAME;
+
+  return res;
+}
+libnsl_hidden_nolink_def (nis_checkpoint, GLIBC_2_1)
diff --git a/REORG.TODO/nis/nis_clone_dir.c b/REORG.TODO/nis/nis_clone_dir.c
new file mode 100644
index 0000000000..982f475218
--- /dev/null
+++ b/REORG.TODO/nis/nis_clone_dir.c
@@ -0,0 +1,75 @@
+/* Copyright (c) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <string.h>
+#include <rpc/rpc.h>
+#include <rpcsvc/nis.h>
+#include <shlib-compat.h>
+
+#include "nis_xdr.h"
+
+directory_obj *
+nis_clone_directory (const directory_obj *src, directory_obj *dest)
+{
+  char *addr;
+  unsigned int size;
+  XDR xdrs;
+
+  if (src == NULL)
+    return NULL;
+
+  size = xdr_sizeof ((xdrproc_t)_xdr_directory_obj, (char *)src);
+  if ((addr = calloc(1, size)) == NULL)
+    return NULL;
+
+  xdrmem_create(&xdrs, addr, size, XDR_ENCODE);
+  if (!_xdr_directory_obj (&xdrs, (directory_obj *)src))
+    {
+      xdr_destroy (&xdrs);
+      free (addr);
+      return NULL;
+    }
+  xdr_destroy (&xdrs);
+
+  directory_obj *res;
+  if (dest == NULL)
+    {
+      if ((res = calloc (1, sizeof (directory_obj))) == NULL)
+	{
+	  free (addr);
+	  return NULL;
+	}
+    }
+  else
+    res = dest;
+
+  xdrmem_create (&xdrs, addr, size, XDR_DECODE);
+  if (!_xdr_directory_obj (&xdrs, res))
+    {
+      xdr_destroy (&xdrs);
+      if (res != dest)
+	free (res);
+      free (addr);
+      return NULL;
+    }
+  xdr_destroy (&xdrs);
+  free (addr);
+
+  return res;
+}
+libnsl_hidden_nolink_def(nis_clone_directory, GLIBC_2_1)
diff --git a/REORG.TODO/nis/nis_clone_obj.c b/REORG.TODO/nis/nis_clone_obj.c
new file mode 100644
index 0000000000..1d7e2e3ca5
--- /dev/null
+++ b/REORG.TODO/nis/nis_clone_obj.c
@@ -0,0 +1,68 @@
+/* Copyright (c) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <string.h>
+#include <rpc/rpc.h>
+#include <rpcsvc/nis.h>
+#include <shlib-compat.h>
+
+#include "nis_xdr.h"
+
+nis_object *
+nis_clone_object (const nis_object *src, nis_object *dest)
+{
+  char *addr;
+  unsigned int size;
+  XDR xdrs;
+  nis_object *res = NULL;
+
+  if (src == NULL)
+    return (NULL);
+
+  size = xdr_sizeof ((xdrproc_t)_xdr_nis_object, (char *) src);
+  if ((addr = calloc (1, size)) == NULL)
+    return NULL;
+
+  if (dest == NULL)
+    {
+      if ((res = calloc (1, sizeof (nis_object))) == NULL)
+	goto out;
+    }
+  else
+    res = dest;
+
+  xdrmem_create (&xdrs, addr, size, XDR_ENCODE);
+  if (!_xdr_nis_object (&xdrs, (nis_object *) src))
+    goto out2;
+  xdr_destroy (&xdrs);
+  xdrmem_create (&xdrs, addr, size, XDR_DECODE);
+  if (!_xdr_nis_object (&xdrs, res))
+    {
+    out2:
+      if (dest == NULL)
+	free (res);
+      res = NULL;
+    }
+
+  xdr_destroy (&xdrs);
+ out:
+  free (addr);
+
+  return res;
+}
+libnsl_hidden_nolink_def (nis_clone_object, GLIBC_2_1)
diff --git a/REORG.TODO/nis/nis_clone_res.c b/REORG.TODO/nis/nis_clone_res.c
new file mode 100644
index 0000000000..db7716538a
--- /dev/null
+++ b/REORG.TODO/nis/nis_clone_res.c
@@ -0,0 +1,75 @@
+/* Copyright (c) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <string.h>
+#include <rpc/rpc.h>
+#include <rpcsvc/nis.h>
+#include <shlib-compat.h>
+
+#include "nis_xdr.h"
+
+nis_result *
+nis_clone_result (const nis_result *src, nis_result *dest)
+{
+  char *addr;
+  unsigned int size;
+  XDR xdrs;
+
+  if (src == NULL)
+    return (NULL);
+
+  size = xdr_sizeof ((xdrproc_t)_xdr_nis_result, (char *)src);
+  if ((addr = calloc(1, size)) == NULL)
+    return NULL;
+
+  xdrmem_create (&xdrs, addr, size, XDR_ENCODE);
+  if (!_xdr_nis_result (&xdrs, (nis_result *)src))
+    {
+      xdr_destroy (&xdrs);
+      free (addr);
+      return NULL;
+    }
+  xdr_destroy (&xdrs);
+
+  nis_result *res;
+  if (dest == NULL)
+    {
+      if ((res = calloc (1, sizeof (nis_result))) == NULL)
+	{
+	  free (addr);
+	  return NULL;
+	}
+    }
+  else
+    res = dest;
+
+  xdrmem_create (&xdrs, addr, size, XDR_DECODE);
+  if (!_xdr_nis_result (&xdrs, res))
+    {
+      xdr_destroy (&xdrs);
+      if (res != dest)
+	free (res);
+      free (addr);
+      return NULL;
+    }
+  xdr_destroy (&xdrs);
+  free (addr);
+
+  return res;
+}
+libnsl_hidden_nolink_def (nis_clone_result, GLIBC_2_1)
diff --git a/REORG.TODO/nis/nis_creategroup.c b/REORG.TODO/nis/nis_creategroup.c
new file mode 100644
index 0000000000..1d7e058710
--- /dev/null
+++ b/REORG.TODO/nis/nis_creategroup.c
@@ -0,0 +1,85 @@
+/* Copyright (c) 1997-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <time.h>
+#include <string.h>
+#include <rpcsvc/nis.h>
+#include <shlib-compat.h>
+
+nis_error
+nis_creategroup (const_nis_name group, unsigned int flags)
+{
+  if (group != NULL && group[0] != '\0')
+    {
+      size_t grouplen = strlen (group);
+      char buf[grouplen + 50];
+      char leafbuf[grouplen + 2];
+      char domainbuf[grouplen + 2];
+      nis_error status;
+      nis_result *res;
+      char *cp, *cp2;
+      nis_object *obj;
+
+      cp = stpcpy (buf, nis_leaf_of_r (group, leafbuf, sizeof (leafbuf) - 1));
+      cp = stpcpy (cp, ".groups_dir");
+      cp2 = nis_domain_of_r (group, domainbuf, sizeof (domainbuf) - 1);
+      if (cp2 != NULL && cp2[0] != '\0')
+        {
+	  *cp++ = '.';
+          stpcpy (cp, cp2);
+        }
+      else
+	return NIS_BADNAME;
+
+      obj = calloc (1, sizeof (nis_object));
+      if (__glibc_unlikely (obj == NULL))
+	return NIS_NOMEMORY;
+
+      obj->zo_oid.ctime = obj->zo_oid.mtime = time (NULL);
+      obj->zo_name = strdup (leafbuf);
+      obj->zo_owner = __nis_default_owner (NULL);
+      obj->zo_group = __nis_default_group (NULL);
+      obj->zo_domain = strdup (domainbuf);
+      if (obj->zo_name == NULL || obj->zo_owner == NULL
+	  || obj->zo_group == NULL || obj->zo_domain == NULL)
+	{
+	  free (obj->zo_group);
+	  free (obj->zo_owner);
+	  free (obj->zo_name);
+	  free (obj);
+	  return NIS_NOMEMORY;
+	}
+      obj->zo_access = __nis_default_access (NULL, 0);
+      obj->zo_ttl = 60 * 60;
+      obj->zo_data.zo_type = NIS_GROUP_OBJ;
+      obj->zo_data.objdata_u.gr_data.gr_flags = flags;
+      obj->zo_data.objdata_u.gr_data.gr_members.gr_members_len = 0;
+      obj->zo_data.objdata_u.gr_data.gr_members.gr_members_val = NULL;
+
+      res = nis_add (buf, obj);
+      nis_free_object (obj);
+      if (res == NULL)
+	return NIS_NOMEMORY;
+      status = NIS_RES_STATUS (res);
+      nis_freeresult (res);
+
+      return status;
+    }
+  return NIS_FAIL;
+}
+libnsl_hidden_nolink_def (nis_creategroup, GLIBC_2_1)
diff --git a/REORG.TODO/nis/nis_defaults.c b/REORG.TODO/nis/nis_defaults.c
new file mode 100644
index 0000000000..1188a81b30
--- /dev/null
+++ b/REORG.TODO/nis/nis_defaults.c
@@ -0,0 +1,456 @@
+/* Copyright (c) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <rpc/rpc.h>
+#include <rpcsvc/nis.h>
+#include <shlib-compat.h>
+
+#define DEFAULT_TTL 43200
+
+/*
+** Some functions for parsing the -D param and NIS_DEFAULTS Environ
+*/
+static nis_name
+searchXYX (char *str, const char *what)
+{
+  assert (strlen (what) == 6);
+  assert (strncmp (str, what, 6) == 0);
+  str += 6;			/* Points to the begin of the parameters.  */
+
+  int i = 0;
+  while (str[i] != '\0' && str[i] != ':')
+    ++i;
+  if (i == 0)			/* only "<WHAT>=" ? */
+    return strdup ("");
+
+  return strndup (str, i);
+}
+
+
+static nis_name
+searchgroup (char *str)
+{
+  return searchXYX (str, "group=");
+}
+
+
+static nis_name
+searchowner (char *str)
+{
+  return searchXYX (str, "owner=");
+}
+
+
+static uint32_t
+searchttl (char *str)
+{
+  char buf[strlen (str) + 1];
+  char *cptr, *dptr;
+  uint32_t time;
+  int i;
+
+  dptr = strstr (str, "ttl=");
+  if (dptr == NULL)		/* should (could) not happen */
+    return DEFAULT_TTL;;
+
+  dptr += 4;			/* points to the begin of the new ttl */
+  i = 0;
+  while (dptr[i] != '\0' && dptr[i] != ':')
+    i++;
+  if (i == 0)			/* only "ttl=" ? */
+    return DEFAULT_TTL;
+
+  strncpy (buf, dptr, i);
+  buf[i] = '\0';
+  time = 0;
+
+  dptr = buf;
+  cptr = strchr (dptr, 'd');
+  if (cptr != NULL)
+    {
+      *cptr = '\0';
+      cptr++;
+      time += atoi (dptr) * 60 * 60 * 24;
+      dptr = cptr;
+    }
+
+  cptr = strchr (dptr, 'h');
+  if (cptr != NULL)
+    {
+      *cptr = '\0';
+      cptr++;
+      time += atoi (dptr) * 60 * 60;
+      dptr = cptr;
+    }
+
+  cptr = strchr (dptr, 'm');
+  if (cptr != NULL)
+    {
+      *cptr = '\0';
+      cptr++;
+      time += atoi (dptr) * 60;
+      dptr = cptr;
+    }
+
+  cptr = strchr (dptr, 's');
+  if (cptr != NULL)
+    *cptr = '\0';
+
+  time += atoi (dptr);
+
+  return time;
+}
+
+static unsigned int
+searchaccess (char *str, unsigned int access)
+{
+  char buf[strlen (str) + 1];
+  char *cptr;
+  unsigned int result = access;
+  int i;
+  int n, o, g, w;
+
+  cptr = strstr (str, "access=");
+  if (cptr == NULL)
+    return 0;
+
+  cptr += 7;			/* points to the begin of the access string */
+  i = 0;
+  while (cptr[i] != '\0' && cptr[i] != ':')
+    i++;
+  if (i == 0)			/* only "access=" ? */
+    return 0;
+
+  strncpy (buf, cptr, i);
+  buf[i] = '\0';
+
+  n = o = g = w = 0;
+  cptr = buf;
+  if (*cptr == ',') /* Fix for stupid Solaris scripts */
+    ++cptr;
+  while (*cptr != '\0')
+    {
+      switch (*cptr)
+	{
+	case 'n':
+	  n = 1;
+	  break;
+	case 'o':
+	  o = 1;
+	  break;
+	case 'g':
+	  g = 1;
+	  break;
+	case 'w':
+	  w = 1;
+	  break;
+	case 'a':
+	  o = g = w = 1;
+	  break;
+	case '-':
+	  cptr++;		/* Remove "-" from beginning */
+	  while (*cptr != '\0' && *cptr != ',')
+	    {
+	      switch (*cptr)
+		{
+		case 'r':
+		  if (n)
+		    result = result & ~(NIS_READ_ACC << 24);
+		  if (o)
+		    result = result & ~(NIS_READ_ACC << 16);
+		  if (g)
+		    result = result & ~(NIS_READ_ACC << 8);
+		  if (w)
+		    result = result & ~(NIS_READ_ACC);
+		  break;
+		case 'm':
+		  if (n)
+		    result = result & ~(NIS_MODIFY_ACC << 24);
+		  if (o)
+		    result = result & ~(NIS_MODIFY_ACC << 16);
+		  if (g)
+		    result = result & ~(NIS_MODIFY_ACC << 8);
+		  if (w)
+		    result = result & ~(NIS_MODIFY_ACC);
+		  break;
+		case 'c':
+		  if (n)
+		    result = result & ~(NIS_CREATE_ACC << 24);
+		  if (o)
+		    result = result & ~(NIS_CREATE_ACC << 16);
+		  if (g)
+		    result = result & ~(NIS_CREATE_ACC << 8);
+		  if (w)
+		    result = result & ~(NIS_CREATE_ACC);
+		  break;
+		case 'd':
+		  if (n)
+		    result = result & ~(NIS_DESTROY_ACC << 24);
+		  if (o)
+		    result = result & ~(NIS_DESTROY_ACC << 16);
+		  if (g)
+		    result = result & ~(NIS_DESTROY_ACC << 8);
+		  if (w)
+		    result = result & ~(NIS_DESTROY_ACC);
+		  break;
+		default:
+		  return (~0U);
+		}
+	      cptr++;
+	    }
+	  n = o = g = w = 0;
+	  break;
+	case '+':
+	  cptr++;		/* Remove "+" from beginning */
+	  while (*cptr != '\0' && *cptr != ',')
+	    {
+	      switch (*cptr)
+		{
+		case 'r':
+		  if (n)
+		    result = result | (NIS_READ_ACC << 24);
+		  if (o)
+		    result = result | (NIS_READ_ACC << 16);
+		  if (g)
+		    result = result | (NIS_READ_ACC << 8);
+		  if (w)
+		    result = result | (NIS_READ_ACC);
+		  break;
+		case 'm':
+		  if (n)
+		    result = result | (NIS_MODIFY_ACC << 24);
+		  if (o)
+		    result = result | (NIS_MODIFY_ACC << 16);
+		  if (g)
+		    result = result | (NIS_MODIFY_ACC << 8);
+		  if (w)
+		    result = result | (NIS_MODIFY_ACC);
+		  break;
+		case 'c':
+		  if (n)
+		    result = result | (NIS_CREATE_ACC << 24);
+		  if (o)
+		    result = result | (NIS_CREATE_ACC << 16);
+		  if (g)
+		    result = result | (NIS_CREATE_ACC << 8);
+		  if (w)
+		    result = result | (NIS_CREATE_ACC);
+		  break;
+		case 'd':
+		  if (n)
+		    result = result | (NIS_DESTROY_ACC << 24);
+		  if (o)
+		    result = result | (NIS_DESTROY_ACC << 16);
+		  if (g)
+		    result = result | (NIS_DESTROY_ACC << 8);
+		  if (w)
+		    result = result | (NIS_DESTROY_ACC);
+		  break;
+		default:
+		  return (~0U);
+		}
+	      cptr++;
+	    }
+	  n = o = g = w = 0;
+	  break;
+	case '=':
+	  cptr++;		/* Remove "=" from beginning */
+	  /* Clear */
+	  if (n)
+	    result = result & ~((NIS_READ_ACC + NIS_MODIFY_ACC +
+				 NIS_CREATE_ACC + NIS_DESTROY_ACC) << 24);
+
+	  if (o)
+	    result = result & ~((NIS_READ_ACC + NIS_MODIFY_ACC +
+				 NIS_CREATE_ACC + NIS_DESTROY_ACC) << 16);
+	  if (g)
+	    result = result & ~((NIS_READ_ACC + NIS_MODIFY_ACC +
+				 NIS_CREATE_ACC + NIS_DESTROY_ACC) << 8);
+	  if (w)
+	    result = result & ~(NIS_READ_ACC + NIS_MODIFY_ACC +
+				NIS_CREATE_ACC + NIS_DESTROY_ACC);
+	  while (*cptr != '\0' && *cptr != ',')
+	    {
+	      switch (*cptr)
+		{
+		case 'r':
+		  if (n)
+		    result = result | (NIS_READ_ACC << 24);
+		  if (o)
+		    result = result | (NIS_READ_ACC << 16);
+		  if (g)
+		    result = result | (NIS_READ_ACC << 8);
+		  if (w)
+		    result = result | (NIS_READ_ACC);
+		  break;
+		case 'm':
+		  if (n)
+		    result = result | (NIS_MODIFY_ACC << 24);
+		  if (o)
+		    result = result | (NIS_MODIFY_ACC << 16);
+		  if (g)
+		    result = result | (NIS_MODIFY_ACC << 8);
+		  if (w)
+		    result = result | (NIS_MODIFY_ACC);
+		  break;
+		case 'c':
+		  if (n)
+		    result = result | (NIS_CREATE_ACC << 24);
+		  if (o)
+		    result = result | (NIS_CREATE_ACC << 16);
+		  if (g)
+		    result = result | (NIS_CREATE_ACC << 8);
+		  if (w)
+		    result = result | (NIS_CREATE_ACC);
+		  break;
+		case 'd':
+		  if (n)
+		    result = result | (NIS_DESTROY_ACC << 24);
+		  if (o)
+		    result = result | (NIS_DESTROY_ACC << 16);
+		  if (g)
+		    result = result | (NIS_DESTROY_ACC << 8);
+		  if (w)
+		    result = result | (NIS_DESTROY_ACC);
+		  break;
+		default:
+		  return result = (~0U);
+		}
+	      cptr++;
+	    }
+	  n = o = g = w = 0;
+	  break;
+	default:
+	  return result = (~0U);
+	}
+      if (*cptr != '\0')
+	cptr++;
+    }
+
+  return result;
+}
+
+
+nis_name
+__nis_default_owner (char *defaults)
+{
+  char *default_owner = NULL;
+
+  char *cptr = defaults;
+  if (cptr == NULL)
+    cptr = getenv ("NIS_DEFAULTS");
+
+  if (cptr != NULL)
+    {
+      char *dptr = strstr (cptr, "owner=");
+      if (dptr != NULL)
+	{
+	  char *p = searchowner (dptr);
+	  if (p == NULL)
+	    return NULL;
+	  default_owner = strdupa (p);
+	  free (p);
+	}
+    }
+
+  return strdup (default_owner ?: nis_local_principal ());
+}
+libnsl_hidden_nolink_def (__nis_default_owner, GLIBC_2_1)
+
+
+nis_name
+__nis_default_group (char *defaults)
+{
+  char *default_group = NULL;
+
+  char *cptr = defaults;
+  if (cptr == NULL)
+    cptr = getenv ("NIS_DEFAULTS");
+
+  if (cptr != NULL)
+    {
+      char *dptr = strstr (cptr, "group=");
+      if (dptr != NULL)
+	{
+	  char *p = searchgroup (dptr);
+	  if (p == NULL)
+	    return NULL;
+	  default_group = strdupa (p);
+	  free (p);
+	}
+    }
+
+  return strdup (default_group ?: nis_local_group ());
+}
+libnsl_hidden_nolink_def (__nis_default_group, GLIBC_2_1)
+
+
+uint32_t
+__nis_default_ttl (char *defaults)
+{
+  char *cptr, *dptr;
+
+  if (defaults != NULL)
+    {
+      dptr = strstr (defaults, "ttl=");
+      if (dptr != NULL)
+	return searchttl (defaults);
+    }
+
+  cptr = getenv ("NIS_DEFAULTS");
+  if (cptr == NULL)
+    return DEFAULT_TTL;
+
+  dptr = strstr (cptr, "ttl=");
+  if (dptr == NULL)
+    return DEFAULT_TTL;
+
+  return searchttl (cptr);
+}
+
+/* Default access rights are ----rmcdr---r---, but we could change
+   this with the NIS_DEFAULTS variable. */
+unsigned int
+__nis_default_access (char *param, unsigned int defaults)
+{
+  unsigned int result;
+  char *cptr;
+
+  if (defaults == 0)
+    result = 0 | OWNER_DEFAULT | GROUP_DEFAULT | WORLD_DEFAULT;
+  else
+    result = defaults;
+
+  if (param != NULL && strstr (param, "access=") != NULL)
+    result = searchaccess (param, result);
+  else
+    {
+      cptr = getenv ("NIS_DEFAULTS");
+      if (cptr != NULL && strstr (cptr, "access=") != NULL)
+	result = searchaccess (cptr, result);
+    }
+
+  return result;
+}
+libnsl_hidden_nolink_def (__nis_default_access, GLIBC_2_1)
diff --git a/REORG.TODO/nis/nis_destroygroup.c b/REORG.TODO/nis/nis_destroygroup.c
new file mode 100644
index 0000000000..fbcd5efddf
--- /dev/null
+++ b/REORG.TODO/nis/nis_destroygroup.c
@@ -0,0 +1,53 @@
+/* Copyright (c) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <string.h>
+#include <rpcsvc/nis.h>
+#include <shlib-compat.h>
+
+nis_error
+nis_destroygroup (const_nis_name group)
+{
+  if (group != NULL && group[0] != '\0')
+    {
+      size_t grouplen = strlen (group);
+      char buf[grouplen + 50];
+      char leafbuf[grouplen + 3];
+      char domainbuf[grouplen + 3];
+      nis_error status;
+      nis_result *res;
+      char *cp, *cp2;
+
+      cp = stpcpy (buf, nis_leaf_of_r (group, leafbuf, sizeof (leafbuf) - 1));
+      cp = stpcpy (cp, ".groups_dir");
+      cp2 = nis_domain_of_r (group, domainbuf, sizeof (domainbuf) - 1);
+      if (cp2 != NULL && cp2[0] != '\0')
+	{
+	  *cp++ = '.';
+	  stpcpy (cp, cp2);
+	}
+      res = nis_remove (buf, NULL);
+      status = NIS_RES_STATUS (res);
+      nis_freeresult (res);
+      return status;
+    }
+  else
+    return NIS_FAIL;
+
+}
+libnsl_hidden_nolink_def (nis_destroygroup, GLIBC_2_1)
diff --git a/REORG.TODO/nis/nis_domain_of.c b/REORG.TODO/nis/nis_domain_of.c
new file mode 100644
index 0000000000..68d958f75e
--- /dev/null
+++ b/REORG.TODO/nis/nis_domain_of.c
@@ -0,0 +1,43 @@
+/* Copyright (c) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <rpcsvc/nis.h>
+#include <shlib-compat.h>
+
+nis_name
+nis_domain_of (const_nis_name name)
+{
+  static char result[NIS_MAXNAMELEN + 1];
+
+  return nis_domain_of_r (name, result, NIS_MAXNAMELEN);
+}
+libnsl_hidden_nolink_def (nis_domain_of, GLIBC_2_1)
+
+const_nis_name
+__nis_domain_of (const_nis_name name)
+{
+  const_nis_name cptr = strchr (name, '.');
+
+  if (cptr == NULL)
+    return "";
+
+  if (*++cptr == '\0')
+    return ".";
+
+  return cptr;
+}
diff --git a/REORG.TODO/nis/nis_domain_of_r.c b/REORG.TODO/nis/nis_domain_of_r.c
new file mode 100644
index 0000000000..9711eca605
--- /dev/null
+++ b/REORG.TODO/nis/nis_domain_of_r.c
@@ -0,0 +1,62 @@
+/* Copyright (c) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <string.h>
+#include <rpcsvc/nis.h>
+#include <shlib-compat.h>
+
+nis_name
+nis_domain_of_r (const_nis_name name, char *buffer, size_t buflen)
+{
+  char *cptr;
+  size_t cptr_len;
+
+  if (buffer == NULL)
+    {
+    erange:
+      __set_errno (ERANGE);
+      return NULL;
+    }
+
+  buffer[0] = '\0';
+
+  cptr = strchr (name, '.');
+
+  if (cptr == NULL)
+    return buffer;
+
+  ++cptr;
+  cptr_len = strlen (cptr);
+
+  if (cptr_len == 0)
+    {
+      if (buflen < 2)
+	goto erange;
+      return strcpy (buffer, ".");
+    }
+
+  if (__glibc_unlikely (cptr_len >= buflen))
+    {
+      __set_errno (ERANGE);
+      return NULL;
+    }
+
+  return memcpy (buffer, cptr, cptr_len + 1);
+}
+libnsl_hidden_nolink_def (nis_domain_of_r, GLIBC_2_1)
diff --git a/REORG.TODO/nis/nis_error.c b/REORG.TODO/nis/nis_error.c
new file mode 100644
index 0000000000..32b2a100f6
--- /dev/null
+++ b/REORG.TODO/nis/nis_error.c
@@ -0,0 +1,101 @@
+/* Copyright (c) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <syslog.h>
+#include <string.h>
+#include <libintl.h>
+#include <rpcsvc/nis.h>
+#include <shlib-compat.h>
+
+
+#define MF(line) MF1 (line)
+#define MF1(line) str##line
+static const union msgstr_t
+{
+  struct
+  {
+#define S(s) char MF(__LINE__)[sizeof (s)];
+#include "nis_error.h"
+#undef S
+  };
+  char str[0];
+} msgstr =
+  {
+    {
+#define S(s) s,
+#include "nis_error.h"
+#undef S
+    }
+  };
+
+static const unsigned short int msgidx[] =
+  {
+#define S(s) offsetof (union msgstr_t, MF (__LINE__)),
+#include "nis_error.h"
+#undef S
+  };
+
+
+const char *
+nis_sperrno (const nis_error status)
+{
+  if (status >= sizeof (msgidx) / sizeof (msgidx[0]))
+    return "???";
+  else
+    return gettext (msgstr.str + msgidx[status]);
+}
+libnsl_hidden_nolink_def (nis_sperrno, GLIBC_2_1)
+
+void
+nis_perror (const nis_error status, const char *label)
+{
+  fprintf (stderr, "%s: %s\n", label, nis_sperrno (status));
+}
+libnsl_hidden_nolink_def (nis_perror, GLIBC_2_1)
+
+void
+nis_lerror (const nis_error status, const char *label)
+{
+  syslog (LOG_ERR, "%s: %s", label, nis_sperrno (status));
+}
+libnsl_hidden_nolink_def (nis_lerror, GLIBC_2_1)
+
+char *
+nis_sperror_r (const nis_error status, const char *label,
+	       char *buffer, size_t buflen)
+{
+  if (snprintf (buffer, buflen, "%s: %s", label, nis_sperrno (status))
+      >= buflen)
+    {
+      __set_errno (ERANGE);
+      return NULL;
+    }
+
+  return buffer;
+}
+libnsl_hidden_nolink_def (nis_sperror_r, GLIBC_2_1)
+
+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));
+}
+libnsl_hidden_nolink_def (nis_sperror, GLIBC_2_1)
diff --git a/REORG.TODO/nis/nis_error.h b/REORG.TODO/nis/nis_error.h
new file mode 100644
index 0000000000..add1316d9f
--- /dev/null
+++ b/REORG.TODO/nis/nis_error.h
@@ -0,0 +1,48 @@
+S(N_("Success"))
+S(N_("Probable success"))
+S(N_("Not found"))
+S(N_("Probably not found"))
+S(N_("Cache expired"))
+S(N_("NIS+ servers unreachable"))
+S(N_("Unknown object"))
+S(N_("Server busy, try again"))
+S(N_("Generic system error"))
+S(N_("First/next chain broken"))
+S(N_("Permission denied"))
+S(N_("Not owner"))
+S(N_("Name not served by this server"))
+S(N_("Server out of memory"))
+S(N_("Object with same name exists"))
+S(N_("Not master server for this domain"))
+S(N_("Invalid object for operation"))
+S(N_("Malformed name, or illegal name"))
+S(N_("Unable to create callback"))
+S(N_("Results sent to callback proc"))
+S(N_("Not found, no such name"))
+S(N_("Name/entry isn't unique"))
+S(N_("Modification failed"))
+S(N_("Database for table does not exist"))
+S(N_("Entry/table type mismatch"))
+S(N_("Link points to illegal name"))
+S(N_("Partial success"))
+S(N_("Too many attributes"))
+S(N_("Error in RPC subsystem"))
+S(N_("Missing or malformed attribute"))
+S(N_("Named object is not searchable"))
+S(N_("Error while talking to callback proc"))
+S(N_("Non NIS+ namespace encountered"))
+S(N_("Illegal object type for operation"))
+S(N_("Passed object is not the same object on server"))
+S(N_("Modify operation failed"))
+S(N_("Query illegal for named table"))
+S(N_("Attempt to remove a non-empty table"))
+S(N_("Error in accessing NIS+ cold start file.  Is NIS+ installed?"))
+S(N_("Full resync required for directory"))
+S(N_("NIS+ operation failed"))
+S(N_("NIS+ service is unavailable or not installed"))
+S(N_("Yes, 42 is the meaning of life"))
+S(N_("Unable to authenticate NIS+ server"))
+S(N_("Unable to authenticate NIS+ client"))
+S(N_("No file space on server"))
+S(N_("Unable to create process on server"))
+S(N_("Master server busy, full dump rescheduled."))
diff --git a/REORG.TODO/nis/nis_file.c b/REORG.TODO/nis/nis_file.c
new file mode 100644
index 0000000000..d6c1d14aae
--- /dev/null
+++ b/REORG.TODO/nis/nis_file.c
@@ -0,0 +1,106 @@
+/* Copyright (c) 1997-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <rpcsvc/nis.h>
+#include <shlib-compat.h>
+#include "nis_xdr.h"
+
+typedef bool_t (*iofct_t) (XDR *, void *);
+typedef void (*freefct_t) (void *);
+
+
+static void *
+read_nis_obj (const char *name, iofct_t readfct, freefct_t freefct,
+	      size_t objsize)
+{
+  FILE *in = fopen (name, "rce");
+  if (in == NULL)
+    return NULL;
+
+  void *obj = calloc (1, objsize);
+
+  if (obj != NULL)
+    {
+      XDR xdrs;
+      xdrstdio_create (&xdrs, in, XDR_DECODE);
+      bool_t status = readfct (&xdrs, obj);
+      xdr_destroy (&xdrs);
+
+      if (!status)
+	{
+	  freefct (obj);
+	  obj = NULL;
+	}
+    }
+
+  fclose (in);
+
+  return obj;
+}
+
+static bool_t
+write_nis_obj (const char *name, const void *obj, iofct_t writefct)
+{
+  FILE *out = fopen (name, "wce");
+  if (out == NULL)
+    return FALSE;
+
+  XDR xdrs;
+  xdrstdio_create (&xdrs, out, XDR_ENCODE);
+  bool_t status = writefct (&xdrs, (void *) obj);
+  xdr_destroy (&xdrs);
+  fclose (out);
+
+  return status;
+}
+
+
+static const char cold_start_file[] = "/var/nis/NIS_COLD_START";
+
+directory_obj *
+readColdStartFile (void)
+{
+  return read_nis_obj (cold_start_file, (iofct_t) _xdr_directory_obj,
+		       (freefct_t) nis_free_directory, sizeof (directory_obj));
+}
+libnsl_hidden_nolink_def (readColdStartFile, GLIBC_2_1)
+
+bool_t
+writeColdStartFile (const directory_obj *obj)
+{
+  return write_nis_obj (cold_start_file, obj, (iofct_t) _xdr_directory_obj);
+}
+libnsl_hidden_nolink_def (writeColdStartFile, GLIBC_2_1)
+
+nis_object *
+nis_read_obj (const char *name)
+{
+  return read_nis_obj (name, (iofct_t) _xdr_nis_object,
+		       (freefct_t) nis_free_object, sizeof (nis_object));
+}
+libnsl_hidden_nolink_def (nis_read_obj, GLIBC_2_1)
+
+bool_t
+nis_write_obj (const char *name, const nis_object *obj)
+{
+  return write_nis_obj (name, obj, (iofct_t) _xdr_nis_object);
+}
+libnsl_hidden_nolink_def (nis_write_obj, GLIBC_2_1)
diff --git a/REORG.TODO/nis/nis_findserv.c b/REORG.TODO/nis/nis_findserv.c
new file mode 100644
index 0000000000..8e01164e3d
--- /dev/null
+++ b/REORG.TODO/nis/nis_findserv.c
@@ -0,0 +1,218 @@
+/* Copyright (C) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_clnt.h>
+#include <rpcsvc/nis.h>
+
+#include "nis_intern.h"
+
+/* Private data kept per client handle, from sunrpc/clnt_udp.c */
+struct cu_data
+  {
+    int cu_sock;
+    bool_t cu_closeit;
+    struct sockaddr_in cu_raddr;
+    int cu_rlen;
+    struct timeval cu_wait;
+    struct timeval cu_total;
+    struct rpc_err cu_error;
+    XDR cu_outxdrs;
+    u_int cu_xdrpos;
+    u_int cu_sendsz;
+    char *cu_outbuf;
+    u_int cu_recvsz;
+    char cu_inbuf[1];
+  };
+
+
+/*
+ * Find the mapped port for program,version.
+ * Calls the pmap service remotely to do the lookup.
+ * Returns 0 if no map exists.
+ */
+u_short
+__pmap_getnisport (struct sockaddr_in *address, u_long program,
+		   u_long version, u_int protocol)
+{
+  return __libc_rpc_getport (address, program, version, protocol, 1, 1);
+}
+
+/* This is now the public function, which should find the fastest server */
+
+struct findserv_req
+{
+  struct sockaddr_in sin;
+  u_int32_t xid;
+  u_int server_nr;
+  u_int server_ep;
+};
+
+
+static long int
+__nis_findfastest_with_timeout (dir_binding *bind,
+				const struct timeval *timeout)
+{
+  static const struct timeval TIMEOUT00 = { 0, 0 };
+  struct findserv_req *pings;
+  struct sockaddr_in sin, saved_sin;
+  int found = -1;
+  u_int32_t xid_seed;
+  int sock, dontblock = 1;
+  CLIENT *clnt;
+  u_long i, j, pings_count, pings_max, fastest = -1;
+  struct cu_data *cu;
+
+  pings_max = bind->server_len * 2;	/* Reserve a little bit more memory
+					   for multihomed hosts */
+  pings_count = 0;
+  pings = malloc (sizeof (struct findserv_req) * pings_max);
+  xid_seed = (u_int32_t) (time (NULL) ^ getpid ());
+
+  if (__glibc_unlikely (pings == NULL))
+    return -1;
+
+  memset (&sin, '\0', sizeof (sin));
+  sin.sin_family = AF_INET;
+  for (i = 0; i < bind->server_len; i++)
+    for (j = 0; j < bind->server_val[i].ep.ep_len; ++j)
+      if (strcmp (bind->server_val[i].ep.ep_val[j].family, "inet") == 0)
+	if ((bind->server_val[i].ep.ep_val[j].proto == NULL) ||
+	    (bind->server_val[i].ep.ep_val[j].proto[0] == '-') ||
+	    (bind->server_val[i].ep.ep_val[j].proto[0] == '\0'))
+	  {
+	    sin.sin_addr.s_addr =
+	      inetstr2int (bind->server_val[i].ep.ep_val[j].uaddr);
+	    if (sin.sin_addr.s_addr == 0)
+	      continue;
+	    sin.sin_port = htons (__pmap_getnisport (&sin, NIS_PROG,
+						     NIS_VERSION,
+						     IPPROTO_UDP));
+	    if (sin.sin_port == 0)
+	      continue;
+
+	    if (pings_count >= pings_max)
+	      {
+		struct findserv_req *new_pings;
+
+		pings_max += 10;
+		new_pings = realloc (pings, sizeof (struct findserv_req) *
+				     pings_max);
+		if (__glibc_unlikely (new_pings == NULL))
+		  {
+		    free (pings);
+		    return -1;
+		  }
+		pings = new_pings;
+	      }
+	    memcpy ((char *) &pings[pings_count].sin, (char *) &sin,
+		    sizeof (sin));
+	    memcpy ((char *)&saved_sin, (char *)&sin, sizeof(sin));
+	    pings[pings_count].xid = xid_seed + pings_count;
+	    pings[pings_count].server_nr = i;
+	    pings[pings_count].server_ep = j;
+	    ++pings_count;
+	  }
+
+  /* Make sure at least one server was assigned */
+  if (pings_count == 0)
+    {
+      free (pings);
+      return -1;
+    }
+
+  /* Create RPC handle */
+  sock = socket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
+  clnt = clntudp_create (&saved_sin, NIS_PROG, NIS_VERSION, *timeout, &sock);
+  if (clnt == NULL)
+    {
+      close (sock);
+      free (pings);
+      return -1;
+    }
+  auth_destroy (clnt->cl_auth);
+  clnt->cl_auth = authunix_create_default ();
+  cu = (struct cu_data *) clnt->cl_private;
+  ioctl (sock, FIONBIO, &dontblock);
+  /* Send to all servers the NULLPROC */
+  for (i = 0; i < pings_count; ++i)
+    {
+      /* clntudp_call() will increment, subtract one */
+      *((u_int32_t *) (cu->cu_outbuf)) = pings[i].xid - 1;
+      memcpy ((char *) &cu->cu_raddr, (char *) &pings[i].sin,
+	      sizeof (struct sockaddr_in));
+      /* Transmit to NULLPROC, return immediately. */
+      clnt_call (clnt, NULLPROC,
+		 (xdrproc_t) xdr_void, (caddr_t) 0,
+		 (xdrproc_t) xdr_void, (caddr_t) 0, TIMEOUT00);
+    }
+
+  while (found == -1) {
+    /* Receive reply from NULLPROC asynchronously. Note null inproc. */
+    int rc = clnt_call (clnt, NULLPROC,
+			(xdrproc_t) NULL, (caddr_t) 0,
+			(xdrproc_t) xdr_void, (caddr_t) 0,
+			*timeout);
+    if (RPC_SUCCESS == rc) {
+      u_int32_t val;
+      memcpy (&val, cu->cu_inbuf, sizeof (u_int32_t));
+      fastest = val - xid_seed;
+      if (fastest < pings_count) {
+	bind->server_used = pings[fastest].server_nr;
+	bind->current_ep = pings[fastest].server_ep;
+	found = 1;
+      }
+    } else {
+      /*      clnt_perror(clnt, "__nis_findfastest"); */
+      break;
+    }
+  }
+
+
+  auth_destroy (clnt->cl_auth);
+  clnt_destroy (clnt);
+  close (sock);
+
+  free (pings);
+
+  return found;
+}
+
+
+long int
+__nis_findfastest (dir_binding *bind)
+{
+  struct timeval timeout = { __NIS_PING_TIMEOUT_START, 0 };
+  long int found = -1;
+  long int retry = __NIS_PING_RETRY + 1;
+
+  while (retry--)
+    {
+      found = __nis_findfastest_with_timeout (bind, &timeout);
+      if (found != -1)
+	break;
+      timeout.tv_sec += __NIS_PING_TIMEOUT_INCREMENT;
+    }
+
+  return found;
+}
diff --git a/REORG.TODO/nis/nis_free.c b/REORG.TODO/nis/nis_free.c
new file mode 100644
index 0000000000..1d3298f2a9
--- /dev/null
+++ b/REORG.TODO/nis/nis_free.c
@@ -0,0 +1,76 @@
+/* Copyright (c) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <rpcsvc/nis.h>
+#include <shlib-compat.h>
+#include "nis_xdr.h"
+
+void
+__free_fdresult (fd_result *res)
+{
+  if (res != NULL)
+    {
+      xdr_free ((xdrproc_t)_xdr_fd_result, (char *)res);
+      free (res);
+    }
+}
+libnsl_hidden_nolink_def (__free_fdresult, GLIBC_2_1)
+
+void
+nis_free_request (ib_request *ibreq)
+{
+  if (ibreq != NULL)
+    {
+      xdr_free ((xdrproc_t)_xdr_ib_request, (char *)ibreq);
+      free (ibreq);
+    }
+}
+libnsl_hidden_nolink_def (nis_free_request, GLIBC_2_1)
+
+void
+nis_free_directory (directory_obj *obj)
+{
+  if (obj != NULL)
+    {
+      xdr_free ((xdrproc_t)_xdr_directory_obj, (char *)obj);
+      free (obj);
+    }
+}
+libnsl_hidden_nolink_def (nis_free_directory, GLIBC_2_1)
+
+void
+nis_free_object (nis_object *obj)
+{
+  if (obj != NULL)
+    {
+      xdr_free ((xdrproc_t)_xdr_nis_object, (char *)obj);
+      free (obj);
+    }
+}
+libnsl_hidden_nolink_def (nis_free_object, GLIBC_2_1)
+
+void
+nis_freeresult (nis_result *res)
+{
+  if (res != NULL)
+    {
+      xdr_free ((xdrproc_t)_xdr_nis_result, (char *)res);
+      free (res);
+    }
+}
+libnsl_hidden_nolink_def (nis_freeresult, GLIBC_2_1)
diff --git a/REORG.TODO/nis/nis_getservlist.c b/REORG.TODO/nis/nis_getservlist.c
new file mode 100644
index 0000000000..fba18c77ca
--- /dev/null
+++ b/REORG.TODO/nis/nis_getservlist.c
@@ -0,0 +1,171 @@
+/* Copyright (c) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <string.h>
+#include <rpcsvc/nis.h>
+#include <shlib-compat.h>
+
+#include "nis_xdr.h"
+#include "nis_intern.h"
+
+nis_server **
+nis_getservlist (const_nis_name dir)
+{
+  nis_result *res;
+  nis_server **serv;
+
+  res = nis_lookup (dir, FOLLOW_LINKS);
+
+  if (res != NULL && NIS_RES_STATUS (res) == NIS_SUCCESS)
+    {
+      unsigned long i;
+      nis_server *server;
+
+      serv =
+	malloc (sizeof (nis_server *) *
+		(NIS_RES_OBJECT (res)->DI_data.do_servers.do_servers_len + 1));
+      if (__glibc_unlikely (serv == NULL))
+	{
+	  nis_freeresult (res);
+	  return NULL;
+	}
+
+      for (i = 0; i < NIS_RES_OBJECT (res)->DI_data.do_servers.do_servers_len;
+	   ++i)
+	{
+	  server =
+	    &NIS_RES_OBJECT (res)->DI_data.do_servers.do_servers_val[i];
+	  serv[i] = calloc (1, sizeof (nis_server));
+	  if (__glibc_unlikely (serv[i] == NULL))
+	    {
+	    free_all:
+	      while (i-- > 0)
+		{
+		  free (serv[i]->pkey.n_bytes);
+		  if (serv[i]->ep.ep_val != NULL)
+		    {
+		      unsigned long int j;
+		      for (j = 0; j < serv[i]->ep.ep_len; ++j)
+			{
+			  free (serv[i]->ep.ep_val[j].proto);
+			  free (serv[i]->ep.ep_val[j].family);
+			  free (serv[i]->ep.ep_val[j].uaddr);
+			}
+		      free (serv[i]->ep.ep_val);
+		    }
+		  free (serv[i]->name);
+		  free (serv[i]);
+		}
+
+	      free (serv);
+
+	      nis_freeresult (res);
+
+	      return NULL;
+	    }
+
+	  if (server->name != NULL)
+	    {
+	      serv[i]->name = strdup (server->name);
+	      if (__glibc_unlikely (serv[i]->name == NULL))
+		{
+		  ++i;
+		  goto free_all;
+		}
+	    }
+
+          serv[i]->ep.ep_len = server->ep.ep_len;
+          if (serv[i]->ep.ep_len > 0)
+            {
+              unsigned long int j;
+
+              serv[i]->ep.ep_val =
+		malloc (server->ep.ep_len * sizeof (endpoint));
+	      if (__glibc_unlikely (serv[i]->ep.ep_val == NULL))
+		{
+		  ++i;
+		  goto free_all;
+		}
+
+              for (j = 0; j < serv[i]->ep.ep_len; ++j)
+                {
+                  if (server->ep.ep_val[j].uaddr)
+                    serv[i]->ep.ep_val[j].uaddr =
+		      strdup (server->ep.ep_val[j].uaddr);
+                  else
+                    serv[i]->ep.ep_val[j].uaddr = NULL;
+                  if (server->ep.ep_val[j].family)
+		    serv[i]->ep.ep_val[j].family =
+		      strdup (server->ep.ep_val[j].family);
+                  else
+                    serv[i]->ep.ep_val[j].family = NULL;
+                  if (server->ep.ep_val[j].proto)
+		    serv[i]->ep.ep_val[j].proto =
+		      strdup (server->ep.ep_val[j].proto);
+                  else
+		    serv[i]->ep.ep_val[j].proto = NULL;
+                }
+            }
+
+          serv[i]->key_type = server->key_type;
+          serv[i]->pkey.n_len = server->pkey.n_len;
+          if (server->pkey.n_len > 0)
+            {
+              serv[i]->pkey.n_bytes = malloc (server->pkey.n_len);
+              if (__glibc_unlikely (serv[i]->pkey.n_bytes == NULL))
+		{
+		  ++i;
+		  goto free_all;
+		}
+              memcpy (serv[i]->pkey.n_bytes, server->pkey.n_bytes,
+                      server->pkey.n_len);
+            }
+        }
+      serv[i] = NULL;
+    }
+  else
+    {
+      serv = malloc (sizeof (nis_server *));
+      if (__glibc_unlikely (serv != NULL))
+	serv[0] = NULL;
+    }
+
+  nis_freeresult (res);
+
+  return serv;
+}
+libnsl_hidden_nolink_def (nis_getservlist, GLIBC_2_1)
+
+void
+nis_freeservlist (nis_server **serv)
+{
+  int i;
+
+  if (serv == NULL)
+    return;
+
+  i = 0;
+  while (serv[i] != NULL)
+    {
+      xdr_free ((xdrproc_t)_xdr_nis_server, (char *)serv[i]);
+      free (serv[i]);
+      ++i;
+    }
+  free (serv);
+}
+libnsl_hidden_nolink_def (nis_freeservlist, GLIBC_2_1)
diff --git a/REORG.TODO/nis/nis_hash.c b/REORG.TODO/nis/nis_hash.c
new file mode 100644
index 0000000000..cc42ac8911
--- /dev/null
+++ b/REORG.TODO/nis/nis_hash.c
@@ -0,0 +1,76 @@
+/* Copyright (c) 1997-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stdint.h>
+#include <rpcsvc/nis.h>
+
+/* This is from libc/db/hash/hash_func.c, hash3 is static there */
+/*
+ * This is INCREDIBLY ugly, but fast.  We break the string up into 8 byte
+ * units.  On the first time through the loop we get the "leftover bytes"
+ * (strlen % 8).  On every other iteration, we perform 8 HASHC's so we handle
+ * all 8 bytes.  Essentially, this saves us 7 cmp & branch instructions.  If
+ * this routine is heavily used enough, it's worth the ugly coding.
+ *
+ * OZ's original sdbm hash
+ */
+uint32_t
+__nis_hash (const void *keyarg, size_t len)
+{
+  const u_char *key;
+  size_t loop;
+  uint32_t h;
+
+#define HASHC   h = *key++ + 65599 * h
+
+  h = 0;
+  key = keyarg;
+  if (len > 0)
+    {
+      loop = (len + 8 - 1) >> 3;
+      switch (len & (8 - 1))
+	{
+	case 0:
+	  do {
+	    HASHC;
+	    /* FALLTHROUGH */
+	  case 7:
+	    HASHC;
+	    /* FALLTHROUGH */
+	  case 6:
+	    HASHC;
+	    /* FALLTHROUGH */
+	  case 5:
+	    HASHC;
+	    /* FALLTHROUGH */
+	  case 4:
+	    HASHC;
+	    /* FALLTHROUGH */
+	  case 3:
+	    HASHC;
+	    /* FALLTHROUGH */
+	  case 2:
+	    HASHC;
+	    /* FALLTHROUGH */
+	  case 1:
+	    HASHC;
+	  } while (--loop);
+	}
+    }
+  return h;
+}
diff --git a/REORG.TODO/nis/nis_intern.h b/REORG.TODO/nis/nis_intern.h
new file mode 100644
index 0000000000..a541c287cf
--- /dev/null
+++ b/REORG.TODO/nis/nis_intern.h
@@ -0,0 +1,83 @@
+/* Copyright (c) 1997-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef __NIS_INTERN_H
+
+#define __NIS_INTERN_H
+#include <features.h>
+
+/* Configurable parameters for pinging NIS servers:  */
+
+/* Number of retries.  */
+#ifndef __NIS_PING_RETRY
+# define __NIS_PING_RETRY 2
+#endif
+/* Initial timeout in seconds.  */
+#ifndef __NIS_PING_TIMEOUT_START
+# define __NIS_PING_TIMEOUT_START 3
+#endif
+/* Timeout increment for retries in seconds.  */
+#ifndef __NIS_PING_TIMEOUT_INCREMENT
+# define __NIS_PING_TIMEOUT_INCREMENT 3
+#endif
+
+
+__BEGIN_DECLS
+
+struct nis_cb
+  {
+    nis_server *serv;
+    SVCXPRT *xprt;
+    int sock;
+    int nomore;
+    nis_error result;
+    int (*callback) (const_nis_name, const nis_object *, const void *);
+    const void *userdata;
+  };
+typedef struct nis_cb nis_cb;
+
+extern unsigned long int inetstr2int (const char *str);
+extern long int __nis_findfastest (dir_binding *bind);
+extern nis_error __do_niscall2 (const nis_server *serv, u_int serv_len,
+				u_long prog, xdrproc_t xargs, caddr_t req,
+				xdrproc_t xres, caddr_t resp,
+				unsigned int flags, nis_cb *cb);
+extern nis_error __do_niscall (const_nis_name name, u_long prog,
+			       xdrproc_t xargs, caddr_t req,
+			       xdrproc_t xres, caddr_t resp,
+			       unsigned int flags, nis_cb *cb);
+extern nis_error __do_niscall3 (dir_binding *dbp, u_long prog,
+				xdrproc_t xargs, caddr_t req,
+				xdrproc_t xres, caddr_t resp,
+				unsigned int flags, nis_cb *cb);
+libnsl_hidden_proto (__do_niscall3)
+
+extern u_short __pmap_getnisport (struct sockaddr_in *address, u_long program,
+				  u_long version, u_int protocol);
+
+/* NIS+ callback */
+extern nis_error __nis_do_callback (struct dir_binding *bptr,
+				    netobj *cookie, struct nis_cb *cb);
+extern struct nis_cb *__nis_create_callback
+      (int (*callback)(const_nis_name, const nis_object *, const void *),
+       const void *userdata, unsigned int flags);
+extern nis_error __nis_destroy_callback (struct nis_cb *cb);
+
+__END_DECLS
+
+#endif
diff --git a/REORG.TODO/nis/nis_ismember.c b/REORG.TODO/nis/nis_ismember.c
new file mode 100644
index 0000000000..5aba3367f5
--- /dev/null
+++ b/REORG.TODO/nis/nis_ismember.c
@@ -0,0 +1,150 @@
+/* Copyright (c) 1997-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <string.h>
+#include <rpcsvc/nis.h>
+#include <shlib-compat.h>
+
+/* internal_nis_ismember ()
+   return codes: -1 principal is in -group
+                  0 principal isn't in any group
+		  1 pirncipal is in group */
+static int
+internal_ismember (const_nis_name principal, const_nis_name group)
+{
+  size_t grouplen = strlen (group);
+  char buf[grouplen + 50];
+  char leafbuf[grouplen + 2];
+  char domainbuf[grouplen + 2];
+  nis_result *res;
+  char *cp, *cp2;
+  u_int i;
+
+  cp = stpcpy (buf, nis_leaf_of_r (group, leafbuf, sizeof (leafbuf) - 1));
+  cp = stpcpy (cp, ".groups_dir");
+  cp2 = nis_domain_of_r (group, domainbuf, sizeof (domainbuf) - 1);
+  if (cp2 != NULL && cp2[0] != '\0')
+    {
+      *cp++ = '.';
+      strcpy (cp, cp2);
+    }
+
+  res = nis_lookup (buf, EXPAND_NAME|FOLLOW_LINKS);
+  if (res == NULL || NIS_RES_STATUS (res) != NIS_SUCCESS)
+    {
+      nis_freeresult (res);
+      return 0;
+    }
+
+  if ((NIS_RES_NUMOBJ (res) != 1) ||
+      (__type_of (NIS_RES_OBJECT (res)) != NIS_GROUP_OBJ))
+    {
+      nis_freeresult (res);
+      return 0;
+    }
+
+  /* We search twice in the list, at first, if we have the name
+     with a "-", then if without. "-member" has priority */
+  for (i = 0; i < NIS_RES_OBJECT(res)->GR_data.gr_members.gr_members_len; ++i)
+    {
+      cp = NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_val[i];
+      if (cp[0] == '-')
+	{
+	  if (strcmp (&cp[1], principal) == 0)
+	    {
+	      nis_freeresult (res);
+	      return -1;
+	    }
+	  if (cp[1] == '@')
+	    switch (internal_ismember (principal, &cp[2]))
+	      {
+	      case -1:
+		nis_freeresult (res);
+		return -1;
+	      case 1:
+		nis_freeresult (res);
+		return 1;
+	      default:
+		break;
+	      }
+	  else
+	    if (cp[1] == '*')
+	      {
+		char buf1[strlen (principal) + 2];
+		char buf2[strlen (cp) + 2];
+
+		if (strcmp (nis_domain_of_r (principal, buf1, sizeof buf1),
+			    nis_domain_of_r (cp, buf2, sizeof buf2)) == 0)
+		  {
+		    nis_freeresult (res);
+		    return -1;
+		  }
+	      }
+	}
+    }
+
+  for (i = 0; i < NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_len; ++i)
+    {
+      cp = NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_val[i];
+      if (cp[0] != '-')
+	{
+	  if (strcmp (cp, principal) == 0)
+	    {
+	      nis_freeresult (res);
+	      return 1;
+	    }
+	  if (cp[0] == '@')
+	    switch (internal_ismember (principal, &cp[1]))
+	      {
+	      case -1:
+		nis_freeresult (res);
+		return -1;
+	      case 1:
+		nis_freeresult (res);
+		return 1;
+	      default:
+		break;
+	      }
+	  else
+	    if (cp[0] == '*')
+	      {
+		char buf1[strlen (principal) + 2];
+		char buf2[strlen (cp) + 2];
+
+		if (strcmp (nis_domain_of_r (principal, buf1, sizeof buf1),
+			    nis_domain_of_r (cp, buf2, sizeof buf2)) == 0)
+		  {
+		    nis_freeresult (res);
+		    return 1;
+		  }
+	      }
+	}
+    }
+  nis_freeresult (res);
+  return 0;
+}
+
+bool_t
+nis_ismember (const_nis_name principal, const_nis_name group)
+{
+  if (group != NULL && group[0] != '\0' && principal != NULL)
+    return internal_ismember (principal, group) == 1 ? TRUE : FALSE;
+  else
+    return FALSE;
+}
+libnsl_hidden_nolink_def (nis_ismember, GLIBC_2_1)
diff --git a/REORG.TODO/nis/nis_local_names.c b/REORG.TODO/nis/nis_local_names.c
new file mode 100644
index 0000000000..99d8f99e27
--- /dev/null
+++ b/REORG.TODO/nis/nis_local_names.c
@@ -0,0 +1,178 @@
+/* Copyright (c) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <libintl.h>
+#include <rpcsvc/nis.h>
+#include <shlib-compat.h>
+
+nis_name
+nis_local_group (void)
+{
+  static char __nisgroup[NIS_MAXNAMELEN + 1];
+
+  char *cptr;
+  if (__nisgroup[0] == '\0'
+      && (cptr = getenv ("NIS_GROUP")) != NULL
+      && strlen (cptr) < NIS_MAXNAMELEN)
+    {
+      char *cp = stpcpy (__nisgroup, cptr);
+
+      if (cp[-1] != '.')
+	{
+	  cptr = nis_local_directory ();
+	  if ((cp - __nisgroup) + strlen (cptr) + 1 < NIS_MAXNAMELEN)
+	    {
+	      *cp++ = '.';
+	      strcpy (cp, cptr);
+	    }
+	  else
+	    __nisgroup[0] = '\0';
+	}
+    }
+
+  return __nisgroup;
+}
+libnsl_hidden_nolink_def (nis_local_group, GLIBC_2_1)
+
+nis_name
+nis_local_directory (void)
+{
+  static char __nisdomainname[NIS_MAXNAMELEN + 1];
+
+  if (__nisdomainname[0] == '\0')
+    {
+      if (getdomainname (__nisdomainname, NIS_MAXNAMELEN) < 0)
+	__nisdomainname[0] = '\0';
+      else
+	{
+	  char *cp = rawmemchr (__nisdomainname, '\0');
+
+	  /* Missing trailing dot? */
+	  if (cp[-1] != '.')
+	    {
+	      *cp++ = '.';
+	      *cp = '\0';
+	    }
+	}
+    }
+
+  return __nisdomainname;
+}
+libnsl_hidden_nolink_def (nis_local_directory, GLIBC_2_1)
+
+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)
+	{
+	  int len = snprintf (buf, NIS_MAXNAMELEN - 1,
+			      "[auth_name=%d,auth_type=LOCAL],cred.org_dir.%s",
+			      uid, nis_local_directory ());
+
+	  if (len >= NIS_MAXNAMELEN - 1)
+	    nobody:
+	    /* XXX The buffer is too small.  Can this happen???  */
+	    return strcpy (__principal, "nobody");
+
+	  if (buf[len - 1] != '.')
+	    {
+	      buf[len++] = '.';
+	      buf[len] = '\0';
+	    }
+
+	  res = nis_list (buf, USE_DGRAM + NO_AUTHINFO + FOLLOW_LINKS +
+			  FOLLOW_PATH, NULL, NULL);
+
+	  if (res == NULL)
+	    goto nobody;
+
+	  if (NIS_RES_STATUS (res) == 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);
+	      goto nobody;
+	    }
+	}
+      else
+	return strcpy (__principal, nis_local_host ());
+
+      /* Should be never reached */
+      goto nobody;
+    }
+  return __principal;
+}
+libnsl_hidden_nolink_def (nis_local_principal, GLIBC_2_1)
+
+nis_name
+nis_local_host (void)
+{
+  static char __nishostname[NIS_MAXNAMELEN + 1];
+
+  if (__nishostname[0] == '\0')
+    {
+      if (gethostname (__nishostname, NIS_MAXNAMELEN) < 0)
+	__nishostname[0] = '\0';
+      else
+	{
+	  char *cp = rawmemchr (__nishostname, '\0');
+	  int len = cp - __nishostname;
+
+	  /* Hostname already fully qualified? */
+	  if (cp[-1] == '.')
+	    return __nishostname;
+
+	  if (len + strlen (nis_local_directory ()) + 1 > NIS_MAXNAMELEN)
+	    {
+	      __nishostname[0] = '\0';
+	      return __nishostname;
+	    }
+
+	  *cp++ = '.';
+	  strncpy (cp, nis_local_directory (), NIS_MAXNAMELEN - len -1);
+	  __nishostname[NIS_MAXNAMELEN] = '\0';
+	}
+    }
+
+  return __nishostname;
+}
+libnsl_hidden_nolink_def (nis_local_host, GLIBC_2_1)
diff --git a/REORG.TODO/nis/nis_lookup.c b/REORG.TODO/nis/nis_lookup.c
new file mode 100644
index 0000000000..f6d84abecd
--- /dev/null
+++ b/REORG.TODO/nis/nis_lookup.c
@@ -0,0 +1,219 @@
+/* Copyright (C) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <string.h>
+#include <rpcsvc/nis.h>
+#include "nis_xdr.h"
+#include "nis_intern.h"
+#include <libnsl.h>
+#include <shlib-compat.h>
+
+
+nis_result *
+nis_lookup (const_nis_name name, const unsigned int flags)
+{
+  nis_result *res = calloc (1, sizeof (nis_result));
+  struct ns_request req;
+  nis_name *names;
+  nis_error status;
+  int link_first_try = 0;
+  int count_links = 0;	 /* We will follow only 16 links in the deep */
+  int done = 0;
+  int name_nr = 0;
+  nis_name namebuf[2] = {NULL, NULL};
+
+  if (res == NULL)
+    return NULL;
+
+  if ((flags & EXPAND_NAME) && (name[strlen (name) - 1] != '.'))
+    {
+      names = nis_getnames (name);
+      if (names == NULL)
+	{
+	  NIS_RES_STATUS (res) = NIS_NAMEUNREACHABLE;
+	  return res;
+	}
+    }
+  else
+    {
+      names = namebuf;
+      names[0] = (nis_name)name;
+    }
+
+  req.ns_name = names[0];
+  while (!done)
+    {
+      dir_binding bptr;
+      directory_obj *dir = NULL;
+      req.ns_object.ns_object_len = 0;
+      req.ns_object.ns_object_val = NULL;
+
+      status = __prepare_niscall (req.ns_name, &dir, &bptr, flags);
+      if (__glibc_unlikely (status != NIS_SUCCESS))
+	{
+	  NIS_RES_STATUS (res) = status;
+	  goto out;
+	}
+
+      do
+	{
+	  static const struct timeval RPCTIMEOUT = {10, 0};
+	  enum clnt_stat result;
+
+	again:
+	  result = clnt_call (bptr.clnt, NIS_LOOKUP,
+			      (xdrproc_t) _xdr_ns_request,
+			      (caddr_t) &req, (xdrproc_t) _xdr_nis_result,
+			      (caddr_t) res, RPCTIMEOUT);
+
+	  if (result != RPC_SUCCESS)
+	    status = NIS_RPCERROR;
+	  else
+	    {
+	      status = NIS_SUCCESS;
+
+	      if (NIS_RES_STATUS (res) == NIS_SUCCESS)
+		{
+		    if (__type_of (NIS_RES_OBJECT (res)) == NIS_LINK_OBJ
+			&& (flags & FOLLOW_LINKS)) /* We are following links */
+		      {
+			/* if we hit the link limit, bail */
+			if (count_links > NIS_MAXLINKS)
+			  {
+			    NIS_RES_STATUS (res) = NIS_LINKNAMEERROR;
+			    break;
+			  }
+			++count_links;
+			req.ns_name =
+			  strdupa (NIS_RES_OBJECT (res)->LI_data.li_name);
+
+			/* The following is a non-obvious optimization.  A
+			   nis_freeresult call would call xdr_free as the
+			   following code.  But it also would unnecessarily
+			   free the result structure.  We avoid this here
+			   along with the necessary tests.  */
+			xdr_free ((xdrproc_t) _xdr_nis_result, (char *) res);
+			memset (res, '\0', sizeof (*res));
+
+			link_first_try = 1; /* Try at first the old binding */
+			goto again;
+		      }
+		}
+	      else
+		if (NIS_RES_STATUS (res) == NIS_SYSTEMERROR
+		    || NIS_RES_STATUS (res) == NIS_NOSUCHNAME
+		    || NIS_RES_STATUS (res) == NIS_NOT_ME)
+		  {
+		    if (link_first_try)
+		      {
+			__nisbind_destroy (&bptr);
+			nis_free_directory (dir);
+			/* Otherwise __nisfind_server will not do anything.  */
+			dir = NULL;
+
+			if (__nisfind_server (req.ns_name, 1, &dir, &bptr,
+					      flags & ~MASTER_ONLY)
+			    != NIS_SUCCESS)
+			  goto out;
+		      }
+		    else
+		      if (__nisbind_next (&bptr) != NIS_SUCCESS)
+			{
+			  /* No more servers to search.  Try parent.  */
+			  const char *ndomain = __nis_domain_of (req.ns_name);
+			  req.ns_name = strdupa (ndomain);
+			  if (strcmp (req.ns_name, ".") == 0)
+			    {
+			      NIS_RES_STATUS (res) = NIS_NAMEUNREACHABLE;
+			      goto out;
+			    }
+
+			  __nisbind_destroy (&bptr);
+			  nis_free_directory (dir);
+			  dir = NULL;
+			  status = __prepare_niscall (req.ns_name, &dir,
+						      &bptr, flags);
+			  if (__glibc_unlikely (status != NIS_SUCCESS))
+			    {
+			      NIS_RES_STATUS (res) = status;
+			      goto out;
+			    }
+			  goto again;
+			}
+
+		    while (__nisbind_connect (&bptr) != NIS_SUCCESS)
+		      {
+			if (__nisbind_next (&bptr) != NIS_SUCCESS)
+			  {
+			    nis_free_directory (dir);
+			    goto out;
+			  }
+		      }
+		    goto again;
+		  }
+	      break;
+	    }
+	  link_first_try = 0; /* Set it back */
+	}
+      while ((flags & HARD_LOOKUP) && status == NIS_RPCERROR);
+
+      __nisbind_destroy (&bptr);
+      nis_free_directory (dir);
+
+      if (status != NIS_SUCCESS)
+	{
+	  NIS_RES_STATUS (res) = status;
+	  goto out;
+	}
+
+      switch (NIS_RES_STATUS (res))
+	{
+	case NIS_PARTIAL:
+	case NIS_SUCCESS:
+	case NIS_S_SUCCESS:
+	case NIS_LINKNAMEERROR: /* We follow to max links */
+	case NIS_UNAVAIL: /* NIS+ is not installed, or all servers are down */
+	  ++done;
+	  break;
+	default:
+	  /* Try the next domainname if we don't follow a link */
+	  if (count_links)
+	    {
+	      free (req.ns_name);
+	      NIS_RES_STATUS (res) = NIS_LINKNAMEERROR;
+	      ++done;
+	      break;
+	    }
+	  ++name_nr;
+	  if (names[name_nr] == NULL)
+	    {
+	      ++done;
+	      break;
+	    }
+	  req.ns_name = names[name_nr];
+	  break;
+	}
+    }
+
+ out:
+  if (names != namebuf)
+    nis_freenames (names);
+
+  return res;
+}
+libnsl_hidden_nolink_def (nis_lookup, GLIBC_2_1)
diff --git a/REORG.TODO/nis/nis_mkdir.c b/REORG.TODO/nis/nis_mkdir.c
new file mode 100644
index 0000000000..da6690cdcb
--- /dev/null
+++ b/REORG.TODO/nis/nis_mkdir.c
@@ -0,0 +1,44 @@
+/* Copyright (c) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <rpcsvc/nis.h>
+#include <shlib-compat.h>
+
+#include "nis_xdr.h"
+#include "nis_intern.h"
+
+nis_error
+nis_mkdir (const_nis_name dir, const nis_server *server)
+{
+  nis_error res, res2;
+
+  if (server == NULL)
+    res2 = __do_niscall (dir, NIS_MKDIR, (xdrproc_t) _xdr_nis_name,
+			 (caddr_t) &dir, (xdrproc_t) _xdr_nis_error,
+			 (caddr_t) &res, 0, NULL);
+  else
+    res2 = __do_niscall2 (server, 1, NIS_MKDIR,
+			  (xdrproc_t) _xdr_nis_name,
+			  (caddr_t) &dir, (xdrproc_t) _xdr_nis_error,
+			  (caddr_t) &res, 0, NULL);
+  if (res2 != NIS_SUCCESS)
+    return res2;
+
+  return res;
+}
+libnsl_hidden_nolink_def (nis_mkdir, GLIBC_2_1)
diff --git a/REORG.TODO/nis/nis_modify.c b/REORG.TODO/nis/nis_modify.c
new file mode 100644
index 0000000000..67315165bc
--- /dev/null
+++ b/REORG.TODO/nis/nis_modify.c
@@ -0,0 +1,75 @@
+/* Copyright (C) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <string.h>
+#include <rpcsvc/nis.h>
+#include <shlib-compat.h>
+
+#include "nis_xdr.h"
+#include "nis_intern.h"
+
+nis_result *
+nis_modify (const_nis_name name, const nis_object *obj2)
+{
+  nis_object obj;
+  nis_result *res;
+  nis_error status;
+  struct ns_request req;
+  size_t namelen = strlen (name);
+  char buf1[namelen + 20];
+  char buf4[namelen + 20];
+
+  res = calloc (1, sizeof (nis_result));
+  if (res == NULL)
+    return NULL;
+
+  req.ns_name = (char *) name;
+
+  memcpy (&obj, obj2, sizeof (nis_object));
+
+  if (obj.zo_name == NULL || obj.zo_name[0] == '\0')
+    obj.zo_name = nis_leaf_of_r (name, buf1, sizeof (buf1));
+
+  if (obj.zo_owner == NULL || obj.zo_owner[0] == '\0')
+    obj.zo_owner = nis_local_principal ();
+
+  if (obj.zo_group == NULL || obj.zo_group[0] == '\0')
+    obj.zo_group = nis_local_group ();
+
+  obj.zo_domain = nis_domain_of_r (name, buf4, sizeof (buf4));
+
+  req.ns_object.ns_object_val = nis_clone_object (&obj, NULL);
+  if (req.ns_object.ns_object_val == NULL)
+    {
+      NIS_RES_STATUS (res) = NIS_NOMEMORY;
+      return res;
+    }
+  req.ns_object.ns_object_len = 1;
+
+  status = __do_niscall (name, NIS_MODIFY, (xdrproc_t) _xdr_ns_request,
+			 (caddr_t) & req, (xdrproc_t) _xdr_nis_result,
+			 (caddr_t) res, MASTER_ONLY,
+			 NULL);
+  if (status != NIS_SUCCESS)
+    NIS_RES_STATUS (res) = status;
+
+  nis_destroy_object (req.ns_object.ns_object_val);
+
+  return res;
+}
+libnsl_hidden_nolink_def (nis_modify, GLIBC_2_1)
diff --git a/REORG.TODO/nis/nis_ping.c b/REORG.TODO/nis/nis_ping.c
new file mode 100644
index 0000000000..b744898ba2
--- /dev/null
+++ b/REORG.TODO/nis/nis_ping.c
@@ -0,0 +1,71 @@
+/* Copyright (c) 1997-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <rpcsvc/nis.h>
+#include <shlib-compat.h>
+
+#include "nis_xdr.h"
+#include "nis_intern.h"
+
+void
+nis_ping (const_nis_name dirname, unsigned int utime,
+	  const nis_object *dirobj)
+{
+  nis_result *res = NULL;
+  nis_object *obj;
+  ping_args args;
+  unsigned int i;
+
+  if (dirname == NULL && dirobj == NULL)
+    abort ();
+
+  if (dirobj == NULL)
+    {
+      res = nis_lookup (dirname, MASTER_ONLY);
+      if (res == NULL || NIS_RES_STATUS (res) != NIS_SUCCESS)
+	{
+	  nis_freeresult (res);
+	  return;
+	}
+      obj = res->objects.objects_val;
+    }
+  else
+    obj = (nis_object *) dirobj;
+
+  /* Check if obj is really a diryectory object */
+  if (__type_of (obj) != NIS_DIRECTORY_OBJ)
+    {
+      nis_freeresult (res);
+      return;
+    }
+
+  if (dirname == NULL)
+    args.dir = obj->DI_data.do_name;
+  else
+    args.dir = (char *) dirname;
+  args.stamp = utime;
+
+  /* Send the ping only to replicas */
+  for (i = 1; i < obj->DI_data.do_servers.do_servers_len; ++i)
+    __do_niscall2 (&obj->DI_data.do_servers.do_servers_val[i], 1,
+		   NIS_PING, (xdrproc_t) _xdr_ping_args,
+		   (caddr_t) &args, (xdrproc_t) xdr_void,
+		   (caddr_t) NULL, 0, NULL);
+  nis_freeresult (res);
+}
+libnsl_hidden_nolink_def (nis_ping, GLIBC_2_1)
diff --git a/REORG.TODO/nis/nis_print.c b/REORG.TODO/nis/nis_print.c
new file mode 100644
index 0000000000..869f6aad61
--- /dev/null
+++ b/REORG.TODO/nis/nis_print.c
@@ -0,0 +1,382 @@
+/* Copyright (c) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <time.h>
+#include <string.h>
+#include <libintl.h>
+#include <stdint.h>
+
+#include <rpcsvc/nis.h>
+#include <shlib-compat.h>
+
+static const char *
+nis_nstype2str (const nstype type)
+{
+
+/* Name service names mustn't be translated, only UNKNOWN needs it */
+
+  switch (type)
+    {
+    case NIS:
+      return "NIS";
+    case SUNYP:
+      return "SUNYP";
+    case IVY:
+      return "IVY";
+    case DNS:
+      return "DNS";
+    case X500:
+      return "X500";
+    case DNANS:
+      return "DNANS";
+    case XCHS:
+      return "XCHS";
+    case CDS:
+      return "CDS";
+    default:
+      return N_("UNKNOWN");
+    }
+}
+
+static void
+print_ttl (const uint32_t ttl)
+{
+  uint32_t time, s, m, h;
+
+  time = ttl;
+
+  h = time / (60 * 60);
+  time %= (60 * 60);
+  m = time / 60;
+  time %= 60;
+  s = time;
+  printf ("%u:%u:%u\n", h, m, s);
+}
+
+static void
+print_flags (const unsigned int flags)
+{
+  fputs ("(", stdout);
+
+  if (flags & TA_SEARCHABLE)
+    fputs ("SEARCHABLE, ", stdout);
+
+  if (flags & TA_BINARY)
+    {
+      fputs ("BINARY DATA", stdout);
+      if (flags & TA_XDR)
+	fputs (", XDR ENCODED", stdout);
+      if (flags & TA_ASN1)
+	fputs (", ASN.1 ENCODED", stdout);
+      if (flags & TA_CRYPT)
+	fputs (", ENCRYPTED", stdout);
+    }
+  else
+    {
+      fputs ("TEXTUAL DATA", stdout);
+      if (flags & TA_SEARCHABLE)
+	{
+	  if (flags & TA_CASE)
+	    fputs (", CASE INSENSITIVE", stdout);
+	  else
+	    fputs (", CASE SENSITIVE", stdout);
+	}
+    }
+
+  fputs (")\n", stdout);
+}
+
+static void
+nis_print_objtype (enum zotypes type)
+{
+  switch (type)
+    {
+    case NIS_BOGUS_OBJ:
+      fputs (_("BOGUS OBJECT\n"), stdout);
+      break;
+    case NIS_NO_OBJ:
+      fputs (_("NO OBJECT\n"), stdout);
+      break;
+    case NIS_DIRECTORY_OBJ:
+      fputs (_("DIRECTORY\n"), stdout);
+      break;
+    case NIS_GROUP_OBJ:
+      fputs (_("GROUP\n"), stdout);
+      break;
+    case NIS_TABLE_OBJ:
+      fputs (_("TABLE\n"), stdout);
+      break;
+    case NIS_ENTRY_OBJ:
+      fputs (_("ENTRY\n"), stdout);
+      break;
+    case NIS_LINK_OBJ:
+      fputs (_("LINK\n"), stdout);
+      break;
+    case NIS_PRIVATE_OBJ:
+      fputs (_("PRIVATE\n"), stdout);
+      break;
+    default:
+      fputs (_("(Unknown object)\n"), stdout);
+      break;
+    }
+}
+
+void
+nis_print_rights (const unsigned int access)
+{
+  char result[17];
+  unsigned int 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;
+    }
+  fputs (result, stdout);
+}
+libnsl_hidden_nolink_def (nis_print_rights, GLIBC_2_1)
+
+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"), 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:
+	  printf (_("Diffie-Hellmann (%d bits)\n"),
+		  (sptr->pkey.n_len - 1) * 4);
+	  /* sptr->pkey.n_len counts the last 0, too */
+	  break;
+	case NIS_PK_RSA:
+	  printf (_("RSA (%d bits)\n"), (sptr->pkey.n_len - 1) * 4);
+	  break;
+	case NIS_PK_KERB:
+	  fputs (_("Kerberos.\n"), stdout);
+	  break;
+	default:
+	  printf (_("Unknown (type = %d, bits = %d)\n"), sptr->key_type,
+		  (sptr->pkey.n_len - 1) * 4);
+	  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 && ptr->proto[0] != '\0')
+		printf ("%s, ", ptr->proto);
+	      else
+		printf ("-, ");
+	      if (ptr->family != NULL && ptr->family[0] != '\0')
+		printf ("%s, ", ptr->family);
+	      else
+		printf ("-, ");
+	      if (ptr->uaddr != NULL && ptr->uaddr[0] != '\0')
+		printf ("%s\n", ptr->uaddr);
+	      else
+		fputs ("-\n", stdout);
+	      ptr++;
+	    }
+	}
+      sptr++;
+    }
+
+  fputs (_("Time to live : "), stdout);
+  print_ttl (dir->do_ttl);
+  fputs (_("Default Access rights :\n"), stdout);
+  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++)
+	{
+	  nis_print_rights (ptr->oa_rights);
+	  printf (_("\tType         : %s\n"), nis_nstype2str (ptr->oa_otype));
+	  fputs (_("\tAccess rights: "), stdout);
+	  nis_print_rights (ptr->oa_rights);
+	  fputs ("\n", stdout);
+	  ptr++;
+	}
+    }
+}
+libnsl_hidden_nolink_def (nis_print_directory, GLIBC_2_1)
+
+void
+nis_print_group (const group_obj *obj)
+{
+  unsigned int i;
+
+  fputs (_("Group Flags :"), stdout);
+  if (obj->gr_flags)
+    printf ("0x%08X", 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]);
+}
+libnsl_hidden_nolink_def (nis_print_group, GLIBC_2_1)
+
+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);
+      fputs (_("\t\tAttributes    : "), stdout);
+      print_flags (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);
+    }
+}
+libnsl_hidden_nolink_def (nis_print_table, GLIBC_2_1)
+
+void
+nis_print_link (const link_obj *obj)
+{
+  fputs (_("Linked Object Type : "), stdout);
+  nis_print_objtype (obj->li_rtype);
+  printf (_("Linked to : %s\n"), obj->li_name);
+  /* XXX Print the attributes here, if they exists */
+}
+libnsl_hidden_nolink_def (nis_print_link, GLIBC_2_1)
+
+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 if (obj->en_cols.en_cols_val[i].ec_value.ec_value_len == 0)
+	fputs ("'(nil)'\n", stdout);
+      else
+	printf ("'%.*s'\n",
+		(int)obj->en_cols.en_cols_val[i].ec_value.ec_value_len,
+		obj->en_cols.en_cols_val[i].ec_value.ec_value_val);
+    }
+}
+libnsl_hidden_nolink_def (nis_print_entry, GLIBC_2_1)
+
+void
+nis_print_object (const nis_object * obj)
+{
+  time_t buf;
+
+  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  : "));
+  print_ttl (obj->zo_ttl);
+  buf = obj->zo_oid.ctime;
+  printf (_("Creation Time : %s"), ctime (&buf));
+  buf = obj->zo_oid.mtime;
+  printf (_("Mod. Time     : %s"), ctime (&buf));
+  fputs (_("Object Type   : "), stdout);
+  nis_print_objtype (obj->zo_data.zo_type);
+  switch (obj->zo_data.zo_type)
+    {
+    case NIS_DIRECTORY_OBJ:
+      nis_print_directory (&obj->zo_data.objdata_u.di_data);
+      break;
+    case NIS_GROUP_OBJ:
+      nis_print_group (&obj->zo_data.objdata_u.gr_data);
+      break;
+    case NIS_TABLE_OBJ:
+      nis_print_table (&obj->zo_data.objdata_u.ta_data);
+      break;
+    case NIS_ENTRY_OBJ:
+      nis_print_entry (&obj->zo_data.objdata_u.en_data);
+      break;
+    case NIS_LINK_OBJ:
+      nis_print_link (&obj->zo_data.objdata_u.li_data);
+      break;
+    case NIS_PRIVATE_OBJ:
+      printf (_("    Data Length = %u\n"),
+	      obj->zo_data.objdata_u.po_data.po_data_len);
+      break;
+    default:
+      break;
+    }
+}
+libnsl_hidden_nolink_def (nis_print_object, GLIBC_2_1)
+
+void
+nis_print_result (const nis_result *res)
+{
+  unsigned int i;
+
+  printf (_("Status            : %s\n"), nis_sperrno (NIS_RES_STATUS (res)));
+  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]);
+    }
+}
+libnsl_hidden_nolink_def (nis_print_result, GLIBC_2_1)
diff --git a/REORG.TODO/nis/nis_print_group_entry.c b/REORG.TODO/nis/nis_print_group_entry.c
new file mode 100644
index 0000000000..3a717e71d7
--- /dev/null
+++ b/REORG.TODO/nis/nis_print_group_entry.c
@@ -0,0 +1,175 @@
+/* Copyright (c) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <alloca.h>
+#include <string.h>
+#include <libintl.h>
+#include <rpcsvc/nis.h>
+#include <shlib-compat.h>
+
+void
+nis_print_group_entry (const_nis_name group)
+{
+  if (group != NULL && group[0] != '\0')
+    {
+      size_t grouplen = strlen (group);
+      char buf[grouplen + 50];
+      char leafbuf[grouplen + 3];
+      char domainbuf[grouplen + 3];
+      nis_result *res;
+      char *cp, *cp2;
+      u_int i;
+
+      cp = stpcpy (buf, nis_leaf_of_r (group, leafbuf, sizeof (leafbuf) - 1));
+      cp = stpcpy (cp, ".groups_dir");
+      cp2 = nis_domain_of_r (group, domainbuf, sizeof (domainbuf) - 1);
+      if (cp2 != NULL && cp2[0] != '\0')
+	{
+	  *cp++ = '.';
+	  stpcpy (cp, cp2);
+	}
+      res = nis_lookup (buf, FOLLOW_LINKS | EXPAND_NAME);
+
+      if (res == NULL)
+	return;
+
+      if (NIS_RES_STATUS (res) != NIS_SUCCESS
+	  || NIS_RES_NUMOBJ (res) != 1
+	  || __type_of (NIS_RES_OBJECT (res)) != NIS_GROUP_OBJ)
+	{
+	  nis_freeresult (res);
+	  return;
+	}
+
+      char *mem_exp[NIS_RES_NUMOBJ (res)];
+      char *mem_imp[NIS_RES_NUMOBJ (res)];
+      char *mem_rec[NIS_RES_NUMOBJ (res)];
+      char *nomem_exp[NIS_RES_NUMOBJ (res)];
+      char *nomem_imp[NIS_RES_NUMOBJ (res)];
+      char *nomem_rec[NIS_RES_NUMOBJ (res)];
+      unsigned long mem_exp_cnt = 0, mem_imp_cnt = 0, mem_rec_cnt = 0;
+      unsigned long nomem_exp_cnt = 0, nomem_imp_cnt = 0, nomem_rec_cnt = 0;
+
+      for (i = 0;
+	   i < NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_len; ++i)
+	{
+	  char *grmem =
+	    NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_val[i];
+	  int neg = grmem[0] == '-';
+
+	  switch (grmem[neg])
+	    {
+	    case '*':
+	      if (neg)
+		{
+		  nomem_imp[nomem_imp_cnt] = grmem;
+		  ++nomem_imp_cnt;
+		}
+	      else
+		{
+		  mem_imp[mem_imp_cnt] = grmem;
+		  ++mem_imp_cnt;
+		}
+	      break;
+	    case '@':
+	      if (neg)
+		{
+		  nomem_rec[nomem_rec_cnt] = grmem;
+		  ++nomem_rec_cnt;
+		}
+	      else
+		{
+		  mem_rec[mem_rec_cnt] = grmem;
+		  ++mem_rec_cnt;
+		}
+	      break;
+	    default:
+	      if (neg)
+		{
+		  nomem_exp[nomem_exp_cnt] = grmem;
+		  ++nomem_exp_cnt;
+		}
+	      else
+		{
+		  mem_exp[mem_exp_cnt] = grmem;
+		  ++mem_exp_cnt;
+		}
+	      break;
+	    }
+	}
+      {
+	char buf[strlen (NIS_RES_OBJECT (res)->zo_domain) + 10];
+	printf (_("Group entry for \"%s.%s\" group:\n"),
+		NIS_RES_OBJECT (res)->zo_name,
+		nis_domain_of_r (NIS_RES_OBJECT (res)->zo_domain,
+				 buf, strlen (NIS_RES_OBJECT (res)->zo_domain)
+				 + 10));
+      }
+      if (mem_exp_cnt)
+	{
+	  fputs (_("    Explicit members:\n"), stdout);
+	  for (i = 0; i < mem_exp_cnt; ++i)
+	    printf ("\t%s\n", mem_exp[i]);
+	}
+      else
+	fputs (_("    No explicit members\n"), stdout);
+      if (mem_imp_cnt)
+	{
+	  fputs (_("    Implicit members:\n"), stdout);
+	  for (i = 0; i < mem_imp_cnt; ++i)
+	    printf ("\t%s\n", &mem_imp[i][2]);
+	}
+      else
+	fputs (_("    No implicit members\n"), stdout);
+      if (mem_rec_cnt)
+	{
+	  fputs (_("    Recursive members:\n"), stdout);
+	  for (i = 0; i < mem_rec_cnt; ++i)
+	    printf ("\t%s\n", &mem_rec[i][1]);
+	}
+      else
+        fputs (_("    No recursive members\n"), stdout);
+      if (nomem_exp_cnt)
+	{
+	  fputs (_("    Explicit nonmembers:\n"), stdout);
+	  for (i = 0; i < nomem_exp_cnt; ++i)
+	    printf ("\t%s\n", &nomem_exp[i][1]);
+	}
+      else
+	fputs (_("    No explicit nonmembers\n"), stdout);
+      if (nomem_imp_cnt)
+	{
+	  fputs (_("    Implicit nonmembers:\n"), stdout);
+	  for (i = 0; i < nomem_imp_cnt; ++i)
+	    printf ("\t%s\n", &nomem_imp[i][3]);
+	}
+      else
+	fputs (_("    No implicit nonmembers\n"), stdout);
+      if (nomem_rec_cnt)
+	{
+	  fputs (_("    Recursive nonmembers:\n"), stdout);
+	  for (i = 0; i < nomem_rec_cnt; ++i)
+	    printf ("\t%s=n", &nomem_rec[i][2]);
+	}
+      else
+        fputs (_("    No recursive nonmembers\n"), stdout);
+
+      nis_freeresult (res);
+    }
+}
+libnsl_hidden_nolink_def (nis_print_group_entry, GLIBC_2_1)
diff --git a/REORG.TODO/nis/nis_remove.c b/REORG.TODO/nis/nis_remove.c
new file mode 100644
index 0000000000..87c539793d
--- /dev/null
+++ b/REORG.TODO/nis/nis_remove.c
@@ -0,0 +1,59 @@
+/* Copyright (C) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <rpcsvc/nis.h>
+#include <shlib-compat.h>
+
+#include "nis_xdr.h"
+#include "nis_intern.h"
+
+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));
+  if (res == NULL)
+    return NULL;
+
+  req.ns_name = (char *)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 (name, NIS_REMOVE, (xdrproc_t) _xdr_ns_request,
+			      (caddr_t) &req, (xdrproc_t) _xdr_nis_result,
+			      (caddr_t) res, MASTER_ONLY,
+			      NULL)) != NIS_SUCCESS)
+    NIS_RES_STATUS (res) = status;
+
+  nis_destroy_object (req.ns_object.ns_object_val);
+
+  return res;
+}
+libnsl_hidden_nolink_def (nis_remove, GLIBC_2_1)
diff --git a/REORG.TODO/nis/nis_removemember.c b/REORG.TODO/nis/nis_removemember.c
new file mode 100644
index 0000000000..af9e2a899c
--- /dev/null
+++ b/REORG.TODO/nis/nis_removemember.c
@@ -0,0 +1,93 @@
+/* Copyright (c) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <assert.h>
+#include <string.h>
+#include <rpcsvc/nis.h>
+#include <shlib-compat.h>
+
+nis_error
+nis_removemember (const_nis_name member, const_nis_name group)
+{
+  if (group != NULL && group[0] != '\0')
+    {
+      size_t grouplen = strlen (group);
+      char buf[grouplen + 14 + NIS_MAXNAMELEN];
+      char domainbuf[grouplen + 2];
+      nis_result *res, *res2;
+      nis_error status;
+      char *cp, *cp2;
+
+      cp = rawmemchr (nis_leaf_of_r (group, buf, sizeof (buf) - 1), '\0');
+      cp = stpcpy (cp, ".groups_dir");
+      cp2 = nis_domain_of_r (group, domainbuf, sizeof (domainbuf) - 1);
+      if (cp2 != NULL && cp2[0] != '\0')
+        {
+          cp = stpcpy (cp, ".");
+          stpcpy (cp, cp2);
+        }
+      res = nis_lookup (buf, FOLLOW_LINKS | EXPAND_NAME);
+      if (res == NULL)
+	return NIS_NOMEMORY;
+      if (NIS_RES_STATUS (res) != NIS_SUCCESS)
+        {
+	  status = NIS_RES_STATUS (res);
+	  nis_freeresult (res);
+          return status;
+        }
+
+      if (NIS_RES_NUMOBJ (res) != 1
+	  || __type_of (NIS_RES_OBJECT (res)) != NIS_GROUP_OBJ)
+	{
+	  nis_freeresult (res);
+	  return NIS_INVALIDOBJ;
+	}
+
+      nis_name *gr_members_val
+	= NIS_RES_OBJECT(res)->GR_data.gr_members.gr_members_val;
+      u_int gr_members_len
+	= NIS_RES_OBJECT(res)->GR_data.gr_members.gr_members_len;
+
+      u_int j = 0;
+      for (u_int i = 0; i < gr_members_len; ++i)
+	if (strcmp (gr_members_val[i], member) != 0)
+	  gr_members_val[j++] = gr_members_val[i];
+	else
+	  free (gr_members_val[i]);
+
+      /* There is no need to reallocate the gr_members_val array.  We
+	 just adjust the size to match the number of strings still in
+	 it.  Yes, xdr_array will use mem_free with a size parameter
+	 but this is mapped to a simple free call which determines the
+	 size of the block by itself.  */
+      NIS_RES_OBJECT (res)->GR_data.gr_members.gr_members_len = j;
+
+      cp = stpcpy (buf, NIS_RES_OBJECT (res)->zo_name);
+      *cp++ = '.';
+      strncpy (cp, NIS_RES_OBJECT (res)->zo_domain, NIS_MAXNAMELEN);
+      res2 = nis_modify (buf, NIS_RES_OBJECT (res));
+      status = NIS_RES_STATUS (res2);
+      nis_freeresult (res);
+      nis_freeresult (res2);
+
+      return status;
+    }
+  else
+    return NIS_FAIL;
+}
+libnsl_hidden_nolink_def (nis_removemember, GLIBC_2_1)
diff --git a/REORG.TODO/nis/nis_rmdir.c b/REORG.TODO/nis/nis_rmdir.c
new file mode 100644
index 0000000000..53a0509e05
--- /dev/null
+++ b/REORG.TODO/nis/nis_rmdir.c
@@ -0,0 +1,42 @@
+/* Copyright (c) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <rpcsvc/nis.h>
+#include <shlib-compat.h>
+
+#include "nis_xdr.h"
+#include "nis_intern.h"
+
+nis_error
+nis_rmdir (const_nis_name dir, const nis_server *server)
+{
+  nis_error res, res2;
+
+  if (server == NULL)
+    return NIS_SYSTEMERROR;
+
+  res2 = __do_niscall2 (server, 1, NIS_RMDIR,
+			(xdrproc_t) _xdr_nis_name,
+			(caddr_t) &dir, (xdrproc_t) _xdr_nis_error,
+			(caddr_t) &res, 0, NULL);
+  if (res2 != NIS_SUCCESS)
+    return res2;
+
+  return res;
+}
+libnsl_hidden_nolink_def (nis_rmdir, GLIBC_2_1)
diff --git a/REORG.TODO/nis/nis_server.c b/REORG.TODO/nis/nis_server.c
new file mode 100644
index 0000000000..63857721f2
--- /dev/null
+++ b/REORG.TODO/nis/nis_server.c
@@ -0,0 +1,89 @@
+/* Copyright (c) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <string.h>
+#include <rpcsvc/nis.h>
+#include <shlib-compat.h>
+
+#include "nis_xdr.h"
+#include "nis_intern.h"
+
+nis_error
+nis_servstate (const nis_server *serv, const nis_tag *tags,
+	       const int numtags, nis_tag **result)
+{
+  nis_taglist taglist;
+  nis_taglist tagres;
+
+  *result = 0;
+  tagres.tags.tags_len = 0;
+  tagres.tags.tags_val = NULL;
+  taglist.tags.tags_len = numtags;
+  taglist.tags.tags_val = (nis_tag *) tags;
+
+  if (serv == NULL)
+    return NIS_BADOBJECT;
+
+  if (__do_niscall2 (serv, 1, NIS_SERVSTATE, (xdrproc_t) _xdr_nis_taglist,
+		     (caddr_t) &taglist, (xdrproc_t) _xdr_nis_taglist,
+		     (caddr_t) &tagres, 0, NULL) != NIS_SUCCESS)
+    return NIS_RPCERROR;
+
+  *result = tagres.tags.tags_val;
+
+  return NIS_SUCCESS;
+}
+libnsl_hidden_nolink_def (nis_servstate, GLIBC_2_1)
+
+nis_error
+nis_stats (const nis_server *serv, const nis_tag *tags,
+	   const int numtags, nis_tag **result)
+{
+  nis_taglist taglist;
+  nis_taglist tagres;
+
+  *result = NULL;
+  tagres.tags.tags_len = 0;
+  tagres.tags.tags_val = NULL;
+  taglist.tags.tags_len = numtags;
+  taglist.tags.tags_val = (nis_tag *) tags;
+
+  if (serv == NULL)
+    return NIS_BADOBJECT;
+
+  if (__do_niscall2 (serv, 1, NIS_STATUS, (xdrproc_t) _xdr_nis_taglist,
+		     (caddr_t) &taglist, (xdrproc_t) _xdr_nis_taglist,
+		     (caddr_t) &tagres, 0, NULL) != NIS_SUCCESS)
+    return NIS_RPCERROR;
+
+  *result = tagres.tags.tags_val;
+
+  return NIS_SUCCESS;
+}
+libnsl_hidden_nolink_def (nis_stats, GLIBC_2_1)
+
+void
+nis_freetags (nis_tag *tags, const int numtags)
+{
+  int i;
+
+  for (i = 0; i < numtags; ++i)
+    free (tags[i].tag_val);
+  free (tags);
+}
+libnsl_hidden_nolink_def (nis_freetags, GLIBC_2_1)
diff --git a/REORG.TODO/nis/nis_subr.c b/REORG.TODO/nis/nis_subr.c
new file mode 100644
index 0000000000..5d93e77330
--- /dev/null
+++ b/REORG.TODO/nis/nis_subr.c
@@ -0,0 +1,354 @@
+/* Copyright (c) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <string.h>
+#include <rpcsvc/nis.h>
+#include <shlib-compat.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);
+}
+libnsl_hidden_nolink_def (nis_leaf_of, GLIBC_2_1)
+
+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 (__glibc_unlikely (i >= buflen))
+    {
+      __set_errno (ERANGE);
+      return NULL;
+    }
+
+  *((char *) __mempcpy (buffer, name, i)) = '\0';
+
+  return buffer;
+}
+libnsl_hidden_nolink_def (nis_leaf_of_r, GLIBC_2_1)
+
+nis_name
+nis_name_of (const_nis_name name)
+{
+  static char result[NIS_MAXNAMELEN + 1];
+
+  return nis_name_of_r (name, result, NIS_MAXNAMELEN);
+}
+libnsl_hidden_nolink_def (nis_name_of, GLIBC_2_1)
+
+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)
+    {
+      __set_errno (ERANGE);
+      return NULL;
+    }
+
+  *((char *) __mempcpy (buffer, name, diff - 1)) = '\0';
+
+  if (diff - 1 == 0)
+    return NULL;
+
+  return buffer;
+}
+libnsl_hidden_nolink_def (nis_name_of_r, GLIBC_2_1)
+
+static int __always_inline
+count_dots (const_nis_name str)
+{
+  int count = 0;
+
+  for (size_t i = 0; str[i] != '\0'; ++i)
+    if (str[i] == '.')
+      ++count;
+
+  return count;
+}
+
+/* If we run out of memory, we don't give already allocated memory
+   free. The overhead for bringing getnames back in a safe state to
+   free it is to big. */
+nis_name *
+nis_getnames (const_nis_name name)
+{
+  const char *local_domain = nis_local_directory ();
+  size_t local_domain_len = strlen (local_domain);
+  size_t name_len = strlen (name);
+  char *path;
+  int pos = 0;
+  char *saveptr = NULL;
+  int have_point;
+  const char *cp;
+  const char *cp2;
+
+  int count = 2;
+  nis_name *getnames = malloc ((count + 1) * sizeof (char *));
+  if (__glibc_unlikely (getnames == NULL))
+      return NULL;
+
+  /* Do we have a fully qualified NIS+ name ? If yes, give it back */
+  if (name[name_len - 1] == '.')
+    {
+      if ((getnames[0] = strdup (name)) == NULL)
+	{
+	free_null:
+	  while (pos-- > 0)
+	    free (getnames[pos]);
+	  free (getnames);
+	  return NULL;
+	}
+
+      getnames[1] = NULL;
+
+      return getnames;
+    }
+
+  /* If the passed NAME is shared a suffix (the latter of course with
+     a final dot) with each other we pass back NAME with a final
+     dot.  */
+  if (local_domain_len > 2)
+    {
+      have_point = 0;
+      cp = &local_domain[local_domain_len - 2];
+      cp2 = &name[name_len - 1];
+
+      while (*cp == *cp2)
+	{
+	  if (*cp == '.')
+	    have_point = 1;
+	  --cp;
+	  --cp2;
+	  if (cp < local_domain)
+	    {
+	      have_point = cp2 < name || *cp2 == '.';
+	      break;
+	    }
+	  if (cp2 < name)
+	    {
+	      have_point = *cp == '.';
+	      break;
+	    }
+	}
+
+      if (have_point)
+	{
+	  getnames[0] = malloc (name_len + 2);
+	  if (getnames[0] == NULL)
+	    goto free_null;
+
+	  strcpy (stpcpy (getnames[0], name), ".");
+	  ++pos;
+	}
+    }
+
+  /* Get the search path, where we have to search "name" */
+  path = getenv ("NIS_PATH");
+  if (path == NULL)
+    path = strdupa ("$");
+  else
+    path = strdupa (path);
+
+  have_point = strchr (name, '.') != NULL;
+
+  cp = __strtok_r (path, ":", &saveptr);
+  while (cp)
+    {
+      if (strcmp (cp, "$") == 0)
+	{
+	  const char *cptr = local_domain;
+	  char *tmp;
+
+	  while (*cptr != '\0' && count_dots (cptr) >= 2)
+	    {
+	      if (pos >= count)
+		{
+		  count += 5;
+		  nis_name *newp = realloc (getnames,
+					    (count + 1) * sizeof (char *));
+		  if (__glibc_unlikely (newp == NULL))
+		    goto free_null;
+		  getnames = newp;
+		}
+	      tmp = malloc (strlen (cptr) + local_domain_len + name_len + 2);
+	      if (__glibc_unlikely (tmp == NULL))
+		goto free_null;
+
+	      getnames[pos] = tmp;
+	      tmp = stpcpy (tmp, name);
+	      *tmp++ = '.';
+	      if (cptr[1] != '\0')
+		stpcpy (tmp, cptr);
+	      else
+		++cptr;
+
+	      ++pos;
+
+	      while (*cptr != '.' && *cptr != '\0')
+		++cptr;
+	      if (cptr[0] != '\0' && cptr[1] != '\0')
+		/* If we have only ".", don't remove the "." */
+		++cptr;
+	    }
+	}
+      else
+	{
+	  char *tmp;
+	  size_t cplen = strlen (cp);
+
+	  if (cp[cplen - 1] == '$')
+	    {
+	      char *p;
+
+	      tmp = malloc (cplen + local_domain_len + name_len + 2);
+	      if (__glibc_unlikely (tmp == NULL))
+		goto free_null;
+
+	      p = __stpcpy (tmp, name);
+	      *p++ = '.';
+	      p = __mempcpy (p, cp, cplen);
+	      --p;
+	      if (p[-1] != '.')
+		*p++ = '.';
+	      __stpcpy (p, local_domain);
+	    }
+	  else
+	    {
+	      char *p;
+
+	      tmp = malloc (cplen + name_len + 3);
+	      if (__glibc_unlikely (tmp == NULL))
+		goto free_null;
+
+	      p = __mempcpy (tmp, name, name_len);
+	      *p++ = '.';
+	      p = __mempcpy (p, cp, cplen);
+	      if (p[-1] != '.')
+		*p++ = '.';
+	      *p = '\0';
+	    }
+
+	  if (pos >= count)
+	    {
+	      count += 5;
+	      nis_name *newp = realloc (getnames,
+					(count + 1) * sizeof (char *));
+	      if (__glibc_unlikely (newp == NULL))
+		goto free_null;
+	      getnames = newp;
+	    }
+	  getnames[pos] = tmp;
+	  ++pos;
+	}
+      cp = __strtok_r (NULL, ":", &saveptr);
+    }
+
+  if (pos == 0
+      && __asprintf (&getnames[pos++], "%s%s%s%s",
+		     name, name[name_len - 1] == '.' ? "" : ".",
+		     local_domain,
+		     local_domain[local_domain_len - 1] == '.' ? "" : ".") < 0)
+    goto free_null;
+
+  getnames[pos] = NULL;
+
+  return getnames;
+}
+libnsl_hidden_nolink_def (nis_getnames, GLIBC_2_1)
+
+void
+nis_freenames (nis_name *names)
+{
+  int i = 0;
+
+  while (names[i] != NULL)
+    {
+      free (names[i]);
+      ++i;
+    }
+
+  free (names);
+}
+libnsl_hidden_nolink_def  (nis_freenames, GLIBC_2_1)
+
+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;
+
+    }
+}
+libnsl_hidden_nolink_def (nis_dir_cmp, GLIBC_2_1)
+
+void
+nis_destroy_object (nis_object *obj)
+{
+  nis_free_object (obj);
+}
+libnsl_hidden_nolink_def (nis_destroy_object, GLIBC_2_1)
diff --git a/REORG.TODO/nis/nis_table.c b/REORG.TODO/nis/nis_table.c
new file mode 100644
index 0000000000..88eb6797e6
--- /dev/null
+++ b/REORG.TODO/nis/nis_table.c
@@ -0,0 +1,813 @@
+/* Copyright (c) 1997-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <assert.h>
+#include <string.h>
+#include <rpcsvc/nis.h>
+#include <libc-diag.h>
+#include <shlib-compat.h>
+
+#include "nis_xdr.h"
+#include "nis_intern.h"
+#include "libnsl.h"
+
+
+struct ib_request *
+__create_ib_request (const_nis_name name, unsigned int flags)
+{
+  struct ib_request *ibreq = calloc (1, sizeof (struct ib_request));
+  nis_attr *search_val = NULL;
+  size_t search_len = 0;
+  size_t size = 0;
+
+  if (ibreq == NULL)
+    return NULL;
+
+  ibreq->ibr_flags = flags;
+
+  char *cptr = strdupa (name);
+
+  /* Not of "[key=value,key=value,...],foo.." format? */
+  if (cptr[0] != '[')
+    {
+      ibreq->ibr_name = strdup (cptr);
+      if (ibreq->ibr_name == NULL)
+	{
+	  free (ibreq);
+	  return NULL;
+	}
+      return ibreq;
+    }
+
+  /* "[key=value,...],foo" format */
+  ibreq->ibr_name = strchr (cptr, ']');
+  if (ibreq->ibr_name == NULL || ibreq->ibr_name[1] != ',')
+    {
+      /* The object has not really been built yet so we use free.  */
+      free (ibreq);
+      return NULL;
+    }
+
+  /* Check if we have an entry of "[key=value,],bar".  If, remove the "," */
+  if (ibreq->ibr_name[-1] == ',')
+    ibreq->ibr_name[-1] = '\0';
+  else
+    ibreq->ibr_name[0] = '\0';
+  ibreq->ibr_name += 2;
+  ibreq->ibr_name = strdup (ibreq->ibr_name);
+  if (ibreq->ibr_name == NULL)
+    {
+    free_null:
+      while (search_len-- > 0)
+	{
+	  free (search_val[search_len].zattr_ndx);
+	  free (search_val[search_len].zattr_val.zattr_val_val);
+	}
+      free (search_val);
+      nis_free_request (ibreq);
+      return NULL;
+    }
+
+  ++cptr; /* Remove "[" */
+
+  while (cptr != NULL && cptr[0] != '\0')
+    {
+      char *key = cptr;
+      char *val = strchr (cptr, '=');
+
+      cptr = strchr (key, ',');
+      if (cptr != NULL)
+	*cptr++ = '\0';
+
+      if (__glibc_unlikely (val == NULL))
+	{
+	  nis_free_request (ibreq);
+	  return NULL;
+	}
+      *val++ = '\0';
+      if (search_len + 1 >= size)
+	{
+	  size += 1;
+	  nis_attr *newp = realloc (search_val, size * sizeof (nis_attr));
+	  if (newp == NULL)
+	    goto free_null;
+	  search_val = newp;
+	}
+      search_val[search_len].zattr_ndx = strdup (key);
+      if (search_val[search_len].zattr_ndx == NULL)
+	goto free_null;
+
+      search_val[search_len].zattr_val.zattr_val_len = strlen (val) + 1;
+      search_val[search_len].zattr_val.zattr_val_val = strdup (val);
+      if (search_val[search_len].zattr_val.zattr_val_val == NULL)
+	{
+	  free (search_val[search_len].zattr_ndx);
+	  goto free_null;
+	}
+
+      ++search_len;
+    }
+
+  ibreq->ibr_srch.ibr_srch_val = search_val;
+  ibreq->ibr_srch.ibr_srch_len = search_len;
+
+  return ibreq;
+}
+libnsl_hidden_nolink_def (__create_ib_request, GLIBC_PRIVATE)
+
+static const struct timeval RPCTIMEOUT = {10, 0};
+
+static char *
+get_tablepath (char *name, dir_binding *bptr)
+{
+  enum clnt_stat result;
+  nis_result res;
+  struct ns_request req;
+
+  memset (&res, '\0', sizeof (res));
+
+  req.ns_name = name;
+  req.ns_object.ns_object_len = 0;
+  req.ns_object.ns_object_val = NULL;
+
+  result = clnt_call (bptr->clnt, NIS_LOOKUP, (xdrproc_t) _xdr_ns_request,
+		      (caddr_t) &req, (xdrproc_t) _xdr_nis_result,
+		      (caddr_t) &res, RPCTIMEOUT);
+
+  const char *cptr;
+  if (result == RPC_SUCCESS && NIS_RES_STATUS (&res) == NIS_SUCCESS
+      && __type_of (NIS_RES_OBJECT (&res)) == NIS_TABLE_OBJ)
+    cptr = NIS_RES_OBJECT (&res)->TA_data.ta_path;
+  else
+    cptr = "";
+
+  char *str = strdup (cptr);
+
+  if (result == RPC_SUCCESS)
+    xdr_free ((xdrproc_t) _xdr_nis_result, (char *) &res);
+
+  return str;
+}
+
+
+nis_error
+__follow_path (char **tablepath, char **tableptr, struct ib_request *ibreq,
+	       dir_binding *bptr)
+{
+  if (*tablepath == NULL)
+    {
+      *tablepath = get_tablepath (ibreq->ibr_name, bptr);
+      if (*tablepath == NULL)
+	return NIS_NOMEMORY;
+
+      *tableptr = *tablepath;
+    }
+
+  /* Since tableptr is only set here, and it's set when tablepath is NULL,
+     which it is initially defined as, we know it will always be set here.  */
+  DIAG_PUSH_NEEDS_COMMENT;
+  DIAG_IGNORE_NEEDS_COMMENT (4.7, "-Wmaybe-uninitialized");
+
+  if (*tableptr == NULL)
+    return NIS_NOTFOUND;
+
+  char *newname = strsep (tableptr, ":");
+  if (newname[0] == '\0')
+    return NIS_NOTFOUND;
+
+  DIAG_POP_NEEDS_COMMENT;
+
+  newname = strdup (newname);
+  if (newname == NULL)
+    return NIS_NOMEMORY;
+
+  free (ibreq->ibr_name);
+  ibreq->ibr_name = newname;
+
+  return NIS_SUCCESS;
+}
+libnsl_hidden_nolink_def (__follow_path, GLIBC_PRIVATE)
+
+
+nis_result *
+nis_list (const_nis_name name, unsigned int flags,
+	  int (*callback) (const_nis_name name,
+			   const nis_object *object,
+			   const void *userdata),
+	  const void *userdata)
+{
+  nis_result *res = malloc (sizeof (nis_result));
+  ib_request *ibreq;
+  int status;
+  enum clnt_stat clnt_status;
+  int count_links = 0;		/* We will only follow NIS_MAXLINKS links! */
+  int done = 0;
+  nis_name *names;
+  nis_name namebuf[2] = {NULL, NULL};
+  int name_nr = 0;
+  nis_cb *cb = NULL;
+  char *tableptr;
+  char *tablepath = NULL;
+  int first_try = 0; /* Do we try the old binding at first ? */
+  nis_result *allres = NULL;
+
+  if (res == NULL)
+    return NULL;
+
+  if (name == NULL)
+    {
+      status = NIS_BADNAME;
+    err_out:
+      nis_freeresult (allres);
+      memset (res, '\0', sizeof (nis_result));
+      NIS_RES_STATUS (res) = status;
+      return res;
+    }
+
+  ibreq = __create_ib_request (name, flags);
+  if (ibreq == NULL)
+    {
+      status = NIS_BADNAME;
+      goto err_out;
+    }
+
+  if ((flags & EXPAND_NAME)
+      && ibreq->ibr_name[strlen (ibreq->ibr_name) - 1] != '.')
+    {
+      names = nis_getnames (ibreq->ibr_name);
+      free (ibreq->ibr_name);
+      ibreq->ibr_name = NULL;
+      if (names == NULL)
+	{
+	  nis_free_request (ibreq);
+	  status = NIS_BADNAME;
+	  goto err_out;
+	}
+      ibreq->ibr_name = strdup (names[name_nr]);
+      if (ibreq->ibr_name == NULL)
+	{
+	  nis_freenames (names);
+	  nis_free_request (ibreq);
+	  status = NIS_NOMEMORY;
+	  goto err_out;
+	}
+    }
+  else
+    {
+      names = namebuf;
+      names[name_nr] = ibreq->ibr_name;
+    }
+
+  cb = NULL;
+
+  while (!done)
+    {
+      dir_binding bptr;
+      directory_obj *dir = NULL;
+
+      memset (res, '\0', sizeof (nis_result));
+
+      status = __nisfind_server (ibreq->ibr_name,
+				 ibreq->ibr_srch.ibr_srch_val != NULL,
+				 &dir, &bptr, flags & ~MASTER_ONLY);
+      if (status != NIS_SUCCESS)
+	{
+	  NIS_RES_STATUS (res) = status;
+	  goto fail3;
+	}
+
+      while (__nisbind_connect (&bptr) != NIS_SUCCESS)
+	if (__glibc_unlikely (__nisbind_next (&bptr) != NIS_SUCCESS))
+	  {
+	    NIS_RES_STATUS (res) = NIS_NAMEUNREACHABLE;
+	    goto fail;
+	  }
+
+      if (callback != NULL)
+	{
+	  assert (cb == NULL);
+	  cb = __nis_create_callback (callback, userdata, flags);
+	  ibreq->ibr_cbhost.ibr_cbhost_len = 1;
+	  ibreq->ibr_cbhost.ibr_cbhost_val = cb->serv;
+	}
+
+    again:
+      clnt_status = clnt_call (bptr.clnt, NIS_IBLIST,
+			       (xdrproc_t) _xdr_ib_request, (caddr_t) ibreq,
+			       (xdrproc_t) _xdr_nis_result,
+			       (caddr_t) res, RPCTIMEOUT);
+
+      if (__glibc_unlikely (clnt_status != RPC_SUCCESS))
+	NIS_RES_STATUS (res) = NIS_RPCERROR;
+      else
+	switch (NIS_RES_STATUS (res))
+	  { /* start switch */
+	  case NIS_PARTIAL:
+	  case NIS_SUCCESS:
+	  case NIS_S_SUCCESS:
+	    if (__type_of (NIS_RES_OBJECT (res)) == NIS_LINK_OBJ
+		&& (flags & FOLLOW_LINKS))	/* We are following links.  */
+	      {
+		free (ibreq->ibr_name);
+		ibreq->ibr_name = NULL;
+		/* If we hit the link limit, bail.  */
+		if (__glibc_unlikely (count_links > NIS_MAXLINKS))
+		  {
+		    NIS_RES_STATUS (res) = NIS_LINKNAMEERROR;
+		    ++done;
+		    break;
+		  }
+		++count_links;
+		ibreq->ibr_name =
+		  strdup (NIS_RES_OBJECT (res)->LI_data.li_name);
+		if (ibreq->ibr_name == NULL)
+		  {
+		    NIS_RES_STATUS (res) = NIS_NOMEMORY;
+		  fail:
+		    __nisbind_destroy (&bptr);
+		    nis_free_directory (dir);
+		  fail3:
+		    free (tablepath);
+		    if (cb)
+		      {
+			__nis_destroy_callback (cb);
+			ibreq->ibr_cbhost.ibr_cbhost_len = 0;
+			ibreq->ibr_cbhost.ibr_cbhost_val = NULL;
+		      }
+		    if (names != namebuf)
+		      nis_freenames (names);
+		    nis_free_request (ibreq);
+		    nis_freeresult (allres);
+		    return res;
+		  }
+		if (NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_len)
+		  if (ibreq->ibr_srch.ibr_srch_len == 0)
+		    {
+		      ibreq->ibr_srch.ibr_srch_len =
+			NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_len;
+		      ibreq->ibr_srch.ibr_srch_val =
+			NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_val;
+		    }
+		/* The following is a non-obvious optimization.  A
+		   nis_freeresult call would call xdr_free as the
+		   following code.  But it also would unnecessarily
+		   free the result structure.  We avoid this here
+		   along with the necessary tests.  */
+		xdr_free ((xdrproc_t) _xdr_nis_result, (char *)res);
+		memset (res, '\0', sizeof (*res));
+		first_try = 1; /* Try at first the old binding */
+		goto again;
+	      }
+	    else if ((flags & FOLLOW_PATH)
+		     && NIS_RES_STATUS (res) == NIS_PARTIAL)
+	      {
+		enum nis_error err = __follow_path (&tablepath, &tableptr,
+						    ibreq, &bptr);
+		if (err != NIS_SUCCESS)
+		  {
+		    if (err == NIS_NOMEMORY)
+		      NIS_RES_STATUS (res) = err;
+		    ++done;
+		  }
+		else
+		  {
+		    /* The following is a non-obvious optimization.  A
+		       nis_freeresult call would call xdr_free as the
+		       following code.  But it also would unnecessarily
+		       free the result structure.  We avoid this here
+		       along with the necessary tests.  */
+		    xdr_free ((xdrproc_t) _xdr_nis_result, (char *) res);
+		    memset (res, '\0', sizeof (*res));
+		    first_try = 1;
+		    goto again;
+		  }
+	      }
+	    else if ((flags & (FOLLOW_PATH | ALL_RESULTS))
+		     == (FOLLOW_PATH | ALL_RESULTS))
+	      {
+		if (allres == NULL)
+		  {
+		    allres = res;
+		    res = malloc (sizeof (nis_result));
+		    if (res == NULL)
+		      {
+			res = allres;
+			allres = NULL;
+			NIS_RES_STATUS (res) = NIS_NOMEMORY;
+			goto fail;
+		      }
+		    NIS_RES_STATUS (res) = NIS_RES_STATUS (allres);
+		  }
+		else
+		  {
+		    nis_object *objects_val
+		      = realloc (NIS_RES_OBJECT (allres),
+				 (NIS_RES_NUMOBJ (allres)
+				  + NIS_RES_NUMOBJ (res))
+				 * sizeof (nis_object));
+		    if (objects_val == NULL)
+		      {
+			NIS_RES_STATUS (res) = NIS_NOMEMORY;
+			goto fail;
+		      }
+		    NIS_RES_OBJECT (allres) = objects_val;
+		    memcpy (NIS_RES_OBJECT (allres) + NIS_RES_NUMOBJ (allres),
+			    NIS_RES_OBJECT (res),
+			    NIS_RES_NUMOBJ (res) * sizeof (nis_object));
+		    NIS_RES_NUMOBJ (allres) += NIS_RES_NUMOBJ (res);
+		    NIS_RES_NUMOBJ (res) = 0;
+		    free (NIS_RES_OBJECT (res));
+		    NIS_RES_OBJECT (res) = NULL;
+		    NIS_RES_STATUS (allres) = NIS_RES_STATUS (res);
+		    xdr_free ((xdrproc_t) _xdr_nis_result, (char *) res);
+		  }
+		enum nis_error err = __follow_path (&tablepath, &tableptr,
+						    ibreq, &bptr);
+		if (err != NIS_SUCCESS)
+		  {
+		    /* Prepare for the nis_freeresult call.  */
+		    memset (res, '\0', sizeof (*res));
+
+		    if (err == NIS_NOMEMORY)
+		      NIS_RES_STATUS (allres) = err;
+		    ++done;
+		  }
+	      }
+	    else
+	      ++done;
+	    break;
+	  case NIS_CBRESULTS:
+	    if (cb != NULL)
+	      {
+		__nis_do_callback (&bptr, &res->cookie, cb);
+		NIS_RES_STATUS (res) = cb->result;
+
+		if (!(flags & ALL_RESULTS))
+		  ++done;
+		else
+		  {
+		    enum nis_error err
+		      = __follow_path (&tablepath, &tableptr, ibreq, &bptr);
+		    if (err != NIS_SUCCESS)
+		      {
+			if (err == NIS_NOMEMORY)
+			  NIS_RES_STATUS (res) = err;
+			++done;
+		      }
+		  }
+	      }
+	    break;
+	  case NIS_SYSTEMERROR:
+	  case NIS_NOSUCHNAME:
+	  case NIS_NOT_ME:
+	    /* If we had first tried the old binding, do nothing, but
+	       get a new binding */
+	    if (!first_try)
+	      {
+		if (__nisbind_next (&bptr) != NIS_SUCCESS)
+		  {
+		    ++done;
+		    break; /* No more servers to search */
+		  }
+		while (__nisbind_connect (&bptr) != NIS_SUCCESS)
+		  {
+		    if (__nisbind_next (&bptr) != NIS_SUCCESS)
+		      {
+			++done;
+			break; /* No more servers to search */
+		      }
+		  }
+		goto again;
+	      }
+	    break;
+	  default:
+	    if (!first_try)
+	      {
+		/* Try the next domainname if we don't follow a link.  */
+		free (ibreq->ibr_name);
+		ibreq->ibr_name = NULL;
+		if (__glibc_unlikely (count_links))
+		  {
+		    NIS_RES_STATUS (res) = NIS_LINKNAMEERROR;
+		    ++done;
+		    break;
+		  }
+		++name_nr;
+		if (names[name_nr] == NULL)
+		  {
+		    ++done;
+		    break;
+		  }
+		ibreq->ibr_name = strdup (names[name_nr]);
+		if (ibreq->ibr_name == NULL)
+		  {
+		    NIS_RES_STATUS (res) = NIS_NOMEMORY;
+		    goto fail;
+		  }
+		first_try = 1; /* Try old binding at first */
+		goto again;
+	      }
+	    break;
+	  }
+      first_try = 0;
+
+      if (cb)
+	{
+	  __nis_destroy_callback (cb);
+	  ibreq->ibr_cbhost.ibr_cbhost_len = 0;
+	  ibreq->ibr_cbhost.ibr_cbhost_val = NULL;
+	  cb = NULL;
+	}
+
+      __nisbind_destroy (&bptr);
+      nis_free_directory (dir);
+    }
+
+  free (tablepath);
+
+  if (names != namebuf)
+    nis_freenames (names);
+
+  nis_free_request (ibreq);
+
+  if (allres)
+    {
+      nis_freeresult (res);
+      return allres;
+    }
+
+  return res;
+}
+libnsl_hidden_nolink_def (nis_list, GLIBC_2_1)
+
+nis_result *
+nis_add_entry (const_nis_name name, const nis_object *obj2, unsigned int flags)
+{
+  nis_result *res = calloc (1, sizeof (nis_result));
+  if (res == NULL)
+    return NULL;
+
+  if (name == NULL)
+    {
+      NIS_RES_STATUS (res) = NIS_BADNAME;
+      return res;
+    }
+
+  ib_request *ibreq = __create_ib_request (name, flags);
+  if (ibreq == NULL)
+    {
+      NIS_RES_STATUS (res) = NIS_BADNAME;
+      return res;
+    }
+
+  nis_object obj;
+  memcpy (&obj, obj2, sizeof (nis_object));
+
+  size_t namelen = strlen (name);
+  char buf1[namelen + 20];
+  char buf4[namelen + 20];
+
+  if (obj.zo_name == NULL || strlen (obj.zo_name) == 0)
+    obj.zo_name = nis_leaf_of_r (name, buf1, sizeof (buf1));
+
+  if (obj.zo_owner == NULL || strlen (obj.zo_owner) == 0)
+    obj.zo_owner = nis_local_principal ();
+
+  if (obj.zo_group == NULL || strlen (obj.zo_group) == 0)
+    obj.zo_group = nis_local_group ();
+
+  obj.zo_domain = nis_domain_of_r (name, buf4, sizeof (buf4));
+
+  ibreq->ibr_obj.ibr_obj_val = nis_clone_object (&obj, NULL);
+  if (ibreq->ibr_obj.ibr_obj_val == NULL)
+    {
+      nis_free_request (ibreq);
+      NIS_RES_STATUS (res) = NIS_NOMEMORY;
+      return res;
+    }
+  ibreq->ibr_obj.ibr_obj_len = 1;
+
+  nis_error status = __do_niscall (ibreq->ibr_name, NIS_IBADD,
+				   (xdrproc_t) _xdr_ib_request,
+				   (caddr_t) ibreq,
+				   (xdrproc_t) _xdr_nis_result,
+				   (caddr_t) res, 0, NULL);
+  if (__glibc_unlikely (status != NIS_SUCCESS))
+    NIS_RES_STATUS (res) = status;
+
+  nis_free_request (ibreq);
+
+  return res;
+}
+libnsl_hidden_nolink_def (nis_add_entry, GLIBC_2_1)
+
+nis_result *
+nis_modify_entry (const_nis_name name, const nis_object *obj2,
+		  unsigned int flags)
+{
+  nis_object obj;
+  nis_result *res;
+  nis_error status;
+  ib_request *ibreq;
+  size_t namelen = strlen (name);
+  char buf1[namelen + 20];
+  char buf4[namelen + 20];
+
+  res = calloc (1, sizeof (nis_result));
+  if (res == NULL)
+    return NULL;
+
+  ibreq = __create_ib_request (name, flags);
+  if (ibreq == NULL)
+    {
+      NIS_RES_STATUS (res) = NIS_BADNAME;
+      return res;
+    }
+
+  memcpy (&obj, obj2, sizeof (nis_object));
+
+  if (obj.zo_name == NULL || strlen (obj.zo_name) == 0)
+    obj.zo_name = nis_leaf_of_r (name, buf1, sizeof (buf1));
+
+  if (obj.zo_owner == NULL || strlen (obj.zo_owner) == 0)
+    obj.zo_owner = nis_local_principal ();
+
+  if (obj.zo_group == NULL || strlen (obj.zo_group) == 0)
+    obj.zo_group = nis_local_group ();
+
+  obj.zo_domain = nis_domain_of_r (name, buf4, sizeof (buf4));
+
+  ibreq->ibr_obj.ibr_obj_val = nis_clone_object (&obj, NULL);
+  if (ibreq->ibr_obj.ibr_obj_val == NULL)
+    {
+      nis_free_request (ibreq);
+      NIS_RES_STATUS (res) = NIS_NOMEMORY;
+      return res;
+    }
+  ibreq->ibr_obj.ibr_obj_len = 1;
+
+  status = __do_niscall (ibreq->ibr_name, NIS_IBMODIFY,
+			 (xdrproc_t) _xdr_ib_request,
+			 (caddr_t) ibreq, (xdrproc_t) _xdr_nis_result,
+			 (caddr_t) res, 0, NULL);
+  if (__glibc_unlikely (status != NIS_SUCCESS))
+    NIS_RES_STATUS (res) = status;
+
+  nis_free_request (ibreq);
+
+  return res;
+}
+libnsl_hidden_nolink_def (nis_modify_entry, GLIBC_2_1)
+
+nis_result *
+nis_remove_entry (const_nis_name name, const nis_object *obj,
+		  unsigned int flags)
+{
+  nis_result *res;
+  ib_request *ibreq;
+  nis_error status;
+
+  res = calloc (1, sizeof (nis_result));
+  if (res == NULL)
+    return NULL;
+
+  if (name == NULL)
+    {
+      NIS_RES_STATUS (res) = NIS_BADNAME;
+      return res;
+    }
+
+  ibreq = __create_ib_request (name, flags);
+  if (ibreq == NULL)
+    {
+      NIS_RES_STATUS (res) = NIS_BADNAME;
+      return res;
+    }
+
+  if (obj != NULL)
+    {
+      ibreq->ibr_obj.ibr_obj_val = nis_clone_object (obj, NULL);
+      if (ibreq->ibr_obj.ibr_obj_val == NULL)
+	{
+	  nis_free_request (ibreq);
+	  NIS_RES_STATUS (res) = NIS_NOMEMORY;
+	  return res;
+	}
+      ibreq->ibr_obj.ibr_obj_len = 1;
+    }
+
+  if ((status = __do_niscall (ibreq->ibr_name, NIS_IBREMOVE,
+			      (xdrproc_t) _xdr_ib_request,
+			      (caddr_t) ibreq, (xdrproc_t) _xdr_nis_result,
+			      (caddr_t) res, 0, NULL)) != NIS_SUCCESS)
+    NIS_RES_STATUS (res) = status;
+
+  nis_free_request (ibreq);
+
+  return res;
+}
+libnsl_hidden_nolink_def (nis_remove_entry, GLIBC_2_1)
+
+nis_result *
+nis_first_entry (const_nis_name name)
+{
+  nis_result *res;
+  ib_request *ibreq;
+  nis_error status;
+
+  res = calloc (1, sizeof (nis_result));
+  if (res == NULL)
+    return NULL;
+
+  if (name == NULL)
+    {
+      NIS_RES_STATUS (res) = NIS_BADNAME;
+      return res;
+    }
+
+  ibreq = __create_ib_request (name, 0);
+  if (ibreq == NULL)
+    {
+      NIS_RES_STATUS (res) = NIS_BADNAME;
+      return res;
+    }
+
+  status = __do_niscall (ibreq->ibr_name, NIS_IBFIRST,
+			 (xdrproc_t) _xdr_ib_request,
+			 (caddr_t) ibreq, (xdrproc_t) _xdr_nis_result,
+			 (caddr_t) res, 0, NULL);
+
+  if (__glibc_unlikely (status != NIS_SUCCESS))
+    NIS_RES_STATUS (res) = status;
+
+  nis_free_request (ibreq);
+
+  return res;
+}
+libnsl_hidden_nolink_def (nis_first_entry, GLIBC_2_1)
+
+nis_result *
+nis_next_entry (const_nis_name name, const netobj *cookie)
+{
+  nis_result *res;
+  ib_request *ibreq;
+  nis_error status;
+
+  res = calloc (1, sizeof (nis_result));
+  if (res == NULL)
+    return NULL;
+
+  if (name == NULL)
+    {
+      NIS_RES_STATUS (res) = NIS_BADNAME;
+      return res;
+    }
+
+  ibreq = __create_ib_request (name, 0);
+  if (ibreq == NULL)
+    {
+      NIS_RES_STATUS (res) = NIS_BADNAME;
+      return res;
+    }
+
+  if (cookie != NULL)
+    {
+      ibreq->ibr_cookie.n_bytes = cookie->n_bytes;
+      ibreq->ibr_cookie.n_len = cookie->n_len;
+    }
+
+  status = __do_niscall (ibreq->ibr_name, NIS_IBNEXT,
+			 (xdrproc_t) _xdr_ib_request,
+			 (caddr_t) ibreq, (xdrproc_t) _xdr_nis_result,
+			 (caddr_t) res, 0, NULL);
+
+  if (__glibc_unlikely (status != NIS_SUCCESS))
+    NIS_RES_STATUS (res) = status;
+
+  if (cookie != NULL)
+    {
+      /* Don't give cookie free, it is not from us */
+      ibreq->ibr_cookie.n_bytes = NULL;
+      ibreq->ibr_cookie.n_len = 0;
+    }
+
+  nis_free_request (ibreq);
+
+  return res;
+}
+libnsl_hidden_nolink_def (nis_next_entry, GLIBC_2_1)
diff --git a/REORG.TODO/nis/nis_util.c b/REORG.TODO/nis/nis_util.c
new file mode 100644
index 0000000000..fcb7120e41
--- /dev/null
+++ b/REORG.TODO/nis/nis_util.c
@@ -0,0 +1,52 @@
+/* Copyright (c) 1997-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <string.h>
+#include <rpcsvc/nis.h>
+#include <shlib-compat.h>
+
+#include "nis_xdr.h"
+#include "nis_intern.h"
+
+fd_result *
+__nis_finddirectory (directory_obj *dir, const_nis_name name)
+{
+  nis_error status;
+  fd_args fd_args;
+  fd_result *fd_res;
+
+  fd_args.dir_name = (char *)name;
+  fd_args.requester = nis_local_host();
+  fd_res = calloc (1, sizeof (fd_result));
+  if (fd_res == NULL)
+    return NULL;
+
+  status = __do_niscall2 (dir->do_servers.do_servers_val,
+			  dir->do_servers.do_servers_len,
+			  NIS_FINDDIRECTORY, (xdrproc_t) _xdr_fd_args,
+			  (caddr_t) &fd_args, (xdrproc_t) _xdr_fd_result,
+			  (caddr_t) fd_res, NO_AUTHINFO|USE_DGRAM, NULL);
+  if (status != NIS_SUCCESS)
+    fd_res->status = status;
+
+  return fd_res;
+}
+libnsl_hidden_nolink_def (__nis_finddirectory, GLIBC_2_1)
+
+/* The hash implementation is in a separate file.  */
+#include "nis_hash.c"
diff --git a/REORG.TODO/nis/nis_verifygroup.c b/REORG.TODO/nis/nis_verifygroup.c
new file mode 100644
index 0000000000..4fb2cc5977
--- /dev/null
+++ b/REORG.TODO/nis/nis_verifygroup.c
@@ -0,0 +1,52 @@
+/* Copyright (c) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <string.h>
+#include <rpcsvc/nis.h>
+#include <shlib-compat.h>
+
+nis_error
+nis_verifygroup (const_nis_name group)
+{
+  if (group != NULL && group[0] != '\0')
+    {
+      size_t grouplen = strlen (group);
+      char buf[grouplen + 50];
+      char leafbuf[grouplen + 2];
+      char domainbuf[grouplen + 2];
+      nis_result *res;
+      nis_error status;
+      char *cp, *cp2;
+
+      cp = stpcpy (buf, nis_leaf_of_r (group, leafbuf, sizeof (leafbuf) - 1));
+      cp = stpcpy (cp, ".groups_dir");
+      cp2 = nis_domain_of_r (group, domainbuf, sizeof (domainbuf) - 1);
+      if (cp2 != NULL && cp2[0] != '\0')
+	{
+	  *cp++ = '.';
+	  stpcpy (cp, cp2);
+	}
+      res = nis_lookup (buf, 0);
+      status = NIS_RES_STATUS (res);
+      nis_freeresult (res);
+      return status;
+    }
+  else
+    return NIS_FAIL;
+}
+libnsl_hidden_nolink_def (nis_verifygroup, GLIBC_2_1)
diff --git a/REORG.TODO/nis/nis_xdr.c b/REORG.TODO/nis/nis_xdr.c
new file mode 100644
index 0000000000..3217dc51bd
--- /dev/null
+++ b/REORG.TODO/nis/nis_xdr.c
@@ -0,0 +1,460 @@
+/* Copyright (c) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stdint.h>
+#include <rpcsvc/nis.h>
+#include <rpcsvc/nis_callback.h> /* for "official" Solaris xdr functions */
+#include <shlib-compat.h>
+
+/* This functions do exist without beginning "_" under Solaris 2.x, but
+   we have no prototypes for them. To avoid the same problems as with the
+   YP xdr functions, we don't make them public. */
+#include "nis_xdr.h"
+
+static bool_t
+xdr_nis_attr (XDR *xdrs, nis_attr *objp)
+{
+  bool_t res = xdr_string (xdrs, &objp->zattr_ndx, ~0);
+  if (__builtin_expect (res, TRUE))
+    res = xdr_bytes (xdrs, (char **) &objp->zattr_val.zattr_val_val,
+		     &objp->zattr_val.zattr_val_len, ~0);
+  return res;
+}
+
+static __always_inline bool_t
+xdr_nis_name (XDR *xdrs, nis_name *objp)
+{
+  return xdr_string (xdrs, objp, ~0);
+}
+
+bool_t
+_xdr_nis_name (XDR *xdrs, nis_name *objp)
+{
+  return xdr_nis_name (xdrs, objp);
+}
+
+static __always_inline bool_t
+xdr_zotypes (XDR *xdrs, zotypes *objp)
+{
+  return xdr_enum (xdrs, (enum_t *) objp);
+}
+
+static __always_inline bool_t
+xdr_nstype (XDR *xdrs, nstype *objp)
+{
+  return xdr_enum (xdrs, (enum_t *) objp);
+}
+
+static bool_t
+xdr_oar_mask (XDR *xdrs, oar_mask *objp)
+{
+  bool_t res = xdr_u_int (xdrs, &objp->oa_rights);
+  if (__builtin_expect (res, TRUE))
+    res = xdr_zotypes (xdrs, &objp->oa_otype);
+  return res;
+}
+
+static bool_t
+xdr_endpoint (XDR *xdrs, endpoint *objp)
+{
+  bool_t res =  xdr_string (xdrs, &objp->uaddr, ~0);
+  if (__builtin_expect (res, TRUE))
+    {
+      res = xdr_string (xdrs, &objp->family, ~0);
+      if (__glibc_likely (res))
+	res = xdr_string (xdrs, &objp->proto, ~0);
+    }
+  return res;
+}
+
+bool_t
+_xdr_nis_server (XDR *xdrs, nis_server *objp)
+{
+  bool_t res = xdr_nis_name (xdrs, &objp->name);
+  if (__builtin_expect (res, TRUE))
+    {
+      res = xdr_array (xdrs, (void *) &objp->ep.ep_val, &objp->ep.ep_len,
+		       ~0, sizeof (endpoint), (xdrproc_t) xdr_endpoint);
+      if (__builtin_expect (res, TRUE))
+	{
+	  res = xdr_u_int (xdrs, &objp->key_type);
+	  if (__builtin_expect (res, TRUE))
+	    res = xdr_netobj (xdrs, &objp->pkey);
+	}
+    }
+  return res;
+}
+
+bool_t
+_xdr_directory_obj (XDR *xdrs, directory_obj *objp)
+{
+  bool_t res = xdr_nis_name (xdrs, &objp->do_name);
+  if (__builtin_expect (res, TRUE))
+    {
+      res = xdr_nstype (xdrs, &objp->do_type);
+      if (__builtin_expect (res, TRUE))
+	{
+	  res = xdr_array (xdrs, (void *) &objp->do_servers.do_servers_val,
+			   &objp->do_servers.do_servers_len, ~0,
+			   sizeof (nis_server), (xdrproc_t) _xdr_nis_server);
+	  if (__builtin_expect (res, TRUE))
+	    {
+	      res = xdr_uint32_t (xdrs, &objp->do_ttl);
+	      if (__builtin_expect (res, TRUE))
+		res = xdr_array (xdrs,
+				 (void *) &objp->do_armask.do_armask_val,
+				 &objp->do_armask.do_armask_len, ~0,
+				 sizeof (oar_mask), (xdrproc_t) xdr_oar_mask);
+	    }
+	}
+    }
+  return res;
+}
+
+static bool_t
+xdr_entry_col (XDR *xdrs, entry_col *objp)
+{
+  bool_t res = xdr_u_int (xdrs, &objp->ec_flags);
+  if (__builtin_expect (res, TRUE))
+    res = xdr_bytes (xdrs, (char **) &objp->ec_value.ec_value_val,
+		     &objp->ec_value.ec_value_len, ~0);
+  return res;
+}
+
+static bool_t
+xdr_entry_obj (XDR *xdrs, entry_obj *objp)
+{
+  bool_t res = xdr_string (xdrs, &objp->en_type, ~0);
+  if (__builtin_expect (res, TRUE))
+    res = xdr_array (xdrs, (void *) &objp->en_cols.en_cols_val,
+		     &objp->en_cols.en_cols_len, ~0,
+		     sizeof (entry_col), (xdrproc_t) xdr_entry_col);
+  return res;
+}
+
+static bool_t
+xdr_group_obj (XDR *xdrs, group_obj *objp)
+{
+  bool_t res = xdr_u_int (xdrs, &objp->gr_flags);
+  if (__builtin_expect (res, TRUE))
+    res = xdr_array (xdrs, (void *) &objp->gr_members.gr_members_val,
+		     &objp->gr_members.gr_members_len, ~0,
+		     sizeof (nis_name), (xdrproc_t) _xdr_nis_name);
+  return res;
+}
+
+static bool_t
+xdr_link_obj (XDR *xdrs, link_obj *objp)
+{
+  bool_t res = xdr_zotypes (xdrs, &objp->li_rtype);
+  if (__builtin_expect (res, TRUE))
+    {
+      res = xdr_array (xdrs, (void *) &objp->li_attrs.li_attrs_val,
+		       &objp->li_attrs.li_attrs_len, ~0,
+		       sizeof (nis_attr), (xdrproc_t) xdr_nis_attr);
+      if (__builtin_expect (res, TRUE))
+	res = xdr_nis_name (xdrs, &objp->li_name);
+    }
+  return res;
+}
+
+static bool_t
+xdr_table_col (XDR *xdrs, table_col *objp)
+{
+  bool_t res = xdr_string (xdrs, &objp->tc_name, 64);
+  if (__builtin_expect (res, TRUE))
+    {
+      res = xdr_u_int (xdrs, &objp->tc_flags);
+      if (__builtin_expect (res, TRUE))
+	res = xdr_u_int (xdrs, &objp->tc_rights);
+    }
+  return res;
+}
+
+static bool_t
+xdr_table_obj (XDR *xdrs, table_obj *objp)
+{
+  bool_t res = xdr_string (xdrs, &objp->ta_type, 64);
+  if (__builtin_expect (res, TRUE))
+    {
+      res = xdr_int (xdrs, &objp->ta_maxcol);
+      if (__builtin_expect (res, TRUE))
+	{
+	  res = xdr_u_char (xdrs, &objp->ta_sep);
+	  if (__builtin_expect (res, TRUE))
+	    {
+	      res = xdr_array (xdrs, (void *) &objp->ta_cols.ta_cols_val,
+			       &objp->ta_cols.ta_cols_len, ~0,
+			       sizeof (table_col), (xdrproc_t) xdr_table_col);
+	      if (__builtin_expect (res, TRUE))
+		res = xdr_string (xdrs, &objp->ta_path, ~0);
+	    }
+	}
+    }
+  return res;
+}
+
+static bool_t
+xdr_objdata (XDR *xdrs, objdata *objp)
+{
+  bool_t res = xdr_zotypes (xdrs, &objp->zo_type);
+  if (!__builtin_expect (res, TRUE))
+    return res;
+  switch (objp->zo_type)
+    {
+    case NIS_DIRECTORY_OBJ:
+      return _xdr_directory_obj (xdrs, &objp->objdata_u.di_data);
+    case NIS_GROUP_OBJ:
+      return xdr_group_obj (xdrs, &objp->objdata_u.gr_data);
+    case NIS_TABLE_OBJ:
+      return xdr_table_obj (xdrs, &objp->objdata_u.ta_data);
+    case NIS_ENTRY_OBJ:
+      return xdr_entry_obj (xdrs, &objp->objdata_u.en_data);
+    case NIS_LINK_OBJ:
+      return xdr_link_obj (xdrs, &objp->objdata_u.li_data);
+    case NIS_PRIVATE_OBJ:
+      return xdr_bytes (xdrs, &objp->objdata_u.po_data.po_data_val,
+			&objp->objdata_u.po_data.po_data_len, ~0);
+    case NIS_NO_OBJ:
+    case NIS_BOGUS_OBJ:
+    default:
+      return TRUE;
+    }
+}
+
+static bool_t
+xdr_nis_oid (XDR *xdrs, nis_oid *objp)
+{
+  bool_t res = xdr_uint32_t (xdrs, &objp->ctime);
+  if  (__builtin_expect (res, TRUE))
+    res = xdr_uint32_t (xdrs, &objp->mtime);
+  return res;
+}
+
+bool_t
+_xdr_nis_object (XDR *xdrs, nis_object *objp)
+{
+  bool_t res = xdr_nis_oid (xdrs, &objp->zo_oid);
+  if (__builtin_expect (res, TRUE))
+    {
+      res = xdr_nis_name (xdrs, &objp->zo_name);
+      if (__builtin_expect (res, TRUE))
+	{
+	  res = xdr_nis_name (xdrs, &objp->zo_owner);
+	  if (__builtin_expect (res, TRUE))
+	    {
+	      res = xdr_nis_name (xdrs, &objp->zo_group);
+	      if (__builtin_expect (res, TRUE))
+		{
+		  res = xdr_nis_name (xdrs, &objp->zo_domain);
+		  if (__builtin_expect (res, TRUE))
+		    {
+		      res = xdr_u_int (xdrs, &objp->zo_access);
+		      if (__builtin_expect (res, TRUE))
+			{
+			  res = xdr_uint32_t (xdrs, &objp->zo_ttl);
+			  if (__builtin_expect (res, TRUE))
+			    res = xdr_objdata (xdrs, &objp->zo_data);
+			}
+		    }
+		}
+	    }
+	}
+    }
+  return res;
+}
+
+static __always_inline bool_t
+xdr_nis_error (XDR *xdrs, nis_error *objp)
+{
+  return xdr_enum (xdrs, (enum_t *) objp);
+}
+
+bool_t
+_xdr_nis_error (XDR *xdrs, nis_error *objp)
+{
+  return xdr_nis_error (xdrs, objp);
+}
+
+bool_t
+_xdr_nis_result (XDR *xdrs, nis_result *objp)
+{
+  bool_t res = xdr_nis_error (xdrs, &objp->status);
+  if (__builtin_expect (res, TRUE))
+    {
+      res = xdr_array (xdrs, (void *) &objp->objects.objects_val,
+		       &objp->objects.objects_len, ~0,
+		       sizeof (nis_object), (xdrproc_t) _xdr_nis_object);
+      if (__builtin_expect (res, TRUE))
+	{
+	  res = xdr_netobj (xdrs, &objp->cookie);
+	  if (__builtin_expect (res, TRUE))
+	    {
+	      res = xdr_uint32_t (xdrs, &objp->zticks);
+	      if (__builtin_expect (res, TRUE))
+		{
+		  res = xdr_uint32_t (xdrs, &objp->dticks);
+		  if (__builtin_expect (res, TRUE))
+		    {
+		      res = xdr_uint32_t (xdrs, &objp->aticks);
+		      if (__builtin_expect (res, TRUE))
+			res = xdr_uint32_t (xdrs, &objp->cticks);
+		    }
+		}
+	    }
+	}
+    }
+  return res;
+}
+libnsl_hidden_nolink_def (_xdr_nis_result, GLIBC_PRIVATE)
+
+bool_t
+_xdr_ns_request (XDR *xdrs, ns_request *objp)
+{
+  bool_t res = xdr_nis_name (xdrs, &objp->ns_name);
+  if (__builtin_expect (res, TRUE))
+    res = xdr_array (xdrs, (void *) &objp->ns_object.ns_object_val,
+		     &objp->ns_object.ns_object_len, 1,
+		     sizeof (nis_object), (xdrproc_t) _xdr_nis_object);
+  return res;
+}
+
+bool_t
+_xdr_ib_request (XDR *xdrs, ib_request *objp)
+{
+  bool_t res = xdr_nis_name (xdrs, &objp->ibr_name);
+  if (__builtin_expect (res, TRUE))
+    {
+      res = xdr_array (xdrs, (void *) &objp->ibr_srch.ibr_srch_val,
+		       &objp->ibr_srch.ibr_srch_len, ~0,
+		       sizeof (nis_attr), (xdrproc_t) xdr_nis_attr);
+      if (__builtin_expect (res, TRUE))
+	{
+	  res = xdr_u_int (xdrs, &objp->ibr_flags);
+	  if (__builtin_expect (res, TRUE))
+	    {
+	      res = xdr_array (xdrs, (void *) &objp->ibr_obj.ibr_obj_val,
+			       &objp->ibr_obj.ibr_obj_len, 1,
+			       sizeof (nis_object),
+			       (xdrproc_t) _xdr_nis_object);
+	      if (__builtin_expect (res, TRUE))
+		{
+		  res = xdr_array (xdrs,
+				   (void *) &objp->ibr_cbhost.ibr_cbhost_val,
+				   &objp->ibr_cbhost.ibr_cbhost_len, 1,
+				   sizeof (nis_server),
+				   (xdrproc_t) _xdr_nis_server);
+		  if (__builtin_expect (res, TRUE))
+		    {
+		      res = xdr_u_int (xdrs, &objp->ibr_bufsize);
+		      if (__builtin_expect (res, TRUE))
+			res =  xdr_netobj (xdrs, &objp->ibr_cookie);
+		    }
+		}
+	    }
+	}
+    }
+  return res;
+}
+libnsl_hidden_nolink_def (_xdr_ib_request, GLIBC_PRIVATE)
+
+bool_t
+_xdr_ping_args (XDR *xdrs, ping_args *objp)
+{
+  bool_t res = xdr_nis_name (xdrs, &objp->dir);
+  if (__builtin_expect (res, TRUE))
+    res = xdr_uint32_t (xdrs, &objp->stamp);
+  return res;
+}
+
+bool_t
+_xdr_cp_result (XDR *xdrs, cp_result *objp)
+{
+  bool_t res = xdr_nis_error (xdrs, &objp->cp_status);
+  if (__builtin_expect (res, TRUE))
+    {
+      res = xdr_uint32_t (xdrs, &objp->cp_zticks);
+      if (__builtin_expect (res, TRUE))
+	res = xdr_uint32_t (xdrs, &objp->cp_dticks);
+    }
+  return res;
+}
+
+bool_t
+_xdr_nis_tag (XDR *xdrs, nis_tag *objp)
+{
+  bool_t res = xdr_u_int (xdrs, &objp->tag_type);
+  if (__builtin_expect (res, TRUE))
+    res = xdr_string (xdrs, &objp->tag_val, ~0);
+  return res;
+}
+
+bool_t
+_xdr_nis_taglist (XDR *xdrs, nis_taglist *objp)
+{
+  return xdr_array (xdrs, (void *) &objp->tags.tags_val,
+		    &objp->tags.tags_len, ~0, sizeof (nis_tag),
+		    (xdrproc_t) _xdr_nis_tag);
+}
+
+bool_t
+_xdr_fd_args (XDR *xdrs, fd_args *objp)
+{
+  bool_t res = xdr_nis_name (xdrs, &objp->dir_name);
+  if (__builtin_expect (res, TRUE))
+    res = xdr_nis_name (xdrs, &objp->requester);
+  return res;
+}
+
+bool_t
+_xdr_fd_result (XDR *xdrs, fd_result *objp)
+{
+  bool_t res = xdr_nis_error (xdrs, &objp->status);
+  if (__builtin_expect (res, TRUE))
+    {
+      res = xdr_nis_name (xdrs, &objp->source);
+      if (__builtin_expect (res, TRUE))
+	{
+	  res = xdr_bytes (xdrs, (char **) &objp->dir_data.dir_data_val,
+			   &objp->dir_data.dir_data_len, ~0);
+	  if (__builtin_expect (res, TRUE))
+	    res = xdr_bytes (xdrs, (char **) &objp->signature.signature_val,
+			     &objp->signature.signature_len, ~0);
+	}
+    }
+  return res;
+}
+
+/* The following functions have prototypes in nis_callback.h.  So
+   we make them public */
+bool_t
+xdr_obj_p (XDR *xdrs, obj_p *objp)
+{
+  return xdr_pointer (xdrs, (char **)objp, sizeof (nis_object),
+		      (xdrproc_t)_xdr_nis_object);
+}
+libnsl_hidden_nolink_def (xdr_obj_p, GLIBC_2_1)
+
+bool_t
+xdr_cback_data (XDR *xdrs, cback_data *objp)
+{
+  return xdr_array (xdrs, (void *) &objp->entries.entries_val,
+		    &objp->entries.entries_len, ~0,
+		    sizeof (obj_p), (xdrproc_t) xdr_obj_p);
+}
+libnsl_hidden_nolink_def (xdr_cback_data, GLIBC_2_1)
diff --git a/REORG.TODO/nis/nis_xdr.h b/REORG.TODO/nis/nis_xdr.h
new file mode 100644
index 0000000000..f56608b590
--- /dev/null
+++ b/REORG.TODO/nis/nis_xdr.h
@@ -0,0 +1,43 @@
+/* Copyright (c) 1998-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef __NIS_XDR_H
+#define __NIS_XDR_H 1
+
+#include <features.h>
+
+extern  bool_t _xdr_nis_attr (XDR *, nis_attr*) attribute_hidden;
+extern  bool_t _xdr_nis_name (XDR *, nis_name*) attribute_hidden;
+extern  bool_t _xdr_nis_server (XDR *, nis_server*) attribute_hidden;
+extern  bool_t _xdr_directory_obj (XDR *, directory_obj*) attribute_hidden;
+extern  bool_t _xdr_nis_object (XDR *, nis_object*) attribute_hidden;
+extern  bool_t _xdr_nis_error (XDR *, nis_error*) attribute_hidden;
+extern  bool_t _xdr_ns_request (XDR *, ns_request*) attribute_hidden;
+extern  bool_t _xdr_ping_args (XDR *, ping_args*) attribute_hidden;
+extern  bool_t _xdr_cp_result (XDR *, cp_result*) attribute_hidden;
+extern  bool_t _xdr_nis_tag (XDR *, nis_tag*) attribute_hidden;
+extern  bool_t _xdr_nis_taglist (XDR *, nis_taglist*) attribute_hidden;
+extern  bool_t _xdr_fd_args (XDR *, fd_args*) attribute_hidden;
+extern  bool_t _xdr_fd_result (XDR *, fd_result*) attribute_hidden;
+
+extern  bool_t _xdr_ib_request (XDR *, ib_request*);
+libnsl_hidden_proto (_xdr_ib_request)
+extern  bool_t _xdr_nis_result (XDR *, nis_result*);
+libnsl_hidden_proto (_xdr_nis_result)
+
+#endif
diff --git a/REORG.TODO/nis/nisplus-parser.h b/REORG.TODO/nis/nisplus-parser.h
new file mode 100644
index 0000000000..313c02ffbb
--- /dev/null
+++ b/REORG.TODO/nis/nisplus-parser.h
@@ -0,0 +1,35 @@
+/* Copyright (C) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef __NISPLUS_PARSER_H
+#define __NISPLUS_PARSER_H	1
+
+#include <pwd.h>
+#include <grp.h>
+#include <shadow.h>
+
+extern int _nss_nisplus_parse_pwent (nis_result *result, struct passwd *pw,
+				     char *buffer, size_t buflen, int *errnop);
+
+extern int _nss_nisplus_parse_grent (nis_result *result, struct group *gr,
+				     char *buffer, size_t buflen, int *errnop);
+
+extern int _nss_nisplus_parse_spent (nis_result *result, struct spwd *sp,
+				     char *buffer, size_t buflen, int *errnop);
+
+#endif
diff --git a/REORG.TODO/nis/nss b/REORG.TODO/nis/nss
new file mode 100644
index 0000000000..0ac6774a1f
--- /dev/null
+++ b/REORG.TODO/nis/nss
@@ -0,0 +1,37 @@
+# /etc/default/nss
+# This file can theoretically contain a bunch of customization variables
+# for Name Service Switch in the GNU C library.  For now there are only
+# four variables:
+#
+# NETID_AUTHORITATIVE
+#   If set to TRUE, the initgroups() function will accept the information
+#   from the netid.byname NIS map as authoritative.  This can speed up the
+#   function significantly if the group.byname map is large.  The content
+#   of the netid.byname map is used AS IS.  The system administrator has
+#   to make sure it is correctly generated.
+#NETID_AUTHORITATIVE=TRUE
+#
+# SERVICES_AUTHORITATIVE
+#   If set to TRUE, the getservbyname{,_r}() function will assume
+#   services.byservicename NIS map exists and is authoritative, particularly
+#   that it contains both keys with /proto and without /proto for both
+#   primary service names and service aliases.  The system administrator
+#   has to make sure it is correctly generated.
+#SERVICES_AUTHORITATIVE=TRUE
+#
+# SETENT_BATCH_READ
+#  If set to TRUE, various setXXent() functions will read the entire
+#  database at once and then hand out the requests one by one from
+#  memory with every getXXent() call.  Otherwise each getXXent() call
+#  might result into a network communication with the server to get
+#  the next entry.
+#SETENT_BATCH_READ=TRUE
+#
+# ADJUNCT_AS_SHADOW
+#  If set to TRUE, the passwd routines in the NIS NSS module will not
+#  use the passwd.adjunct.byname tables to fill in the password data
+#  in the passwd structure.  This is a security problem if the NIS
+#  server cannot be trusted to send the passwd.adjuct table only to
+#  privileged clients.  Instead the passwd.adjunct.byname table is
+#  used to synthesize the shadow.byname table if it does not exist.
+#ADJUNCT_AS_SHADOW=TRUE
diff --git a/REORG.TODO/nis/nss-default.c b/REORG.TODO/nis/nss-default.c
new file mode 100644
index 0000000000..092e121107
--- /dev/null
+++ b/REORG.TODO/nis/nss-default.c
@@ -0,0 +1,127 @@
+/* Copyright (C) 1996-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libc-lock.h>
+
+#include <libnsl.h>
+
+
+/* Path of the file.  */
+static const char default_nss[] = "/etc/default/nss";
+
+/* Flags once read from the file.  */
+static int default_nss_flags;
+
+/* Code to make sure we call 'init' once.  */
+__libc_once_define (static, once);
+
+/* Table of the recognized variables.  */
+static const struct
+{
+  char name[23];
+  unsigned int len;
+  int flag;
+} vars[] =
+  {
+#define STRNLEN(s) s, sizeof (s) - 1
+    { STRNLEN ("NETID_AUTHORITATIVE"), NSS_FLAG_NETID_AUTHORITATIVE },
+    { STRNLEN ("SERVICES_AUTHORITATIVE"), NSS_FLAG_SERVICES_AUTHORITATIVE },
+    { STRNLEN ("SETENT_BATCH_READ"), NSS_FLAG_SETENT_BATCH_READ },
+    { STRNLEN ("ADJUNCT_AS_SHADOW"), NSS_FLAG_ADJUNCT_AS_SHADOW },
+  };
+#define nvars (sizeof (vars) / sizeof (vars[0]))
+
+
+static void
+init (void)
+{
+  int saved_errno = errno;
+  FILE *fp = fopen (default_nss, "rce");
+  if (fp != NULL)
+    {
+      char *line = NULL;
+      size_t linelen = 0;
+
+      __fsetlocking (fp, FSETLOCKING_BYCALLER);
+
+      while (!feof_unlocked (fp))
+	{
+	  ssize_t n = getline (&line, &linelen, fp);
+	  if (n <= 0)
+	    break;
+
+	  /* Recognize only
+
+	       <THE-VARIABLE> = TRUE
+
+	     with arbitrary white spaces.  */
+	  char *cp = line;
+	  while (isspace (*cp))
+	    ++cp;
+
+	  /* Recognize comment lines.  */
+	  if (*cp == '#')
+	    continue;
+
+	  int idx;
+	  for (idx = 0; idx < nvars; ++idx)
+	    if (strncmp (cp, vars[idx].name, vars[idx].len) == 0)
+	      break;
+	  if (idx == nvars)
+	    continue;
+
+	  cp += vars[idx].len;
+	  while (isspace (*cp))
+	    ++cp;
+	  if (*cp++ != '=')
+	    continue;
+	  while (isspace (*cp))
+	    ++cp;
+
+	  if (strncmp (cp, "TRUE", 4) != 0)
+	    continue;
+	  cp += 4;
+
+	  while (isspace (*cp))
+	    ++cp;
+
+	  if (*cp == '\0')
+	    default_nss_flags |= vars[idx].flag;
+	}
+
+      free (line);
+
+      fclose (fp);
+    }
+  __set_errno (saved_errno);
+}
+
+
+int
+_nsl_default_nss (void)
+{
+  /* If we have not yet read the file yet do it now.  */
+  __libc_once (once, init);
+
+  return default_nss_flags;
+}
diff --git a/REORG.TODO/nis/nss-nis.c b/REORG.TODO/nis/nss-nis.c
new file mode 100644
index 0000000000..31ebc4263a
--- /dev/null
+++ b/REORG.TODO/nis/nss-nis.c
@@ -0,0 +1,44 @@
+/* Copyright (C) 1996-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "nss-nis.h"
+#include "nsswitch.h"
+
+
+/* Convert YP error number to NSS error number.  */
+const enum nss_status __yperr2nss_tab[] =
+{
+  [YPERR_SUCCESS] = NSS_STATUS_SUCCESS,
+  [YPERR_BADARGS] = NSS_STATUS_UNAVAIL,
+  [YPERR_RPC]     = NSS_STATUS_UNAVAIL,
+  [YPERR_DOMAIN]  = NSS_STATUS_UNAVAIL,
+  [YPERR_MAP]     = NSS_STATUS_UNAVAIL,
+  [YPERR_KEY]     = NSS_STATUS_NOTFOUND,
+  [YPERR_YPERR]   = NSS_STATUS_UNAVAIL,
+  [YPERR_RESRC]   = NSS_STATUS_TRYAGAIN,
+  [YPERR_NOMORE]  = NSS_STATUS_NOTFOUND,
+  [YPERR_PMAP]    = NSS_STATUS_UNAVAIL,
+  [YPERR_YPBIND]  = NSS_STATUS_UNAVAIL,
+  [YPERR_YPSERV]  = NSS_STATUS_UNAVAIL,
+  [YPERR_NODOM]   = NSS_STATUS_UNAVAIL,
+  [YPERR_BADDB]   = NSS_STATUS_UNAVAIL,
+  [YPERR_VERS]    = NSS_STATUS_UNAVAIL,
+  [YPERR_ACCESS]  = NSS_STATUS_UNAVAIL,
+  [YPERR_BUSY]    = NSS_STATUS_TRYAGAIN
+};
+const unsigned int __yperr2nss_count = (sizeof (__yperr2nss_tab)
+				        / sizeof (__yperr2nss_tab[0]));
diff --git a/REORG.TODO/nis/nss-nis.h b/REORG.TODO/nis/nss-nis.h
new file mode 100644
index 0000000000..3bb04991e7
--- /dev/null
+++ b/REORG.TODO/nis/nss-nis.h
@@ -0,0 +1,58 @@
+/* Copyright (C) 1996-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _NIS_NSS_NIS_H
+#define _NIS_NSS_NIS_H	1
+
+#include <rpcsvc/ypclnt.h>
+
+#include "nsswitch.h"
+
+
+/* Convert YP error number to NSS error number.  */
+extern const enum nss_status __yperr2nss_tab[] attribute_hidden;
+extern const unsigned int __yperr2nss_count attribute_hidden;
+
+static inline enum nss_status
+yperr2nss (int errval)
+{
+  if ((unsigned int) errval >= __yperr2nss_count)
+    return NSS_STATUS_UNAVAIL;
+  return __yperr2nss_tab[(unsigned int) errval];
+}
+
+
+struct response_t
+{
+  struct response_t *next;
+  size_t size;
+  char mem[0];
+};
+
+typedef struct intern_t
+{
+  struct response_t *start;
+  struct response_t *next;
+  size_t offset;
+} intern_t;
+
+
+extern int _nis_saveit (int instatus, char *inkey, int inkeylen, char *inval,
+			int invallen, char *indata) attribute_hidden;
+
+
+#endif /* nis/nss-nis.h */
diff --git a/REORG.TODO/nis/nss-nisplus.c b/REORG.TODO/nis/nss-nisplus.c
new file mode 100644
index 0000000000..9ff37d76ab
--- /dev/null
+++ b/REORG.TODO/nis/nss-nisplus.c
@@ -0,0 +1,78 @@
+/* Copyright (C) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <rpcsvc/nis.h>
+
+#include "nss-nisplus.h"
+#include "nsswitch.h"
+
+
+/* Convert NIS+ error number to NSS error number.  */
+const 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_NOTFOUND,
+  [NIS_CACHEEXPIRED] = NSS_STATUS_UNAVAIL,
+  [NIS_NAMEUNREACHABLE] = NSS_STATUS_UNAVAIL,
+  [NIS_UNKNOWNOBJ] = NSS_STATUS_NOTFOUND,
+  [NIS_TRYAGAIN] = NSS_STATUS_TRYAGAIN,
+  [NIS_SYSTEMERROR] = NSS_STATUS_UNAVAIL,
+  [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_UNAVAIL,
+  [NIS_DUMPLATER] = NSS_STATUS_UNAVAIL
+};
+const unsigned int __niserr2nss_count = (sizeof (__niserr2nss_tab)
+					 / sizeof (__niserr2nss_tab[0]));
diff --git a/REORG.TODO/nis/nss-nisplus.h b/REORG.TODO/nis/nss-nisplus.h
new file mode 100644
index 0000000000..8f16760ac2
--- /dev/null
+++ b/REORG.TODO/nis/nss-nisplus.h
@@ -0,0 +1,40 @@
+/* Copyright (C) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#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.  */
+extern const enum nss_status __niserr2nss_tab[] attribute_hidden;
+extern const unsigned int __niserr2nss_count attribute_hidden;
+
+static enum nss_status
+__attribute__ ((unused))
+niserr2nss (int errval)
+{
+  if ((unsigned int) errval >= __niserr2nss_count)
+    return NSS_STATUS_UNAVAIL;
+  return __niserr2nss_tab[(unsigned int) errval];
+}
+
+#endif /* nis/nss-nisplus.h */
diff --git a/REORG.TODO/nis/nss_compat/compat-grp.c b/REORG.TODO/nis/nss_compat/compat-grp.c
new file mode 100644
index 0000000000..0381458c0c
--- /dev/null
+++ b/REORG.TODO/nis/nss_compat/compat-grp.c
@@ -0,0 +1,683 @@
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <nss.h>
+#include <nsswitch.h>
+#include <stdio_ext.h>
+#include <string.h>
+#include <rpc/types.h>
+#include <libc-lock.h>
+#include <kernel-features.h>
+
+static service_user *ni;
+static enum nss_status (*nss_setgrent) (int stayopen);
+static enum nss_status (*nss_getgrnam_r) (const char *name,
+					  struct group * grp, char *buffer,
+					  size_t buflen, int *errnop);
+static enum nss_status (*nss_getgrgid_r) (gid_t gid, struct group * grp,
+					  char *buffer, size_t buflen,
+					  int *errnop);
+static enum nss_status (*nss_getgrent_r) (struct group * grp, char *buffer,
+					  size_t buflen, int *errnop);
+static enum nss_status (*nss_endgrent) (void);
+
+/* Get the declaration of the parser function.  */
+#define ENTNAME grent
+#define STRUCTURE group
+#define EXTERN_PARSER
+#include <nss/nss_files/files-parse.c>
+
+/* Structure for remembering -group members ... */
+#define BLACKLIST_INITIAL_SIZE 512
+#define BLACKLIST_INCREMENT 256
+struct blacklist_t
+{
+  char *data;
+  int current;
+  int size;
+};
+
+struct ent_t
+{
+  bool_t files;
+  enum nss_status setent_status;
+  FILE *stream;
+  struct blacklist_t blacklist;
+};
+typedef struct ent_t ent_t;
+
+static ent_t ext_ent = { TRUE, NSS_STATUS_SUCCESS, NULL, { NULL, 0, 0 }};
+
+/* Protect global state against multiple changers.  */
+__libc_lock_define_initialized (static, lock)
+
+/* Prototypes for local functions.  */
+static void blacklist_store_name (const char *, ent_t *);
+static int in_blacklist (const char *, int, ent_t *);
+
+/* Initialize the NSS interface/functions. The calling function must
+   hold the lock.  */
+static void
+init_nss_interface (void)
+{
+  if (__nss_database_lookup ("group_compat", NULL, "nis", &ni) >= 0)
+    {
+      nss_setgrent = __nss_lookup_function (ni, "setgrent");
+      nss_getgrnam_r = __nss_lookup_function (ni, "getgrnam_r");
+      nss_getgrgid_r = __nss_lookup_function (ni, "getgrgid_r");
+      nss_getgrent_r = __nss_lookup_function (ni, "getgrent_r");
+      nss_endgrent = __nss_lookup_function (ni, "endgrent");
+    }
+}
+
+static enum nss_status
+internal_setgrent (ent_t *ent, int stayopen, int needent)
+{
+  enum nss_status status = NSS_STATUS_SUCCESS;
+
+  ent->files = TRUE;
+
+  if (ent->blacklist.data != NULL)
+    {
+      ent->blacklist.current = 1;
+      ent->blacklist.data[0] = '|';
+      ent->blacklist.data[1] = '\0';
+    }
+  else
+    ent->blacklist.current = 0;
+
+  if (ent->stream == NULL)
+    {
+      ent->stream = fopen ("/etc/group", "rme");
+
+      if (ent->stream == NULL)
+	status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
+      else
+	/* We take care of locking ourself.  */
+	__fsetlocking (ent->stream, FSETLOCKING_BYCALLER);
+    }
+  else
+    rewind (ent->stream);
+
+  if (needent && status == NSS_STATUS_SUCCESS && nss_setgrent)
+    ent->setent_status = nss_setgrent (stayopen);
+
+  return status;
+}
+
+
+enum nss_status
+_nss_compat_setgrent (int stayopen)
+{
+  enum nss_status result;
+
+  __libc_lock_lock (lock);
+
+  if (ni == NULL)
+    init_nss_interface ();
+
+  result = internal_setgrent (&ext_ent, stayopen, 1);
+
+  __libc_lock_unlock (lock);
+
+  return result;
+}
+
+
+static enum nss_status
+internal_endgrent (ent_t *ent)
+{
+  if (ent->stream != NULL)
+    {
+      fclose (ent->stream);
+      ent->stream = NULL;
+    }
+
+  if (ent->blacklist.data != NULL)
+    {
+      ent->blacklist.current = 1;
+      ent->blacklist.data[0] = '|';
+      ent->blacklist.data[1] = '\0';
+    }
+  else
+    ent->blacklist.current = 0;
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_compat_endgrent (void)
+{
+  enum nss_status result;
+
+  __libc_lock_lock (lock);
+
+  if (nss_endgrent)
+    nss_endgrent ();
+
+  result = internal_endgrent (&ext_ent);
+
+  __libc_lock_unlock (lock);
+
+  return result;
+}
+
+/* get the next group from NSS  (+ entry) */
+static enum nss_status
+getgrent_next_nss (struct group *result, ent_t *ent, char *buffer,
+		   size_t buflen, int *errnop)
+{
+  if (!nss_getgrent_r)
+    return NSS_STATUS_UNAVAIL;
+
+  /* If the setgrent call failed, say so.  */
+  if (ent->setent_status != NSS_STATUS_SUCCESS)
+    return ent->setent_status;
+
+  do
+    {
+      enum nss_status status;
+
+      if ((status = nss_getgrent_r (result, buffer, buflen, errnop)) !=
+	  NSS_STATUS_SUCCESS)
+	return status;
+    }
+  while (in_blacklist (result->gr_name, strlen (result->gr_name), ent));
+
+  return NSS_STATUS_SUCCESS;
+}
+
+/* This function handle the +group entrys in /etc/group */
+static enum nss_status
+getgrnam_plusgroup (const char *name, struct group *result, ent_t *ent,
+		    char *buffer, size_t buflen, int *errnop)
+{
+  if (!nss_getgrnam_r)
+    return NSS_STATUS_UNAVAIL;
+
+  enum nss_status status = nss_getgrnam_r (name, result, buffer, buflen,
+					   errnop);
+  if (status != NSS_STATUS_SUCCESS)
+    return status;
+
+  if (in_blacklist (result->gr_name, strlen (result->gr_name), ent))
+    return NSS_STATUS_NOTFOUND;
+
+  /* We found the entry.  */
+  return NSS_STATUS_SUCCESS;
+}
+
+static enum nss_status
+getgrent_next_file (struct group *result, ent_t *ent,
+		    char *buffer, size_t buflen, int *errnop)
+{
+  struct parser_data *data = (void *) buffer;
+  while (1)
+    {
+      fpos_t pos;
+      int parse_res = 0;
+      char *p;
+
+      do
+	{
+	  /* We need at least 3 characters for one line.  */
+	  if (__glibc_unlikely (buflen < 3))
+	    {
+	    erange:
+	      *errnop = ERANGE;
+	      return NSS_STATUS_TRYAGAIN;
+	    }
+
+	  fgetpos (ent->stream, &pos);
+	  buffer[buflen - 1] = '\xff';
+	  p = fgets_unlocked (buffer, buflen, ent->stream);
+	  if (p == NULL && feof_unlocked (ent->stream))
+	    return NSS_STATUS_NOTFOUND;
+
+	  if (p == NULL || __builtin_expect (buffer[buflen - 1] != '\xff', 0))
+	    {
+	    erange_reset:
+	      fsetpos (ent->stream, &pos);
+	      goto erange;
+	    }
+
+	  /* Terminate the line for any case.  */
+	  buffer[buflen - 1] = '\0';
+
+	  /* Skip leading blanks.  */
+	  while (isspace (*p))
+	    ++p;
+	}
+      while (*p == '\0' || *p == '#' ||	/* Ignore empty and comment lines. */
+	     /* Parse the line.  If it is invalid, loop to
+	        get the next line of the file to parse.  */
+	     !(parse_res = _nss_files_parse_grent (p, result, data, buflen,
+						   errnop)));
+
+      if (__glibc_unlikely (parse_res == -1))
+	/* The parser ran out of space.  */
+	goto erange_reset;
+
+      if (result->gr_name[0] != '+' && result->gr_name[0] != '-')
+	/* This is a real entry.  */
+	break;
+
+      /* -group */
+      if (result->gr_name[0] == '-' && result->gr_name[1] != '\0'
+	  && result->gr_name[1] != '@')
+	{
+	  blacklist_store_name (&result->gr_name[1], ent);
+	  continue;
+	}
+
+      /* +group */
+      if (result->gr_name[0] == '+' && result->gr_name[1] != '\0'
+	  && result->gr_name[1] != '@')
+	{
+	  size_t len = strlen (result->gr_name);
+	  char buf[len];
+	  enum nss_status status;
+
+	  /* Store the group in the blacklist for the "+" at the end of
+	     /etc/group */
+	  memcpy (buf, &result->gr_name[1], len);
+	  status = getgrnam_plusgroup (&result->gr_name[1], result, ent,
+				       buffer, buflen, errnop);
+	  blacklist_store_name (buf, ent);
+	  if (status == NSS_STATUS_SUCCESS)	/* We found the entry. */
+	    break;
+	  else if (status == NSS_STATUS_RETURN /* We couldn't parse the entry*/
+		   || status == NSS_STATUS_NOTFOUND)	/* No group in NIS */
+	    continue;
+	  else
+	    {
+	      if (status == NSS_STATUS_TRYAGAIN)
+		/* The parser ran out of space.  */
+		goto erange_reset;
+
+	      return status;
+	    }
+	}
+
+      /* +:... */
+      if (result->gr_name[0] == '+' && result->gr_name[1] == '\0')
+	{
+	  ent->files = FALSE;
+
+	  return getgrent_next_nss (result, ent, buffer, buflen, errnop);
+	}
+    }
+
+  return NSS_STATUS_SUCCESS;
+}
+
+
+enum nss_status
+_nss_compat_getgrent_r (struct group *grp, char *buffer, size_t buflen,
+			int *errnop)
+{
+  enum nss_status result = NSS_STATUS_SUCCESS;
+
+  __libc_lock_lock (lock);
+
+  /* Be prepared that the setgrent function was not called before.  */
+  if (ni == NULL)
+    init_nss_interface ();
+
+  if (ext_ent.stream == NULL)
+    result = internal_setgrent (&ext_ent, 1, 1);
+
+  if (result == NSS_STATUS_SUCCESS)
+    {
+      if (ext_ent.files)
+	result = getgrent_next_file (grp, &ext_ent, buffer, buflen, errnop);
+      else
+	result = getgrent_next_nss (grp, &ext_ent, buffer, buflen, errnop);
+    }
+  __libc_lock_unlock (lock);
+
+  return result;
+}
+
+/* Searches in /etc/group and the NIS/NIS+ map for a special group */
+static enum nss_status
+internal_getgrnam_r (const char *name, struct group *result, ent_t *ent,
+		     char *buffer, size_t buflen, int *errnop)
+{
+  struct parser_data *data = (void *) buffer;
+  while (1)
+    {
+      fpos_t pos;
+      int parse_res = 0;
+      char *p;
+
+      do
+	{
+	  /* We need at least 3 characters for one line.  */
+	  if (__glibc_unlikely (buflen < 3))
+	    {
+	    erange:
+	      *errnop = ERANGE;
+	      return NSS_STATUS_TRYAGAIN;
+	    }
+
+	  fgetpos (ent->stream, &pos);
+	  buffer[buflen - 1] = '\xff';
+	  p = fgets_unlocked (buffer, buflen, ent->stream);
+	  if (p == NULL && feof_unlocked (ent->stream))
+	    return NSS_STATUS_NOTFOUND;
+
+	  if (p == NULL || __builtin_expect (buffer[buflen - 1] != '\xff', 0))
+	    {
+	    erange_reset:
+	      fsetpos (ent->stream, &pos);
+	      goto erange;
+	    }
+
+	  /* Terminate the line for any case.  */
+	  buffer[buflen - 1] = '\0';
+
+	  /* Skip leading blanks.  */
+	  while (isspace (*p))
+	    ++p;
+	}
+      while (*p == '\0' || *p == '#' ||	/* Ignore empty and comment lines. */
+	     /* Parse the line.  If it is invalid, loop to
+	        get the next line of the file to parse.  */
+	     !(parse_res = _nss_files_parse_grent (p, result, data, buflen,
+						   errnop)));
+
+      if (__glibc_unlikely (parse_res == -1))
+	/* The parser ran out of space.  */
+	goto erange_reset;
+
+      /* This is a real entry.  */
+      if (result->gr_name[0] != '+' && result->gr_name[0] != '-')
+	{
+	  if (strcmp (result->gr_name, name) == 0)
+	    return NSS_STATUS_SUCCESS;
+	  else
+	    continue;
+	}
+
+      /* -group */
+      if (result->gr_name[0] == '-' && result->gr_name[1] != '\0')
+	{
+	  if (strcmp (&result->gr_name[1], name) == 0)
+	    return NSS_STATUS_NOTFOUND;
+	  else
+	    continue;
+	}
+
+      /* +group */
+      if (result->gr_name[0] == '+' && result->gr_name[1] != '\0')
+	{
+	  if (strcmp (name, &result->gr_name[1]) == 0)
+	    {
+	      enum nss_status status;
+
+	      status = getgrnam_plusgroup (name, result, ent,
+					   buffer, buflen, errnop);
+	      if (status == NSS_STATUS_RETURN)
+		/* We couldn't parse the entry */
+		continue;
+	      else
+		return status;
+	    }
+	}
+      /* +:... */
+      if (result->gr_name[0] == '+' && result->gr_name[1] == '\0')
+	{
+	  enum nss_status status;
+
+	  status = getgrnam_plusgroup (name, result, ent,
+				       buffer, buflen, errnop);
+	  if (status == NSS_STATUS_RETURN)
+	    /* We couldn't parse the entry */
+	    continue;
+	  else
+	    return status;
+	}
+    }
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_compat_getgrnam_r (const char *name, struct group *grp,
+			char *buffer, size_t buflen, int *errnop)
+{
+  ent_t ent = { TRUE, NSS_STATUS_SUCCESS, NULL, { NULL, 0, 0 }};
+  enum nss_status result;
+
+  if (name[0] == '-' || name[0] == '+')
+    return NSS_STATUS_NOTFOUND;
+
+  __libc_lock_lock (lock);
+
+  if (ni == NULL)
+    init_nss_interface ();
+
+  __libc_lock_unlock (lock);
+
+  result = internal_setgrent (&ent, 0, 0);
+
+  if (result == NSS_STATUS_SUCCESS)
+    result = internal_getgrnam_r (name, grp, &ent, buffer, buflen, errnop);
+
+  internal_endgrent (&ent);
+
+  return result;
+}
+
+/* Searches in /etc/group and the NIS/NIS+ map for a special group id */
+static enum nss_status
+internal_getgrgid_r (gid_t gid, struct group *result, ent_t *ent,
+		     char *buffer, size_t buflen, int *errnop)
+{
+  struct parser_data *data = (void *) buffer;
+  while (1)
+    {
+      fpos_t pos;
+      int parse_res = 0;
+      char *p;
+
+      do
+	{
+	  /* We need at least 3 characters for one line.  */
+	  if (__glibc_unlikely (buflen < 3))
+	    {
+	    erange:
+	      *errnop = ERANGE;
+	      return NSS_STATUS_TRYAGAIN;
+	    }
+
+	  fgetpos (ent->stream, &pos);
+	  buffer[buflen - 1] = '\xff';
+	  p = fgets_unlocked (buffer, buflen, ent->stream);
+	  if (p == NULL && feof_unlocked (ent->stream))
+	    return NSS_STATUS_NOTFOUND;
+
+	  if (p == NULL || __builtin_expect (buffer[buflen - 1] != '\xff', 0))
+	    {
+	    erange_reset:
+	      fsetpos (ent->stream, &pos);
+	      goto erange;
+	    }
+
+	  /* Terminate the line for any case.  */
+	  buffer[buflen - 1] = '\0';
+
+	  /* Skip leading blanks.  */
+	  while (isspace (*p))
+	    ++p;
+	}
+      while (*p == '\0' || *p == '#' ||	/* Ignore empty and comment lines. */
+	     /* Parse the line.  If it is invalid, loop to
+	        get the next line of the file to parse.  */
+	     !(parse_res = _nss_files_parse_grent (p, result, data, buflen,
+						   errnop)));
+
+      if (__glibc_unlikely (parse_res == -1))
+	/* The parser ran out of space.  */
+	goto erange_reset;
+
+      /* This is a real entry.  */
+      if (result->gr_name[0] != '+' && result->gr_name[0] != '-')
+	{
+	  if (result->gr_gid == gid)
+	    return NSS_STATUS_SUCCESS;
+	  else
+	    continue;
+	}
+
+      /* -group */
+      if (result->gr_name[0] == '-' && result->gr_name[1] != '\0')
+	{
+	  blacklist_store_name (&result->gr_name[1], ent);
+	  continue;
+	}
+
+      /* +group */
+      if (result->gr_name[0] == '+' && result->gr_name[1] != '\0')
+	{
+	  /* Yes, no +1, see the memcpy call below.  */
+	  size_t len = strlen (result->gr_name);
+	  char buf[len];
+	  enum nss_status status;
+
+	  /* Store the group in the blacklist for the "+" at the end of
+	     /etc/group */
+	  memcpy (buf, &result->gr_name[1], len);
+	  status = getgrnam_plusgroup (&result->gr_name[1], result, ent,
+				       buffer, buflen, errnop);
+	  blacklist_store_name (buf, ent);
+	  if (status == NSS_STATUS_SUCCESS && result->gr_gid == gid)
+	    break;
+	  else
+	    continue;
+	}
+      /* +:... */
+      if (result->gr_name[0] == '+' && result->gr_name[1] == '\0')
+	{
+	  if (!nss_getgrgid_r)
+	    return NSS_STATUS_UNAVAIL;
+
+	  enum nss_status status = nss_getgrgid_r (gid, result, buffer, buflen,
+						   errnop);
+	  if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */
+	    return NSS_STATUS_NOTFOUND;
+	  else
+	    return status;
+	}
+    }
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_compat_getgrgid_r (gid_t gid, struct group *grp,
+			char *buffer, size_t buflen, int *errnop)
+{
+  ent_t ent = { TRUE, NSS_STATUS_SUCCESS, NULL, { NULL, 0, 0 }};
+  enum nss_status result;
+
+  __libc_lock_lock (lock);
+
+  if (ni == NULL)
+    init_nss_interface ();
+
+  __libc_lock_unlock (lock);
+
+  result = internal_setgrent (&ent, 0, 0);
+
+  if (result == NSS_STATUS_SUCCESS)
+    result = internal_getgrgid_r (gid, grp, &ent, buffer, buflen, errnop);
+
+  internal_endgrent (&ent);
+
+  return result;
+}
+
+
+/* Support routines for remembering -@netgroup and -user entries.
+   The names are stored in a single string with `|' as separator. */
+static void
+blacklist_store_name (const char *name, ent_t *ent)
+{
+  int namelen = strlen (name);
+  char *tmp;
+
+  /* first call, setup cache */
+  if (ent->blacklist.size == 0)
+    {
+      ent->blacklist.size = MAX (BLACKLIST_INITIAL_SIZE, 2 * namelen);
+      ent->blacklist.data = malloc (ent->blacklist.size);
+      if (ent->blacklist.data == NULL)
+	return;
+      ent->blacklist.data[0] = '|';
+      ent->blacklist.data[1] = '\0';
+      ent->blacklist.current = 1;
+    }
+  else
+    {
+      if (in_blacklist (name, namelen, ent))
+	return;			/* no duplicates */
+
+      if (ent->blacklist.current + namelen + 1 >= ent->blacklist.size)
+	{
+	  ent->blacklist.size += MAX (BLACKLIST_INCREMENT, 2 * namelen);
+	  tmp = realloc (ent->blacklist.data, ent->blacklist.size);
+	  if (tmp == NULL)
+	    {
+	      free (ent->blacklist.data);
+	      ent->blacklist.size = 0;
+	      return;
+	    }
+	  ent->blacklist.data = tmp;
+	}
+    }
+
+  tmp = stpcpy (ent->blacklist.data + ent->blacklist.current, name);
+  *tmp++ = '|';
+  *tmp = '\0';
+  ent->blacklist.current += namelen + 1;
+
+  return;
+}
+
+/* returns TRUE if ent->blacklist contains name, else FALSE */
+static bool_t
+in_blacklist (const char *name, int namelen, ent_t *ent)
+{
+  char buf[namelen + 3];
+  char *cp;
+
+  if (ent->blacklist.data == NULL)
+    return FALSE;
+
+  buf[0] = '|';
+  cp = stpcpy (&buf[1], name);
+  *cp++ = '|';
+  *cp = '\0';
+  return strstr (ent->blacklist.data, buf) != NULL;
+}
diff --git a/REORG.TODO/nis/nss_compat/compat-initgroups.c b/REORG.TODO/nis/nss_compat/compat-initgroups.c
new file mode 100644
index 0000000000..795213448c
--- /dev/null
+++ b/REORG.TODO/nis/nss_compat/compat-initgroups.c
@@ -0,0 +1,576 @@
+/* Copyright (C) 1998-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <nss.h>
+#include <stdio_ext.h>
+#include <string.h>
+#include <unistd.h>
+#include <rpc/types.h>
+#include <sys/param.h>
+#include <nsswitch.h>
+#include <libc-lock.h>
+#include <kernel-features.h>
+#include <scratch_buffer.h>
+
+static service_user *ni;
+/* Type of the lookup function.  */
+static enum nss_status (*nss_initgroups_dyn) (const char *, gid_t,
+					      long int *, long int *,
+					      gid_t **, long int, int *);
+static enum nss_status (*nss_getgrnam_r) (const char *name,
+					  struct group * grp, char *buffer,
+					  size_t buflen, int *errnop);
+static enum nss_status (*nss_getgrgid_r) (gid_t gid, struct group * grp,
+					  char *buffer, size_t buflen,
+					  int *errnop);
+static enum nss_status (*nss_setgrent) (int stayopen);
+static enum nss_status (*nss_getgrent_r) (struct group * grp, char *buffer,
+					  size_t buflen, int *errnop);
+static enum nss_status (*nss_endgrent) (void);
+
+/* Protect global state against multiple changers.  */
+__libc_lock_define_initialized (static, lock)
+
+
+/* Get the declaration of the parser function.  */
+#define ENTNAME grent
+#define STRUCTURE group
+#define EXTERN_PARSER
+#include <nss/nss_files/files-parse.c>
+
+/* Structure for remembering -group members ... */
+#define BLACKLIST_INITIAL_SIZE 512
+#define BLACKLIST_INCREMENT 256
+struct blacklist_t
+{
+  char *data;
+  int current;
+  int size;
+};
+
+struct ent_t
+{
+  bool files;
+  bool need_endgrent;
+  bool skip_initgroups_dyn;
+  FILE *stream;
+  struct blacklist_t blacklist;
+};
+typedef struct ent_t ent_t;
+
+/* Prototypes for local functions.  */
+static void blacklist_store_name (const char *, ent_t *);
+static int in_blacklist (const char *, int, ent_t *);
+
+/* Initialize the NSS interface/functions. The calling function must
+   hold the lock.  */
+static void
+init_nss_interface (void)
+{
+  __libc_lock_lock (lock);
+
+  /* Retest.  */
+  if (ni == NULL
+      && __nss_database_lookup ("group_compat", NULL, "nis", &ni) >= 0)
+    {
+      nss_initgroups_dyn = __nss_lookup_function (ni, "initgroups_dyn");
+      nss_getgrnam_r = __nss_lookup_function (ni, "getgrnam_r");
+      nss_getgrgid_r = __nss_lookup_function (ni, "getgrgid_r");
+      nss_setgrent = __nss_lookup_function (ni, "setgrent");
+      nss_getgrent_r = __nss_lookup_function (ni, "getgrent_r");
+      nss_endgrent = __nss_lookup_function (ni, "endgrent");
+    }
+
+  __libc_lock_unlock (lock);
+}
+
+static enum nss_status
+internal_setgrent (ent_t *ent)
+{
+  enum nss_status status = NSS_STATUS_SUCCESS;
+
+  ent->files = true;
+
+  if (ni == NULL)
+    init_nss_interface ();
+
+  if (ent->blacklist.data != NULL)
+    {
+      ent->blacklist.current = 1;
+      ent->blacklist.data[0] = '|';
+      ent->blacklist.data[1] = '\0';
+    }
+  else
+    ent->blacklist.current = 0;
+
+  ent->stream = fopen ("/etc/group", "rme");
+
+  if (ent->stream == NULL)
+    status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
+  else
+    /* We take care of locking ourself.  */
+    __fsetlocking (ent->stream, FSETLOCKING_BYCALLER);
+
+  return status;
+}
+
+
+static enum nss_status
+internal_endgrent (ent_t *ent)
+{
+  if (ent->stream != NULL)
+    {
+      fclose (ent->stream);
+      ent->stream = NULL;
+    }
+
+  if (ent->blacklist.data != NULL)
+    {
+      ent->blacklist.current = 1;
+      ent->blacklist.data[0] = '|';
+      ent->blacklist.data[1] = '\0';
+    }
+  else
+    ent->blacklist.current = 0;
+
+  if (ent->need_endgrent && nss_endgrent != NULL)
+    nss_endgrent ();
+
+  return NSS_STATUS_SUCCESS;
+}
+
+/* Add new group record.  */
+static void
+add_group (long int *start, long int *size, gid_t **groupsp, long int limit,
+	   gid_t gid)
+{
+  gid_t *groups = *groupsp;
+
+  /* Matches user.  Insert this group.  */
+  if (__glibc_unlikely (*start == *size))
+    {
+      /* Need a bigger buffer.  */
+      gid_t *newgroups;
+      long int newsize;
+
+      if (limit > 0 && *size == limit)
+	/* We reached the maximum.  */
+	return;
+
+      if (limit <= 0)
+	newsize = 2 * *size;
+      else
+	newsize = MIN (limit, 2 * *size);
+
+      newgroups = realloc (groups, newsize * sizeof (*groups));
+      if (newgroups == NULL)
+	return;
+      *groupsp = groups = newgroups;
+      *size = newsize;
+    }
+
+  groups[*start] = gid;
+  *start += 1;
+}
+
+/* This function checks, if the user is a member of this group and if
+   yes, add the group id to the list.  Return nonzero is we couldn't
+   handle the group because the user is not in the member list.  */
+static int
+check_and_add_group (const char *user, gid_t group, long int *start,
+		     long int *size, gid_t **groupsp, long int limit,
+		     struct group *grp)
+{
+  char **member;
+
+  /* Don't add main group to list of groups.  */
+  if (grp->gr_gid == group)
+    return 0;
+
+  for (member = grp->gr_mem; *member != NULL; ++member)
+    if (strcmp (*member, user) == 0)
+      {
+	add_group (start, size, groupsp, limit, grp->gr_gid);
+	return 0;
+      }
+
+  return 1;
+}
+
+/* Get the next group from NSS  (+ entry). If the NSS module supports
+   initgroups_dyn, get all entries at once.  */
+static enum nss_status
+getgrent_next_nss (ent_t *ent, char *buffer, size_t buflen, const char *user,
+		   gid_t group, long int *start, long int *size,
+		   gid_t **groupsp, long int limit, int *errnop)
+{
+  enum nss_status status;
+  struct group grpbuf;
+
+  /* Try nss_initgroups_dyn if supported. We also need getgrgid_r.
+     If this function is not supported, step through the whole group
+     database with getgrent_r.  */
+  if (! ent->skip_initgroups_dyn)
+    {
+      long int mystart = 0;
+      long int mysize = limit <= 0 ? *size : limit;
+      gid_t *mygroups = malloc (mysize * sizeof (gid_t));
+
+      if (mygroups == NULL)
+	return NSS_STATUS_TRYAGAIN;
+
+      /* For every gid in the list we get from the NSS module,
+	 get the whole group entry. We need to do this, since we
+	 need the group name to check if it is in the blacklist.
+	 In worst case, this is as twice as slow as stepping with
+	 getgrent_r through the whole group database. But for large
+	 group databases this is faster, since the user can only be
+	 in a limited number of groups.  */
+      if (nss_initgroups_dyn (user, group, &mystart, &mysize, &mygroups,
+			      limit, errnop) == NSS_STATUS_SUCCESS)
+	{
+	  status = NSS_STATUS_NOTFOUND;
+
+	  /* If there is no blacklist we can trust the underlying
+	     initgroups implementation.  */
+	  if (ent->blacklist.current <= 1)
+	    for (int i = 0; i < mystart; i++)
+	      add_group (start, size, groupsp, limit, mygroups[i]);
+	  else
+	    {
+	      /* A temporary buffer. We use the normal buffer, until we find
+		 an entry, for which this buffer is to small.  In this case, we
+		 overwrite the pointer with one to a bigger buffer.  */
+	      char *tmpbuf = buffer;
+	      size_t tmplen = buflen;
+	      bool use_malloc = false;
+
+	      for (int i = 0; i < mystart; i++)
+		{
+		  while ((status = nss_getgrgid_r (mygroups[i], &grpbuf,
+						   tmpbuf, tmplen, errnop))
+			 == NSS_STATUS_TRYAGAIN
+			 && *errnop == ERANGE)
+                    {
+                      if (__libc_use_alloca (tmplen * 2))
+                        {
+                          if (tmpbuf == buffer)
+                            {
+                              tmplen *= 2;
+                              tmpbuf = __alloca (tmplen);
+                            }
+                          else
+                            tmpbuf = extend_alloca (tmpbuf, tmplen, tmplen * 2);
+                        }
+                      else
+                        {
+                          tmplen *= 2;
+                          char *newbuf = realloc (use_malloc ? tmpbuf : NULL, tmplen);
+
+                          if (newbuf == NULL)
+                            {
+                              status = NSS_STATUS_TRYAGAIN;
+			      goto done;
+                            }
+                          use_malloc = true;
+                          tmpbuf = newbuf;
+                        }
+                    }
+
+		  if (__builtin_expect  (status != NSS_STATUS_NOTFOUND, 1))
+		    {
+		      if (__builtin_expect  (status != NSS_STATUS_SUCCESS, 0))
+		        goto done;
+
+		      if (!in_blacklist (grpbuf.gr_name,
+					 strlen (grpbuf.gr_name), ent)
+			  && check_and_add_group (user, group, start, size,
+						  groupsp, limit, &grpbuf))
+			{
+			  if (nss_setgrent != NULL)
+			    {
+			      nss_setgrent (1);
+			      ent->need_endgrent = true;
+			    }
+			  ent->skip_initgroups_dyn = true;
+
+			  goto iter;
+			}
+		    }
+		}
+
+	      status = NSS_STATUS_NOTFOUND;
+
+ done:
+	      if (use_malloc)
+	        free (tmpbuf);
+	    }
+
+	  free (mygroups);
+
+	  return status;
+	}
+
+      free (mygroups);
+    }
+
+  /* If we come here, the NSS module does not support initgroups_dyn
+     or we were confronted with a split group.  In these cases we have
+     to step through the whole list ourself.  */
+ iter:
+  do
+    {
+      if ((status = nss_getgrent_r (&grpbuf, buffer, buflen, errnop)) !=
+	  NSS_STATUS_SUCCESS)
+	break;
+    }
+  while (in_blacklist (grpbuf.gr_name, strlen (grpbuf.gr_name), ent));
+
+  if (status == NSS_STATUS_SUCCESS)
+    check_and_add_group (user, group, start, size, groupsp, limit, &grpbuf);
+
+  return status;
+}
+
+static enum nss_status
+internal_getgrent_r (ent_t *ent, char *buffer, size_t buflen, const char *user,
+		     gid_t group, long int *start, long int *size,
+		     gid_t **groupsp, long int limit, int *errnop)
+{
+  struct parser_data *data = (void *) buffer;
+  struct group grpbuf;
+
+  if (!ent->files)
+    return getgrent_next_nss (ent, buffer, buflen, user, group,
+			      start, size, groupsp, limit, errnop);
+
+  while (1)
+    {
+      fpos_t pos;
+      int parse_res = 0;
+      char *p;
+
+      do
+	{
+	  /* We need at least 3 characters for one line.  */
+	  if (__glibc_unlikely (buflen < 3))
+	    {
+	    erange:
+	      *errnop = ERANGE;
+	      return NSS_STATUS_TRYAGAIN;
+	    }
+
+	  fgetpos (ent->stream, &pos);
+	  buffer[buflen - 1] = '\xff';
+	  p = fgets_unlocked (buffer, buflen, ent->stream);
+	  if (p == NULL && feof_unlocked (ent->stream))
+	    return NSS_STATUS_NOTFOUND;
+
+	  if (p == NULL || __builtin_expect (buffer[buflen - 1] != '\xff', 0))
+	    {
+	    erange_reset:
+	      fsetpos (ent->stream, &pos);
+	      goto erange;
+	    }
+
+	  /* Terminate the line for any case.  */
+	  buffer[buflen - 1] = '\0';
+
+	  /* Skip leading blanks.  */
+	  while (isspace (*p))
+	    ++p;
+	}
+      while (*p == '\0' || *p == '#' ||	/* Ignore empty and comment lines. */
+	     /* Parse the line.  If it is invalid, loop to
+		get the next line of the file to parse.  */
+	     !(parse_res = _nss_files_parse_grent (p, &grpbuf, data, buflen,
+						   errnop)));
+
+      if (__glibc_unlikely (parse_res == -1))
+	/* The parser ran out of space.  */
+	goto erange_reset;
+
+      if (grpbuf.gr_name[0] != '+' && grpbuf.gr_name[0] != '-')
+	/* This is a real entry.  */
+	break;
+
+      /* -group */
+      if (grpbuf.gr_name[0] == '-' && grpbuf.gr_name[1] != '\0'
+	  && grpbuf.gr_name[1] != '@')
+	{
+	  blacklist_store_name (&grpbuf.gr_name[1], ent);
+	  continue;
+	}
+
+      /* +group */
+      if (grpbuf.gr_name[0] == '+' && grpbuf.gr_name[1] != '\0'
+	  && grpbuf.gr_name[1] != '@')
+	{
+	  if (in_blacklist (&grpbuf.gr_name[1],
+			    strlen (&grpbuf.gr_name[1]), ent))
+	    continue;
+	  /* Store the group in the blacklist for the "+" at the end of
+	     /etc/group */
+	  blacklist_store_name (&grpbuf.gr_name[1], ent);
+	  if (nss_getgrnam_r == NULL)
+	    return NSS_STATUS_UNAVAIL;
+	  else if (nss_getgrnam_r (&grpbuf.gr_name[1], &grpbuf, buffer,
+				   buflen, errnop) != NSS_STATUS_SUCCESS)
+	    continue;
+
+	  check_and_add_group (user, group, start, size, groupsp,
+			       limit, &grpbuf);
+
+	  return NSS_STATUS_SUCCESS;
+	}
+
+      /* +:... */
+      if (grpbuf.gr_name[0] == '+' && grpbuf.gr_name[1] == '\0')
+	{
+	  /* If the selected module does not support getgrent_r or
+	     initgroups_dyn, abort. We cannot find the needed group
+	     entries.  */
+	  if (nss_initgroups_dyn == NULL || nss_getgrgid_r == NULL)
+	    {
+	      if (nss_setgrent != NULL)
+		{
+		  nss_setgrent (1);
+		  ent->need_endgrent = true;
+		}
+	      ent->skip_initgroups_dyn = true;
+
+	      if (nss_getgrent_r == NULL)
+		return NSS_STATUS_UNAVAIL;
+	    }
+
+	  ent->files = false;
+
+	  return getgrent_next_nss (ent, buffer, buflen, user, group,
+				    start, size, groupsp, limit, errnop);
+	}
+    }
+
+  check_and_add_group (user, group, start, size, groupsp, limit, &grpbuf);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+
+enum nss_status
+_nss_compat_initgroups_dyn (const char *user, gid_t group, long int *start,
+			    long int *size, gid_t **groupsp, long int limit,
+			    int *errnop)
+{
+  enum nss_status status;
+  ent_t intern = { true, false, false, NULL, {NULL, 0, 0} };
+
+  status = internal_setgrent (&intern);
+  if (status != NSS_STATUS_SUCCESS)
+    return status;
+
+  struct scratch_buffer tmpbuf;
+  scratch_buffer_init (&tmpbuf);
+
+  do
+    {
+      while ((status = internal_getgrent_r (&intern, tmpbuf.data, tmpbuf.length,
+					    user, group, start, size,
+					    groupsp, limit, errnop))
+	     == NSS_STATUS_TRYAGAIN && *errnop == ERANGE)
+        if (!scratch_buffer_grow (&tmpbuf))
+	    goto done;
+    }
+  while (status == NSS_STATUS_SUCCESS);
+
+  status = NSS_STATUS_SUCCESS;
+
+ done:
+  scratch_buffer_free (&tmpbuf);
+
+  internal_endgrent (&intern);
+
+  return status;
+}
+
+
+/* Support routines for remembering -@netgroup and -user entries.
+   The names are stored in a single string with `|' as separator. */
+static void
+blacklist_store_name (const char *name, ent_t *ent)
+{
+  int namelen = strlen (name);
+  char *tmp;
+
+  /* First call, setup cache.  */
+  if (ent->blacklist.size == 0)
+    {
+      ent->blacklist.size = MAX (BLACKLIST_INITIAL_SIZE, 2 * namelen);
+      ent->blacklist.data = malloc (ent->blacklist.size);
+      if (ent->blacklist.data == NULL)
+	return;
+      ent->blacklist.data[0] = '|';
+      ent->blacklist.data[1] = '\0';
+      ent->blacklist.current = 1;
+    }
+  else
+    {
+      if (in_blacklist (name, namelen, ent))
+	return;			/* no duplicates */
+
+      if (ent->blacklist.current + namelen + 1 >= ent->blacklist.size)
+	{
+	  ent->blacklist.size += MAX (BLACKLIST_INCREMENT, 2 * namelen);
+	  tmp = realloc (ent->blacklist.data, ent->blacklist.size);
+	  if (tmp == NULL)
+	    {
+	      free (ent->blacklist.data);
+	      ent->blacklist.size = 0;
+	      return;
+	    }
+	  ent->blacklist.data = tmp;
+	}
+    }
+
+  tmp = stpcpy (ent->blacklist.data + ent->blacklist.current, name);
+  *tmp++ = '|';
+  *tmp = '\0';
+  ent->blacklist.current += namelen + 1;
+
+  return;
+}
+
+/* returns TRUE if ent->blacklist contains name, else FALSE */
+static bool_t
+in_blacklist (const char *name, int namelen, ent_t *ent)
+{
+  char buf[namelen + 3];
+  char *cp;
+
+  if (ent->blacklist.data == NULL)
+    return FALSE;
+
+  buf[0] = '|';
+  cp = stpcpy (&buf[1], name);
+  *cp++ = '|';
+  *cp = '\0';
+  return strstr (ent->blacklist.data, buf) != NULL;
+}
diff --git a/REORG.TODO/nis/nss_compat/compat-pwd.c b/REORG.TODO/nis/nss_compat/compat-pwd.c
new file mode 100644
index 0000000000..0583a10b84
--- /dev/null
+++ b/REORG.TODO/nis/nss_compat/compat-pwd.c
@@ -0,0 +1,1132 @@
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <nss.h>
+#include <nsswitch.h>
+#include <pwd.h>
+#include <stdio_ext.h>
+#include <string.h>
+#include <rpc/types.h>
+#include <rpcsvc/ypclnt.h>
+#include <libc-lock.h>
+#include <kernel-features.h>
+
+#include "netgroup.h"
+
+static service_user *ni;
+static enum nss_status (*nss_setpwent) (int stayopen);
+static enum nss_status (*nss_getpwnam_r) (const char *name,
+					  struct passwd * pwd, char *buffer,
+					  size_t buflen, int *errnop);
+static enum nss_status (*nss_getpwuid_r) (uid_t uid, struct passwd * pwd,
+					  char *buffer, size_t buflen,
+					  int *errnop);
+static enum nss_status (*nss_getpwent_r) (struct passwd * pwd, char *buffer,
+					  size_t buflen, int *errnop);
+static enum nss_status (*nss_endpwent) (void);
+
+/* Get the declaration of the parser function.  */
+#define ENTNAME pwent
+#define STRUCTURE passwd
+#define EXTERN_PARSER
+#include <nss/nss_files/files-parse.c>
+
+/* Structure for remembering -@netgroup and -user members ... */
+#define BLACKLIST_INITIAL_SIZE 512
+#define BLACKLIST_INCREMENT 256
+struct blacklist_t
+{
+  char *data;
+  int current;
+  int size;
+};
+
+struct ent_t
+{
+  bool netgroup;
+  bool first;
+  bool files;
+  enum nss_status setent_status;
+  FILE *stream;
+  struct blacklist_t blacklist;
+  struct passwd pwd;
+  struct __netgrent netgrdata;
+};
+typedef struct ent_t ent_t;
+
+static ent_t ext_ent = { false, false, true, NSS_STATUS_SUCCESS, NULL,
+			 { NULL, 0, 0 },
+			 { NULL, NULL, 0, 0, NULL, NULL, NULL }};
+
+/* Protect global state against multiple changers.  */
+__libc_lock_define_initialized (static, lock)
+
+/* Prototypes for local functions.  */
+static void blacklist_store_name (const char *, ent_t *);
+static int in_blacklist (const char *, int, ent_t *);
+
+/* Initialize the NSS interface/functions. The calling function must
+   hold the lock.  */
+static void
+init_nss_interface (void)
+{
+  if (__nss_database_lookup ("passwd_compat", NULL, "nis", &ni) >= 0)
+    {
+      nss_setpwent = __nss_lookup_function (ni, "setpwent");
+      nss_getpwnam_r = __nss_lookup_function (ni, "getpwnam_r");
+      nss_getpwuid_r = __nss_lookup_function (ni, "getpwuid_r");
+      nss_getpwent_r = __nss_lookup_function (ni, "getpwent_r");
+      nss_endpwent = __nss_lookup_function (ni, "endpwent");
+    }
+}
+
+static void
+give_pwd_free (struct passwd *pwd)
+{
+  free (pwd->pw_name);
+  free (pwd->pw_passwd);
+  free (pwd->pw_gecos);
+  free (pwd->pw_dir);
+  free (pwd->pw_shell);
+
+  memset (pwd, '\0', sizeof (struct passwd));
+}
+
+static size_t
+pwd_need_buflen (struct passwd *pwd)
+{
+  size_t len = 0;
+
+  if (pwd->pw_passwd != NULL)
+    len += strlen (pwd->pw_passwd) + 1;
+
+  if (pwd->pw_gecos != NULL)
+    len += strlen (pwd->pw_gecos) + 1;
+
+  if (pwd->pw_dir != NULL)
+    len += strlen (pwd->pw_dir) + 1;
+
+  if (pwd->pw_shell != NULL)
+    len += strlen (pwd->pw_shell) + 1;
+
+  return len;
+}
+
+static void
+copy_pwd_changes (struct passwd *dest, struct passwd *src,
+		  char *buffer, size_t buflen)
+{
+  if (src->pw_passwd != NULL && strlen (src->pw_passwd))
+    {
+      if (buffer == NULL)
+	dest->pw_passwd = strdup (src->pw_passwd);
+      else if (dest->pw_passwd &&
+	       strlen (dest->pw_passwd) >= strlen (src->pw_passwd))
+	strcpy (dest->pw_passwd, src->pw_passwd);
+      else
+	{
+	  dest->pw_passwd = buffer;
+	  strcpy (dest->pw_passwd, src->pw_passwd);
+	  buffer += strlen (dest->pw_passwd) + 1;
+	  buflen = buflen - (strlen (dest->pw_passwd) + 1);
+	}
+    }
+
+  if (src->pw_gecos != NULL && strlen (src->pw_gecos))
+    {
+      if (buffer == NULL)
+	dest->pw_gecos = strdup (src->pw_gecos);
+      else if (dest->pw_gecos &&
+	       strlen (dest->pw_gecos) >= strlen (src->pw_gecos))
+	strcpy (dest->pw_gecos, src->pw_gecos);
+      else
+	{
+	  dest->pw_gecos = buffer;
+	  strcpy (dest->pw_gecos, src->pw_gecos);
+	  buffer += strlen (dest->pw_gecos) + 1;
+	  buflen = buflen - (strlen (dest->pw_gecos) + 1);
+	}
+    }
+  if (src->pw_dir != NULL && strlen (src->pw_dir))
+    {
+      if (buffer == NULL)
+	dest->pw_dir = strdup (src->pw_dir);
+      else if (dest->pw_dir && strlen (dest->pw_dir) >= strlen (src->pw_dir))
+	strcpy (dest->pw_dir, src->pw_dir);
+      else
+	{
+	  dest->pw_dir = buffer;
+	  strcpy (dest->pw_dir, src->pw_dir);
+	  buffer += strlen (dest->pw_dir) + 1;
+	  buflen = buflen - (strlen (dest->pw_dir) + 1);
+	}
+    }
+
+  if (src->pw_shell != NULL && strlen (src->pw_shell))
+    {
+      if (buffer == NULL)
+	dest->pw_shell = strdup (src->pw_shell);
+      else if (dest->pw_shell &&
+	       strlen (dest->pw_shell) >= strlen (src->pw_shell))
+	strcpy (dest->pw_shell, src->pw_shell);
+      else
+	{
+	  dest->pw_shell = buffer;
+	  strcpy (dest->pw_shell, src->pw_shell);
+	  buffer += strlen (dest->pw_shell) + 1;
+	  buflen = buflen - (strlen (dest->pw_shell) + 1);
+	}
+    }
+}
+
+static enum nss_status
+internal_setpwent (ent_t *ent, int stayopen, int needent)
+{
+  enum nss_status status = NSS_STATUS_SUCCESS;
+
+  ent->first = ent->netgroup = false;
+  ent->files = true;
+  ent->setent_status = NSS_STATUS_SUCCESS;
+
+  /* If something was left over free it.  */
+  if (ent->netgroup)
+    __internal_endnetgrent (&ent->netgrdata);
+
+  if (ent->blacklist.data != NULL)
+    {
+      ent->blacklist.current = 1;
+      ent->blacklist.data[0] = '|';
+      ent->blacklist.data[1] = '\0';
+    }
+  else
+    ent->blacklist.current = 0;
+
+  if (ent->stream == NULL)
+    {
+      ent->stream = fopen ("/etc/passwd", "rme");
+
+      if (ent->stream == NULL)
+	status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
+      else
+	/* We take care of locking ourself.  */
+	__fsetlocking (ent->stream, FSETLOCKING_BYCALLER);
+    }
+  else
+    rewind (ent->stream);
+
+  give_pwd_free (&ent->pwd);
+
+  if (needent && status == NSS_STATUS_SUCCESS && nss_setpwent)
+    ent->setent_status = nss_setpwent (stayopen);
+
+  return status;
+}
+
+
+enum nss_status
+_nss_compat_setpwent (int stayopen)
+{
+  enum nss_status result;
+
+  __libc_lock_lock (lock);
+
+  if (ni == NULL)
+    init_nss_interface ();
+
+  result = internal_setpwent (&ext_ent, stayopen, 1);
+
+  __libc_lock_unlock (lock);
+
+  return result;
+}
+
+
+static enum nss_status
+internal_endpwent (ent_t *ent)
+{
+  if (ent->stream != NULL)
+    {
+      fclose (ent->stream);
+      ent->stream = NULL;
+    }
+
+  if (ent->netgroup)
+    __internal_endnetgrent (&ent->netgrdata);
+
+  ent->first = ent->netgroup = false;
+
+  if (ent->blacklist.data != NULL)
+    {
+      ent->blacklist.current = 1;
+      ent->blacklist.data[0] = '|';
+      ent->blacklist.data[1] = '\0';
+    }
+  else
+    ent->blacklist.current = 0;
+
+  give_pwd_free (&ent->pwd);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_compat_endpwent (void)
+{
+  enum nss_status result;
+
+  __libc_lock_lock (lock);
+
+  if (nss_endpwent)
+    nss_endpwent ();
+
+  result = internal_endpwent (&ext_ent);
+
+  __libc_lock_unlock (lock);
+
+  return result;
+}
+
+
+static enum nss_status
+getpwent_next_nss_netgr (const char *name, struct passwd *result, ent_t *ent,
+			 char *group, char *buffer, size_t buflen,
+			 int *errnop)
+{
+  char *curdomain = NULL, *host, *user, *domain, *p2;
+  int status;
+  size_t p2len;
+
+  /* Leave function if NSS module does not support getpwnam_r,
+     we need this function here.  */
+  if (!nss_getpwnam_r)
+    return NSS_STATUS_UNAVAIL;
+
+  if (ent->first)
+    {
+      memset (&ent->netgrdata, 0, sizeof (struct __netgrent));
+      __internal_setnetgrent (group, &ent->netgrdata);
+      ent->first = false;
+    }
+
+  while (1)
+    {
+      status = __internal_getnetgrent_r (&host, &user, &domain,
+					 &ent->netgrdata, buffer, buflen,
+					 errnop);
+      if (status != 1)
+	{
+	  __internal_endnetgrent (&ent->netgrdata);
+	  ent->netgroup = 0;
+	  give_pwd_free (&ent->pwd);
+	  return NSS_STATUS_RETURN;
+	}
+
+      if (user == NULL || user[0] == '-')
+	continue;
+
+      if (domain != NULL)
+	{
+	  if (curdomain == NULL
+	      && yp_get_default_domain (&curdomain) != YPERR_SUCCESS)
+	    {
+	      __internal_endnetgrent (&ent->netgrdata);
+	      ent->netgroup = false;
+	      give_pwd_free (&ent->pwd);
+	      return NSS_STATUS_UNAVAIL;
+	    }
+	  if (strcmp (curdomain, domain) != 0)
+	    continue;
+	}
+
+      /* If name != NULL, we are called from getpwnam.  */
+      if (name != NULL)
+	if (strcmp (user, name) != 0)
+	  continue;
+
+      p2len = pwd_need_buflen (&ent->pwd);
+      if (p2len > buflen)
+	{
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+      p2 = buffer + (buflen - p2len);
+      buflen -= p2len;
+
+      if (nss_getpwnam_r (user, result, buffer, buflen, errnop) !=
+	  NSS_STATUS_SUCCESS)
+	continue;
+
+      if (!in_blacklist (result->pw_name, strlen (result->pw_name), ent))
+	{
+	  /* Store the User in the blacklist for possible the "+" at the
+	     end of /etc/passwd */
+	  blacklist_store_name (result->pw_name, ent);
+	  copy_pwd_changes (result, &ent->pwd, p2, p2len);
+	  break;
+	}
+    }
+
+  return NSS_STATUS_SUCCESS;
+}
+
+/* get the next user from NSS  (+ entry) */
+static enum nss_status
+getpwent_next_nss (struct passwd *result, ent_t *ent, char *buffer,
+		   size_t buflen, int *errnop)
+{
+  enum nss_status status;
+  char *p2;
+  size_t p2len;
+
+  /* Return if NSS module does not support getpwent_r.  */
+  if (!nss_getpwent_r)
+    return NSS_STATUS_UNAVAIL;
+
+  /* If the setpwent call failed, say so.  */
+  if (ent->setent_status != NSS_STATUS_SUCCESS)
+    return ent->setent_status;
+
+  p2len = pwd_need_buflen (&ent->pwd);
+  if (p2len > buflen)
+    {
+      *errnop = ERANGE;
+      return NSS_STATUS_TRYAGAIN;
+    }
+  p2 = buffer + (buflen - p2len);
+  buflen -= p2len;
+
+  if (ent->first)
+    ent->first = false;
+
+  do
+    {
+      if ((status = nss_getpwent_r (result, buffer, buflen, errnop)) !=
+	  NSS_STATUS_SUCCESS)
+	return status;
+    }
+  while (in_blacklist (result->pw_name, strlen (result->pw_name), ent));
+
+  copy_pwd_changes (result, &ent->pwd, p2, p2len);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+/* This function handle the +user entrys in /etc/passwd */
+static enum nss_status
+getpwnam_plususer (const char *name, struct passwd *result, ent_t *ent,
+		   char *buffer, size_t buflen, int *errnop)
+{
+  if (!nss_getpwnam_r)
+    return NSS_STATUS_UNAVAIL;
+
+  struct passwd pwd;
+  memset (&pwd, '\0', sizeof (struct passwd));
+
+  copy_pwd_changes (&pwd, result, NULL, 0);
+
+  size_t plen = pwd_need_buflen (&pwd);
+  if (plen > buflen)
+    {
+      *errnop = ERANGE;
+      return NSS_STATUS_TRYAGAIN;
+    }
+  char *p = buffer + (buflen - plen);
+  buflen -= plen;
+
+  enum nss_status status = nss_getpwnam_r (name, result, buffer, buflen,
+					   errnop);
+  if (status != NSS_STATUS_SUCCESS)
+    return status;
+
+  if (in_blacklist (result->pw_name, strlen (result->pw_name), ent))
+    return NSS_STATUS_NOTFOUND;
+
+  copy_pwd_changes (result, &pwd, p, plen);
+  give_pwd_free (&pwd);
+  /* We found the entry.  */
+  return NSS_STATUS_SUCCESS;
+}
+
+static enum nss_status
+getpwent_next_file (struct passwd *result, ent_t *ent,
+		    char *buffer, size_t buflen, int *errnop)
+{
+  struct parser_data *data = (void *) buffer;
+  while (1)
+    {
+      fpos_t pos;
+      char *p;
+      int parse_res;
+
+      do
+	{
+	  /* We need at least 3 characters for one line.  */
+	  if (__glibc_unlikely (buflen < 3))
+	    {
+	    erange:
+	      *errnop = ERANGE;
+	      return NSS_STATUS_TRYAGAIN;
+	    }
+
+	  fgetpos (ent->stream, &pos);
+	  buffer[buflen - 1] = '\xff';
+	  p = fgets_unlocked (buffer, buflen, ent->stream);
+	  if (p == NULL && feof_unlocked (ent->stream))
+	    return NSS_STATUS_NOTFOUND;
+
+	  if (p == NULL || __builtin_expect (buffer[buflen - 1] != '\xff', 0))
+	    {
+	    erange_reset:
+	      fsetpos (ent->stream, &pos);
+	      goto erange;
+	    }
+
+	  /* Terminate the line for any case.  */
+	  buffer[buflen - 1] = '\0';
+
+	  /* Skip leading blanks.  */
+	  while (isspace (*p))
+	    ++p;
+	}
+      while (*p == '\0' || *p == '#' ||	/* Ignore empty and comment lines.  */
+	     /* Parse the line.  If it is invalid, loop to
+	        get the next line of the file to parse.  */
+	     !(parse_res = _nss_files_parse_pwent (p, result, data, buflen,
+						   errnop)));
+
+      if (__glibc_unlikely (parse_res == -1))
+	/* The parser ran out of space.  */
+	goto erange_reset;
+
+      if (result->pw_name[0] != '+' && result->pw_name[0] != '-')
+	/* This is a real entry.  */
+	break;
+
+      /* -@netgroup */
+      if (result->pw_name[0] == '-' && result->pw_name[1] == '@'
+	  && result->pw_name[2] != '\0')
+	{
+	  /* XXX Do not use fixed length buffer.  */
+	  char buf2[1024];
+	  char *user, *host, *domain;
+	  struct __netgrent netgrdata;
+
+	  memset (&netgrdata, 0, sizeof (struct __netgrent));
+	  __internal_setnetgrent (&result->pw_name[2], &netgrdata);
+	  while (__internal_getnetgrent_r (&host, &user, &domain, &netgrdata,
+					   buf2, sizeof (buf2), errnop))
+	    {
+	      if (user != NULL && user[0] != '-')
+		blacklist_store_name (user, ent);
+	    }
+	  __internal_endnetgrent (&netgrdata);
+	  continue;
+	}
+
+      /* +@netgroup */
+      if (result->pw_name[0] == '+' && result->pw_name[1] == '@'
+	  && result->pw_name[2] != '\0')
+	{
+	  enum nss_status status;
+
+	  ent->netgroup = true;
+	  ent->first = true;
+	  copy_pwd_changes (&ent->pwd, result, NULL, 0);
+
+	  status = getpwent_next_nss_netgr (NULL, result, ent,
+					    &result->pw_name[2],
+					    buffer, buflen, errnop);
+	  if (status == NSS_STATUS_RETURN)
+	    continue;
+	  else
+	    return status;
+	}
+
+      /* -user */
+      if (result->pw_name[0] == '-' && result->pw_name[1] != '\0'
+	  && result->pw_name[1] != '@')
+	{
+	  blacklist_store_name (&result->pw_name[1], ent);
+	  continue;
+	}
+
+      /* +user */
+      if (result->pw_name[0] == '+' && result->pw_name[1] != '\0'
+	  && result->pw_name[1] != '@')
+	{
+	  size_t len = strlen (result->pw_name);
+	  char buf[len];
+	  enum nss_status status;
+
+	  /* Store the User in the blacklist for the "+" at the end of
+	     /etc/passwd */
+	  memcpy (buf, &result->pw_name[1], len);
+	  status = getpwnam_plususer (&result->pw_name[1], result, ent,
+				      buffer, buflen, errnop);
+	  blacklist_store_name (buf, ent);
+
+	  if (status == NSS_STATUS_SUCCESS)	/* We found the entry. */
+	    break;
+	  else if (status == NSS_STATUS_RETURN	/* We couldn't parse the entry */
+		   || status == NSS_STATUS_NOTFOUND)	/* entry doesn't exist */
+	    continue;
+	  else
+	    {
+	      if (status == NSS_STATUS_TRYAGAIN)
+		{
+		  /* The parser ran out of space */
+		  fsetpos (ent->stream, &pos);
+		  *errnop = ERANGE;
+		}
+	      return status;
+	    }
+	}
+
+      /* +:... */
+      if (result->pw_name[0] == '+' && result->pw_name[1] == '\0')
+	{
+	  ent->files = false;
+	  ent->first = true;
+	  copy_pwd_changes (&ent->pwd, result, NULL, 0);
+
+	  return getpwent_next_nss (result, ent, buffer, buflen, errnop);
+	}
+    }
+
+  return NSS_STATUS_SUCCESS;
+}
+
+
+static enum nss_status
+internal_getpwent_r (struct passwd *pw, ent_t *ent, char *buffer,
+		     size_t buflen, int *errnop)
+{
+  if (ent->netgroup)
+    {
+      enum nss_status status;
+
+      /* We are searching members in a netgroup */
+      /* Since this is not the first call, we don't need the group name */
+      status = getpwent_next_nss_netgr (NULL, pw, ent, NULL, buffer, buflen,
+					errnop);
+      if (status == NSS_STATUS_RETURN)
+	return getpwent_next_file (pw, ent, buffer, buflen, errnop);
+      else
+	return status;
+    }
+  else if (ent->files)
+    return getpwent_next_file (pw, ent, buffer, buflen, errnop);
+  else
+    return getpwent_next_nss (pw, ent, buffer, buflen, errnop);
+
+}
+
+enum nss_status
+_nss_compat_getpwent_r (struct passwd *pwd, char *buffer, size_t buflen,
+			int *errnop)
+{
+  enum nss_status result = NSS_STATUS_SUCCESS;
+
+  __libc_lock_lock (lock);
+
+  /* Be prepared that the setpwent function was not called before.  */
+  if (ni == NULL)
+    init_nss_interface ();
+
+  if (ext_ent.stream == NULL)
+    result = internal_setpwent (&ext_ent, 1, 1);
+
+  if (result == NSS_STATUS_SUCCESS)
+    result = internal_getpwent_r (pwd, &ext_ent, buffer, buflen, errnop);
+
+  __libc_lock_unlock (lock);
+
+  return result;
+}
+
+/* Searches in /etc/passwd and the NIS/NIS+ map for a special user */
+static enum nss_status
+internal_getpwnam_r (const char *name, struct passwd *result, ent_t *ent,
+		     char *buffer, size_t buflen, int *errnop)
+{
+  struct parser_data *data = (void *) buffer;
+
+  while (1)
+    {
+      fpos_t pos;
+      char *p;
+      int parse_res;
+
+      do
+	{
+	  /* We need at least 3 characters for one line.  */
+	  if (__glibc_unlikely (buflen < 3))
+	    {
+	    erange:
+	      *errnop = ERANGE;
+	      return NSS_STATUS_TRYAGAIN;
+	    }
+
+	  fgetpos (ent->stream, &pos);
+	  buffer[buflen - 1] = '\xff';
+	  p = fgets_unlocked (buffer, buflen, ent->stream);
+	  if (p == NULL && feof_unlocked (ent->stream))
+	    {
+	      return NSS_STATUS_NOTFOUND;
+	    }
+	  if (p == NULL || __builtin_expect (buffer[buflen - 1] != '\xff', 0))
+	    {
+	    erange_reset:
+	      fsetpos (ent->stream, &pos);
+	      goto erange;
+	    }
+
+	  /* Terminate the line for any case.  */
+	  buffer[buflen - 1] = '\0';
+
+	  /* Skip leading blanks.  */
+	  while (isspace (*p))
+	    ++p;
+	}
+      while (*p == '\0' || *p == '#' ||	/* Ignore empty and comment lines.  */
+	     /* Parse the line.  If it is invalid, loop to
+	        get the next line of the file to parse.  */
+	     !(parse_res = _nss_files_parse_pwent (p, result, data, buflen,
+						   errnop)));
+
+      if (__glibc_unlikely (parse_res == -1))
+	/* The parser ran out of space.  */
+	goto erange_reset;
+
+      /* This is a real entry.  */
+      if (result->pw_name[0] != '+' && result->pw_name[0] != '-')
+	{
+	  if (strcmp (result->pw_name, name) == 0)
+	    return NSS_STATUS_SUCCESS;
+	  else
+	    continue;
+	}
+
+      /* -@netgroup */
+      if (result->pw_name[0] == '-' && result->pw_name[1] == '@'
+	  && result->pw_name[2] != '\0')
+	{
+	  if (innetgr (&result->pw_name[2], NULL, name, NULL))
+	    return NSS_STATUS_NOTFOUND;
+	  continue;
+	}
+
+      /* +@netgroup */
+      if (result->pw_name[0] == '+' && result->pw_name[1] == '@'
+	  && result->pw_name[2] != '\0')
+	{
+	  enum nss_status status;
+
+	  if (innetgr (&result->pw_name[2], NULL, name, NULL))
+	    {
+	      status = getpwnam_plususer (name, result, ent, buffer,
+					  buflen, errnop);
+
+	      if (status == NSS_STATUS_RETURN)
+		continue;
+
+	      return status;
+	    }
+	  continue;
+	}
+
+      /* -user */
+      if (result->pw_name[0] == '-' && result->pw_name[1] != '\0'
+	  && result->pw_name[1] != '@')
+	{
+	  if (strcmp (&result->pw_name[1], name) == 0)
+	    return NSS_STATUS_NOTFOUND;
+	  else
+	    continue;
+	}
+
+      /* +user */
+      if (result->pw_name[0] == '+' && result->pw_name[1] != '\0'
+	  && result->pw_name[1] != '@')
+	{
+	  if (strcmp (name, &result->pw_name[1]) == 0)
+	    {
+	      enum nss_status status;
+
+	      status = getpwnam_plususer (name, result, ent, buffer, buflen,
+					  errnop);
+	      if (status == NSS_STATUS_RETURN)
+		/* We couldn't parse the entry */
+		return NSS_STATUS_NOTFOUND;
+	      else
+		return status;
+	    }
+	}
+
+      /* +:... */
+      if (result->pw_name[0] == '+' && result->pw_name[1] == '\0')
+	{
+	  enum nss_status status;
+
+	  status = getpwnam_plususer (name, result, ent,
+				      buffer, buflen, errnop);
+	  if (status == NSS_STATUS_SUCCESS)	/* We found the entry. */
+	    break;
+	  else if (status == NSS_STATUS_RETURN)	/* We couldn't parse the entry */
+	    return NSS_STATUS_NOTFOUND;
+	  else
+	    return status;
+	}
+    }
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_compat_getpwnam_r (const char *name, struct passwd *pwd,
+			char *buffer, size_t buflen, int *errnop)
+{
+  enum nss_status result;
+  ent_t ent = { false, false, true, NSS_STATUS_SUCCESS, NULL, { NULL, 0, 0 },
+		{ NULL, NULL, 0, 0, NULL, NULL, NULL }};
+
+  if (name[0] == '-' || name[0] == '+')
+    return NSS_STATUS_NOTFOUND;
+
+  __libc_lock_lock (lock);
+
+  if (ni == NULL)
+    init_nss_interface ();
+
+  __libc_lock_unlock (lock);
+
+  result = internal_setpwent (&ent, 0, 0);
+
+  if (result == NSS_STATUS_SUCCESS)
+    result = internal_getpwnam_r (name, pwd, &ent, buffer, buflen, errnop);
+
+  internal_endpwent (&ent);
+
+  return result;
+}
+
+/* This function handle the + entry in /etc/passwd for getpwuid */
+static enum nss_status
+getpwuid_plususer (uid_t uid, struct passwd *result, char *buffer,
+		   size_t buflen, int *errnop)
+{
+  struct passwd pwd;
+  char *p;
+  size_t plen;
+
+  if (!nss_getpwuid_r)
+    return NSS_STATUS_UNAVAIL;
+
+  memset (&pwd, '\0', sizeof (struct passwd));
+
+  copy_pwd_changes (&pwd, result, NULL, 0);
+
+  plen = pwd_need_buflen (&pwd);
+  if (plen > buflen)
+    {
+      *errnop = ERANGE;
+      return NSS_STATUS_TRYAGAIN;
+    }
+  p = buffer + (buflen - plen);
+  buflen -= plen;
+
+  if (nss_getpwuid_r (uid, result, buffer, buflen, errnop) ==
+      NSS_STATUS_SUCCESS)
+    {
+      copy_pwd_changes (result, &pwd, p, plen);
+      give_pwd_free (&pwd);
+      /* We found the entry.  */
+      return NSS_STATUS_SUCCESS;
+    }
+  else
+    {
+      /* Give buffer the old len back */
+      buflen += plen;
+      give_pwd_free (&pwd);
+    }
+  return NSS_STATUS_RETURN;
+}
+
+/* Searches in /etc/passwd and the NSS subsystem for a special user id */
+static enum nss_status
+internal_getpwuid_r (uid_t uid, struct passwd *result, ent_t *ent,
+		     char *buffer, size_t buflen, int *errnop)
+{
+  struct parser_data *data = (void *) buffer;
+
+  while (1)
+    {
+      fpos_t pos;
+      char *p;
+      int parse_res;
+
+      do
+	{
+	  /* We need at least 3 characters for one line.  */
+	  if (__glibc_unlikely (buflen < 3))
+	    {
+	    erange:
+	      *errnop = ERANGE;
+	      return NSS_STATUS_TRYAGAIN;
+	    }
+
+	  fgetpos (ent->stream, &pos);
+	  buffer[buflen - 1] = '\xff';
+	  p = fgets_unlocked (buffer, buflen, ent->stream);
+	  if (p == NULL && feof_unlocked (ent->stream))
+	    return NSS_STATUS_NOTFOUND;
+
+	  if (p == NULL || __builtin_expect (buffer[buflen - 1] != '\xff', 0))
+	    {
+	    erange_reset:
+	      fsetpos (ent->stream, &pos);
+	      goto erange;
+	    }
+
+	  /* Terminate the line for any case.  */
+	  buffer[buflen - 1] = '\0';
+
+	  /* Skip leading blanks.  */
+	  while (isspace (*p))
+	    ++p;
+	}
+      while (*p == '\0' || *p == '#' ||	/* Ignore empty and comment lines.  */
+	     /* Parse the line.  If it is invalid, loop to
+	        get the next line of the file to parse.  */
+	     !(parse_res = _nss_files_parse_pwent (p, result, data, buflen,
+						   errnop)));
+
+      if (__glibc_unlikely (parse_res == -1))
+	/* The parser ran out of space.  */
+	goto erange_reset;
+
+      /* This is a real entry.  */
+      if (result->pw_name[0] != '+' && result->pw_name[0] != '-')
+	{
+	  if (result->pw_uid == uid)
+	    return NSS_STATUS_SUCCESS;
+	  else
+	    continue;
+	}
+
+      /* -@netgroup */
+      if (result->pw_name[0] == '-' && result->pw_name[1] == '@'
+	  && result->pw_name[2] != '\0')
+	{
+	  /* -1, because we remove first two character of pw_name.  */
+	  size_t len = strlen (result->pw_name) - 1;
+	  char buf[len];
+	  enum nss_status status;
+
+	  memcpy (buf, &result->pw_name[2], len);
+
+	  status = getpwuid_plususer (uid, result, buffer, buflen, errnop);
+	  if (status == NSS_STATUS_SUCCESS &&
+	      innetgr (buf, NULL, result->pw_name, NULL))
+	    return NSS_STATUS_NOTFOUND;
+
+	  continue;
+	}
+
+      /* +@netgroup */
+      if (result->pw_name[0] == '+' && result->pw_name[1] == '@'
+	  && result->pw_name[2] != '\0')
+	{
+	  /* -1, because we remove first two characters of pw_name.  */
+	  size_t len = strlen (result->pw_name) - 1;
+	  char buf[len];
+	  enum nss_status status;
+
+	  memcpy (buf, &result->pw_name[2], len);
+
+	  status = getpwuid_plususer (uid, result, buffer, buflen, errnop);
+
+	  if (status == NSS_STATUS_RETURN)
+	    continue;
+
+	  if (status == NSS_STATUS_SUCCESS)
+	    {
+	      if (innetgr (buf, NULL, result->pw_name, NULL))
+		return NSS_STATUS_SUCCESS;
+	    }
+	  else if (status == NSS_STATUS_RETURN)	/* We couldn't parse the entry */
+	    return NSS_STATUS_NOTFOUND;
+	  else
+	    return status;
+
+	  continue;
+	}
+
+      /* -user */
+      if (result->pw_name[0] == '-' && result->pw_name[1] != '\0'
+	  && result->pw_name[1] != '@')
+	{
+	  size_t len = strlen (result->pw_name);
+	  char buf[len];
+	  enum nss_status status;
+
+	  memcpy (buf, &result->pw_name[1], len);
+
+	  status = getpwuid_plususer (uid, result, buffer, buflen, errnop);
+	  if (status == NSS_STATUS_SUCCESS &&
+	      innetgr (buf, NULL, result->pw_name, NULL))
+	    return NSS_STATUS_NOTFOUND;
+	  continue;
+	}
+
+      /* +user */
+      if (result->pw_name[0] == '+' && result->pw_name[1] != '\0'
+	  && result->pw_name[1] != '@')
+	{
+	  size_t len = strlen (result->pw_name);
+	  char buf[len];
+	  enum nss_status status;
+
+	  memcpy (buf, &result->pw_name[1], len);
+
+	  status = getpwuid_plususer (uid, result, buffer, buflen, errnop);
+
+	  if (status == NSS_STATUS_RETURN)
+	    continue;
+
+	  if (status == NSS_STATUS_SUCCESS)
+	    {
+	      if (strcmp (buf, result->pw_name) == 0)
+		return NSS_STATUS_SUCCESS;
+	    }
+	  else if (status == NSS_STATUS_RETURN)	/* We couldn't parse the entry */
+	    return NSS_STATUS_NOTFOUND;
+	  else
+	    return status;
+
+	  continue;
+	}
+
+      /* +:... */
+      if (result->pw_name[0] == '+' && result->pw_name[1] == '\0')
+	{
+	  enum nss_status status;
+
+	  status = getpwuid_plususer (uid, result, buffer, buflen, errnop);
+	  if (status == NSS_STATUS_SUCCESS)	/* We found the entry. */
+	    break;
+	  else if (status == NSS_STATUS_RETURN)	/* We couldn't parse the entry */
+	    return NSS_STATUS_NOTFOUND;
+	  else
+	    return status;
+	}
+    }
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_compat_getpwuid_r (uid_t uid, struct passwd *pwd,
+			char *buffer, size_t buflen, int *errnop)
+{
+  enum nss_status result;
+  ent_t ent = { false, false, true, NSS_STATUS_SUCCESS, NULL, { NULL, 0, 0 },
+		{ NULL, NULL, 0, 0, NULL, NULL, NULL }};
+
+  __libc_lock_lock (lock);
+
+  if (ni == NULL)
+    init_nss_interface ();
+
+  __libc_lock_unlock (lock);
+
+  result = internal_setpwent (&ent, 0, 0);
+
+  if (result == NSS_STATUS_SUCCESS)
+    result = internal_getpwuid_r (uid, pwd, &ent, buffer, buflen, errnop);
+
+  internal_endpwent (&ent);
+
+  return result;
+}
+
+
+/* Support routines for remembering -@netgroup and -user entries.
+   The names are stored in a single string with `|' as separator. */
+static void
+blacklist_store_name (const char *name, ent_t *ent)
+{
+  int namelen = strlen (name);
+  char *tmp;
+
+  /* first call, setup cache */
+  if (ent->blacklist.size == 0)
+    {
+      ent->blacklist.size = MAX (BLACKLIST_INITIAL_SIZE, 2 * namelen);
+      ent->blacklist.data = malloc (ent->blacklist.size);
+      if (ent->blacklist.data == NULL)
+	return;
+      ent->blacklist.data[0] = '|';
+      ent->blacklist.data[1] = '\0';
+      ent->blacklist.current = 1;
+    }
+  else
+    {
+      if (in_blacklist (name, namelen, ent))
+	return;			/* no duplicates */
+
+      if (ent->blacklist.current + namelen + 1 >= ent->blacklist.size)
+	{
+	  ent->blacklist.size += MAX (BLACKLIST_INCREMENT, 2 * namelen);
+	  tmp = realloc (ent->blacklist.data, ent->blacklist.size);
+	  if (tmp == NULL)
+	    {
+	      free (ent->blacklist.data);
+	      ent->blacklist.size = 0;
+	      return;
+	    }
+	  ent->blacklist.data = tmp;
+	}
+    }
+
+  tmp = stpcpy (ent->blacklist.data + ent->blacklist.current, name);
+  *tmp++ = '|';
+  *tmp = '\0';
+  ent->blacklist.current += namelen + 1;
+
+  return;
+}
+
+/* Returns TRUE if ent->blacklist contains name, else FALSE.  */
+static bool_t
+in_blacklist (const char *name, int namelen, ent_t *ent)
+{
+  char buf[namelen + 3];
+  char *cp;
+
+  if (ent->blacklist.data == NULL)
+    return FALSE;
+
+  buf[0] = '|';
+  cp = stpcpy (&buf[1], name);
+  *cp++ = '|';
+  *cp = '\0';
+  return strstr (ent->blacklist.data, buf) != NULL;
+}
diff --git a/REORG.TODO/nis/nss_compat/compat-spwd.c b/REORG.TODO/nis/nss_compat/compat-spwd.c
new file mode 100644
index 0000000000..eec3af3d15
--- /dev/null
+++ b/REORG.TODO/nis/nss_compat/compat-spwd.c
@@ -0,0 +1,858 @@
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <nss.h>
+#include <nsswitch.h>
+#include <shadow.h>
+#include <stdio_ext.h>
+#include <string.h>
+#include <rpc/types.h>
+#include <rpcsvc/ypclnt.h>
+#include <libc-lock.h>
+#include <kernel-features.h>
+
+#include "netgroup.h"
+
+static service_user *ni;
+static enum nss_status (*nss_setspent) (int stayopen);
+static enum nss_status (*nss_getspnam_r) (const char *name, struct spwd * sp,
+					  char *buffer, size_t buflen,
+					  int *errnop);
+static enum nss_status (*nss_getspent_r) (struct spwd * sp, char *buffer,
+					  size_t buflen, int *errnop);
+static enum nss_status (*nss_endspent) (void);
+
+/* Get the declaration of the parser function.  */
+#define ENTNAME spent
+#define STRUCTURE spwd
+#define EXTERN_PARSER
+#include <nss/nss_files/files-parse.c>
+
+/* Structure for remembering -@netgroup and -user members ... */
+#define BLACKLIST_INITIAL_SIZE 512
+#define BLACKLIST_INCREMENT 256
+struct blacklist_t
+{
+  char *data;
+  int current;
+  int size;
+};
+
+struct ent_t
+{
+  bool netgroup;
+  bool files;
+  bool first;
+  enum nss_status setent_status;
+  FILE *stream;
+  struct blacklist_t blacklist;
+  struct spwd pwd;
+  struct __netgrent netgrdata;
+};
+typedef struct ent_t ent_t;
+
+static ent_t ext_ent = { false, true, false, NSS_STATUS_SUCCESS, NULL,
+			 { NULL, 0, 0},
+			 { NULL, NULL, 0, 0, 0, 0, 0, 0, 0}};
+
+/* Protect global state against multiple changers.  */
+__libc_lock_define_initialized (static, lock)
+
+/* Prototypes for local functions.  */
+static void blacklist_store_name (const char *, ent_t *);
+static int in_blacklist (const char *, int, ent_t *);
+
+/* Initialize the NSS interface/functions. The calling function must
+   hold the lock.  */
+static void
+init_nss_interface (void)
+{
+  if (__nss_database_lookup ("shadow_compat", "passwd_compat",
+			     "nis", &ni) >= 0)
+    {
+      nss_setspent = __nss_lookup_function (ni, "setspent");
+      nss_getspnam_r = __nss_lookup_function (ni, "getspnam_r");
+      nss_getspent_r = __nss_lookup_function (ni, "getspent_r");
+      nss_endspent = __nss_lookup_function (ni, "endspent");
+    }
+}
+
+static void
+give_spwd_free (struct spwd *pwd)
+{
+  free (pwd->sp_namp);
+  free (pwd->sp_pwdp);
+
+  memset (pwd, '\0', sizeof (struct spwd));
+  pwd->sp_warn = -1;
+  pwd->sp_inact = -1;
+  pwd->sp_expire = -1;
+  pwd->sp_flag = ~0ul;
+}
+
+static int
+spwd_need_buflen (struct spwd *pwd)
+{
+  int len = 0;
+
+  if (pwd->sp_pwdp != NULL)
+    len += strlen (pwd->sp_pwdp) + 1;
+
+  return len;
+}
+
+static void
+copy_spwd_changes (struct spwd *dest, struct spwd *src,
+		   char *buffer, size_t buflen)
+{
+  if (src->sp_pwdp != NULL && strlen (src->sp_pwdp))
+    {
+      if (buffer == NULL)
+	dest->sp_pwdp = strdup (src->sp_pwdp);
+      else if (dest->sp_pwdp &&
+	       strlen (dest->sp_pwdp) >= strlen (src->sp_pwdp))
+	strcpy (dest->sp_pwdp, src->sp_pwdp);
+      else
+	{
+	  dest->sp_pwdp = buffer;
+	  strcpy (dest->sp_pwdp, src->sp_pwdp);
+	  buffer += strlen (dest->sp_pwdp) + 1;
+	  buflen = buflen - (strlen (dest->sp_pwdp) + 1);
+	}
+    }
+  if (src->sp_lstchg != 0)
+    dest->sp_lstchg = src->sp_lstchg;
+  if (src->sp_min != 0)
+    dest->sp_min = src->sp_min;
+  if (src->sp_max != 0)
+    dest->sp_max = src->sp_max;
+  if (src->sp_warn != -1)
+    dest->sp_warn = src->sp_warn;
+  if (src->sp_inact != -1)
+    dest->sp_inact = src->sp_inact;
+  if (src->sp_expire != -1)
+    dest->sp_expire = src->sp_expire;
+  if (src->sp_flag != ~0ul)
+    dest->sp_flag = src->sp_flag;
+}
+
+static enum nss_status
+internal_setspent (ent_t *ent, int stayopen, int needent)
+{
+  enum nss_status status = NSS_STATUS_SUCCESS;
+
+  ent->first = ent->netgroup = 0;
+  ent->files = true;
+
+  /* If something was left over free it.  */
+  if (ent->netgroup)
+    __internal_endnetgrent (&ent->netgrdata);
+
+  if (ent->blacklist.data != NULL)
+    {
+      ent->blacklist.current = 1;
+      ent->blacklist.data[0] = '|';
+      ent->blacklist.data[1] = '\0';
+    }
+  else
+    ent->blacklist.current = 0;
+
+  if (ent->stream == NULL)
+    {
+      ent->stream = fopen ("/etc/shadow", "rme");
+
+      if (ent->stream == NULL)
+	status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
+      else
+	/* We take care of locking ourself.  */
+	__fsetlocking (ent->stream, FSETLOCKING_BYCALLER);
+    }
+  else
+    rewind (ent->stream);
+
+  give_spwd_free (&ent->pwd);
+
+  if (needent && status == NSS_STATUS_SUCCESS && nss_setspent)
+    ent->setent_status = nss_setspent (stayopen);
+
+  return status;
+}
+
+
+enum nss_status
+_nss_compat_setspent (int stayopen)
+{
+  enum nss_status result;
+
+  __libc_lock_lock (lock);
+
+  if (ni == NULL)
+    init_nss_interface ();
+
+  result = internal_setspent (&ext_ent, stayopen, 1);
+
+  __libc_lock_unlock (lock);
+
+  return result;
+}
+
+
+static enum nss_status
+internal_endspent (ent_t *ent)
+{
+  if (ent->stream != NULL)
+    {
+      fclose (ent->stream);
+      ent->stream = NULL;
+    }
+
+  if (ent->netgroup)
+    __internal_endnetgrent (&ent->netgrdata);
+
+  ent->first = ent->netgroup = false;
+  ent->files = true;
+
+  if (ent->blacklist.data != NULL)
+    {
+      ent->blacklist.current = 1;
+      ent->blacklist.data[0] = '|';
+      ent->blacklist.data[1] = '\0';
+    }
+  else
+    ent->blacklist.current = 0;
+
+  give_spwd_free (&ent->pwd);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_compat_endspent (void)
+{
+  enum nss_status result;
+
+  __libc_lock_lock (lock);
+
+  if (nss_endspent)
+    nss_endspent ();
+
+  result = internal_endspent (&ext_ent);
+
+  __libc_lock_unlock (lock);
+
+  return result;
+}
+
+
+static enum nss_status
+getspent_next_nss_netgr (const char *name, struct spwd *result, ent_t *ent,
+			 char *group, char *buffer, size_t buflen,
+			 int *errnop)
+{
+  char *curdomain = NULL, *host, *user, *domain, *p2;
+  size_t p2len;
+
+  if (!nss_getspnam_r)
+    return NSS_STATUS_UNAVAIL;
+
+  /* If the setpwent call failed, say so.  */
+  if (ent->setent_status != NSS_STATUS_SUCCESS)
+    return ent->setent_status;
+
+  if (ent->first)
+    {
+      memset (&ent->netgrdata, 0, sizeof (struct __netgrent));
+      __internal_setnetgrent (group, &ent->netgrdata);
+      ent->first = false;
+    }
+
+  while (1)
+    {
+      enum nss_status status;
+
+      status = __internal_getnetgrent_r (&host, &user, &domain,
+					 &ent->netgrdata, buffer, buflen,
+					 errnop);
+      if (status != 1)
+	{
+	  __internal_endnetgrent (&ent->netgrdata);
+	  ent->netgroup = false;
+	  give_spwd_free (&ent->pwd);
+	  return NSS_STATUS_RETURN;
+	}
+
+      if (user == NULL || user[0] == '-')
+	continue;
+
+      if (domain != NULL)
+	{
+	  if (curdomain == NULL
+	      && yp_get_default_domain (&curdomain) != YPERR_SUCCESS)
+	    {
+	      __internal_endnetgrent (&ent->netgrdata);
+	      ent->netgroup = false;
+	      give_spwd_free (&ent->pwd);
+	      return NSS_STATUS_UNAVAIL;
+	    }
+	  if (strcmp (curdomain, domain) != 0)
+	    continue;
+	}
+
+      /* If name != NULL, we are called from getpwnam */
+      if (name != NULL)
+	if (strcmp (user, name) != 0)
+	  continue;
+
+      p2len = spwd_need_buflen (&ent->pwd);
+      if (p2len > buflen)
+	{
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+      p2 = buffer + (buflen - p2len);
+      buflen -= p2len;
+
+      if (nss_getspnam_r (user, result, buffer, buflen, errnop) !=
+	  NSS_STATUS_SUCCESS)
+	continue;
+
+      if (!in_blacklist (result->sp_namp, strlen (result->sp_namp), ent))
+	{
+	  /* Store the User in the blacklist for possible the "+" at the
+	     end of /etc/passwd */
+	  blacklist_store_name (result->sp_namp, ent);
+	  copy_spwd_changes (result, &ent->pwd, p2, p2len);
+	  break;
+	}
+    }
+
+  return NSS_STATUS_SUCCESS;
+}
+
+
+static enum nss_status
+getspent_next_nss (struct spwd *result, ent_t *ent,
+		   char *buffer, size_t buflen, int *errnop)
+{
+  enum nss_status status;
+  char *p2;
+  size_t p2len;
+
+  if (!nss_getspent_r)
+    return NSS_STATUS_UNAVAIL;
+
+  p2len = spwd_need_buflen (&ent->pwd);
+  if (p2len > buflen)
+    {
+      *errnop = ERANGE;
+      return NSS_STATUS_TRYAGAIN;
+    }
+  p2 = buffer + (buflen - p2len);
+  buflen -= p2len;
+  do
+    {
+      if ((status = nss_getspent_r (result, buffer, buflen, errnop)) !=
+	  NSS_STATUS_SUCCESS)
+	return status;
+    }
+  while (in_blacklist (result->sp_namp, strlen (result->sp_namp), ent));
+
+  copy_spwd_changes (result, &ent->pwd, p2, p2len);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+
+/* This function handle the +user entrys in /etc/shadow */
+static enum nss_status
+getspnam_plususer (const char *name, struct spwd *result, ent_t *ent,
+		   char *buffer, size_t buflen, int *errnop)
+{
+  if (!nss_getspnam_r)
+    return NSS_STATUS_UNAVAIL;
+
+  struct spwd pwd;
+  memset (&pwd, '\0', sizeof (struct spwd));
+  pwd.sp_warn = -1;
+  pwd.sp_inact = -1;
+  pwd.sp_expire = -1;
+  pwd.sp_flag = ~0ul;
+
+  copy_spwd_changes (&pwd, result, NULL, 0);
+
+  size_t plen = spwd_need_buflen (&pwd);
+  if (plen > buflen)
+    {
+      *errnop = ERANGE;
+      return NSS_STATUS_TRYAGAIN;
+    }
+  char *p = buffer + (buflen - plen);
+  buflen -= plen;
+
+  enum nss_status status = nss_getspnam_r (name, result, buffer, buflen,
+					   errnop);
+  if (status != NSS_STATUS_SUCCESS)
+    return status;
+
+  if (in_blacklist (result->sp_namp, strlen (result->sp_namp), ent))
+    return NSS_STATUS_NOTFOUND;
+
+  copy_spwd_changes (result, &pwd, p, plen);
+  give_spwd_free (&pwd);
+  /* We found the entry.  */
+  return NSS_STATUS_SUCCESS;
+}
+
+
+static enum nss_status
+getspent_next_file (struct spwd *result, ent_t *ent,
+		    char *buffer, size_t buflen, int *errnop)
+{
+  struct parser_data *data = (void *) buffer;
+  while (1)
+    {
+      fpos_t pos;
+      int parse_res = 0;
+      char *p;
+
+      do
+	{
+	  /* We need at least 3 characters for one line.  */
+	  if (__glibc_unlikely (buflen < 3))
+	    {
+	    erange:
+	      *errnop = ERANGE;
+	      return NSS_STATUS_TRYAGAIN;
+	    }
+
+	  fgetpos (ent->stream, &pos);
+	  buffer[buflen - 1] = '\xff';
+	  p = fgets_unlocked (buffer, buflen, ent->stream);
+	  if (p == NULL && feof_unlocked (ent->stream))
+	    return NSS_STATUS_NOTFOUND;
+
+	  if (p == NULL || __builtin_expect (buffer[buflen - 1] != '\xff', 0))
+	    {
+	    erange_reset:
+	      fsetpos (ent->stream, &pos);
+	      goto erange;
+	    }
+
+	  /* Skip leading blanks.  */
+	  while (isspace (*p))
+	    ++p;
+	}
+      while (*p == '\0' || *p == '#'	/* Ignore empty and comment lines.  */
+	     /* Parse the line.  If it is invalid, loop to
+	        get the next line of the file to parse.  */
+	     || !(parse_res = _nss_files_parse_spent (p, result, data,
+						      buflen, errnop)));
+
+      if (__glibc_unlikely (parse_res == -1))
+	/* The parser ran out of space.  */
+	goto erange_reset;
+
+      if (result->sp_namp[0] != '+' && result->sp_namp[0] != '-')
+	/* This is a real entry.  */
+	break;
+
+      /* -@netgroup */
+      if (result->sp_namp[0] == '-' && result->sp_namp[1] == '@'
+	  && result->sp_namp[2] != '\0')
+	{
+	  /* XXX Do not use fixed length buffers.  */
+	  char buf2[1024];
+	  char *user, *host, *domain;
+	  struct __netgrent netgrdata;
+
+	  memset (&netgrdata, 0, sizeof (struct __netgrent));
+	  __internal_setnetgrent (&result->sp_namp[2], &netgrdata);
+	  while (__internal_getnetgrent_r (&host, &user, &domain,
+					   &netgrdata, buf2, sizeof (buf2),
+					   errnop))
+	    {
+	      if (user != NULL && user[0] != '-')
+		blacklist_store_name (user, ent);
+	    }
+	  __internal_endnetgrent (&netgrdata);
+	  continue;
+	}
+
+      /* +@netgroup */
+      if (result->sp_namp[0] == '+' && result->sp_namp[1] == '@'
+	  && result->sp_namp[2] != '\0')
+	{
+	  int status;
+
+	  ent->netgroup = true;
+	  ent->first = true;
+	  copy_spwd_changes (&ent->pwd, result, NULL, 0);
+
+	  status = getspent_next_nss_netgr (NULL, result, ent,
+					    &result->sp_namp[2],
+					    buffer, buflen, errnop);
+	  if (status == NSS_STATUS_RETURN)
+	    continue;
+	  else
+	    return status;
+	}
+
+      /* -user */
+      if (result->sp_namp[0] == '-' && result->sp_namp[1] != '\0'
+	  && result->sp_namp[1] != '@')
+	{
+	  blacklist_store_name (&result->sp_namp[1], ent);
+	  continue;
+	}
+
+      /* +user */
+      if (result->sp_namp[0] == '+' && result->sp_namp[1] != '\0'
+	  && result->sp_namp[1] != '@')
+	{
+	  size_t len = strlen (result->sp_namp);
+	  char buf[len];
+	  enum nss_status status;
+
+	  /* Store the User in the blacklist for the "+" at the end of
+	     /etc/passwd */
+	  memcpy (buf, &result->sp_namp[1], len);
+	  status = getspnam_plususer (&result->sp_namp[1], result, ent,
+				      buffer, buflen, errnop);
+	  blacklist_store_name (buf, ent);
+
+	  if (status == NSS_STATUS_SUCCESS)	/* We found the entry. */
+	    break;
+	  /* We couldn't parse the entry */
+	  else if (status == NSS_STATUS_RETURN
+		   /* entry doesn't exist */
+		   || status == NSS_STATUS_NOTFOUND)
+	    continue;
+	  else
+	    {
+	      if (status == NSS_STATUS_TRYAGAIN)
+		{
+		  fsetpos (ent->stream, &pos);
+		  *errnop = ERANGE;
+		}
+	      return status;
+	    }
+	}
+
+      /* +:... */
+      if (result->sp_namp[0] == '+' && result->sp_namp[1] == '\0')
+	{
+	  ent->files = false;
+	  ent->first = true;
+	  copy_spwd_changes (&ent->pwd, result, NULL, 0);
+
+	  return getspent_next_nss (result, ent, buffer, buflen, errnop);
+	}
+    }
+
+  return NSS_STATUS_SUCCESS;
+}
+
+
+static enum nss_status
+internal_getspent_r (struct spwd *pw, ent_t *ent,
+		     char *buffer, size_t buflen, int *errnop)
+{
+  if (ent->netgroup)
+    {
+      enum nss_status status;
+
+      /* We are searching members in a netgroup */
+      /* Since this is not the first call, we don't need the group name */
+      status = getspent_next_nss_netgr (NULL, pw, ent, NULL, buffer,
+					buflen, errnop);
+
+      if (status == NSS_STATUS_RETURN)
+	return getspent_next_file (pw, ent, buffer, buflen, errnop);
+      else
+	return status;
+    }
+  else if (ent->files)
+    return getspent_next_file (pw, ent, buffer, buflen, errnop);
+  else
+    return getspent_next_nss (pw, ent, buffer, buflen, errnop);
+}
+
+
+enum nss_status
+_nss_compat_getspent_r (struct spwd *pwd, char *buffer, size_t buflen,
+			int *errnop)
+{
+  enum nss_status result = NSS_STATUS_SUCCESS;
+
+  __libc_lock_lock (lock);
+
+  /* Be prepared that the setpwent function was not called before.  */
+  if (ni == NULL)
+    init_nss_interface ();
+
+  if (ext_ent.stream == NULL)
+    result = internal_setspent (&ext_ent, 1, 1);
+
+  if (result == NSS_STATUS_SUCCESS)
+    result = internal_getspent_r (pwd, &ext_ent, buffer, buflen, errnop);
+
+  __libc_lock_unlock (lock);
+
+  return result;
+}
+
+
+/* Searches in /etc/passwd and the NIS/NIS+ map for a special user */
+static enum nss_status
+internal_getspnam_r (const char *name, struct spwd *result, ent_t *ent,
+		     char *buffer, size_t buflen, int *errnop)
+{
+  struct parser_data *data = (void *) buffer;
+
+  while (1)
+    {
+      fpos_t pos;
+      char *p;
+      int parse_res;
+
+      do
+	{
+	  /* We need at least 3 characters for one line.  */
+	  if (__glibc_unlikely (buflen < 3))
+	    {
+	    erange:
+	      *errnop = ERANGE;
+	      return NSS_STATUS_TRYAGAIN;
+	    }
+
+	  fgetpos (ent->stream, &pos);
+	  buffer[buflen - 1] = '\xff';
+	  p = fgets_unlocked (buffer, buflen, ent->stream);
+	  if (p == NULL && feof_unlocked (ent->stream))
+	    return NSS_STATUS_NOTFOUND;
+
+	  if (p == NULL || buffer[buflen - 1] != '\xff')
+	    {
+	    erange_reset:
+	      fsetpos (ent->stream, &pos);
+	      goto erange;
+	    }
+
+          /* Terminate the line for any case.  */
+	  buffer[buflen - 1] = '\0';
+
+	  /* Skip leading blanks.  */
+	  while (isspace (*p))
+	    ++p;
+	}
+      while (*p == '\0' || *p == '#' ||	/* Ignore empty and comment lines.  */
+	     /* Parse the line.  If it is invalid, loop to
+	        get the next line of the file to parse.  */
+	     !(parse_res = _nss_files_parse_spent (p, result, data, buflen,
+						   errnop)));
+
+      if (__glibc_unlikely (parse_res == -1))
+	/* The parser ran out of space.  */
+	goto erange_reset;
+
+      /* This is a real entry.  */
+      if (result->sp_namp[0] != '+' && result->sp_namp[0] != '-')
+	{
+	  if (strcmp (result->sp_namp, name) == 0)
+	    return NSS_STATUS_SUCCESS;
+	  else
+	    continue;
+	}
+
+      /* -@netgroup */
+      /* If the loaded NSS module does not support this service, add
+         all users from a +@netgroup entry to the blacklist, too.  */
+      if (result->sp_namp[0] == '-' && result->sp_namp[1] == '@'
+	  && result->sp_namp[2] != '\0')
+	{
+	  if (innetgr (&result->sp_namp[2], NULL, name, NULL))
+	    return NSS_STATUS_NOTFOUND;
+	  continue;
+	}
+
+      /* +@netgroup */
+      if (result->sp_namp[0] == '+' && result->sp_namp[1] == '@'
+	  && result->sp_namp[2] != '\0')
+	{
+	  enum nss_status status;
+
+	  if (innetgr (&result->sp_namp[2], NULL, name, NULL))
+	    {
+	      status = getspnam_plususer (name, result, ent, buffer,
+					  buflen, errnop);
+
+	      if (status == NSS_STATUS_RETURN)
+		continue;
+
+	      return status;
+	    }
+	  continue;
+	}
+
+      /* -user */
+      if (result->sp_namp[0] == '-' && result->sp_namp[1] != '\0'
+	  && result->sp_namp[1] != '@')
+	{
+	  if (strcmp (&result->sp_namp[1], name) == 0)
+	    return NSS_STATUS_NOTFOUND;
+	  else
+	    continue;
+	}
+
+      /* +user */
+      if (result->sp_namp[0] == '+' && result->sp_namp[1] != '\0'
+	  && result->sp_namp[1] != '@')
+	{
+	  if (strcmp (name, &result->sp_namp[1]) == 0)
+	    {
+	      enum nss_status status;
+
+	      status = getspnam_plususer (name, result, ent,
+					  buffer, buflen, errnop);
+
+	      if (status == NSS_STATUS_RETURN)
+		/* We couldn't parse the entry */
+		return NSS_STATUS_NOTFOUND;
+	      else
+		return status;
+	    }
+	}
+
+      /* +:... */
+      if (result->sp_namp[0] == '+' && result->sp_namp[1] == '\0')
+	{
+	  enum nss_status status;
+
+	  status = getspnam_plususer (name, result, ent,
+				      buffer, buflen, errnop);
+
+	  if (status == NSS_STATUS_SUCCESS)
+	    /* We found the entry. */
+            break;
+          else if (status == NSS_STATUS_RETURN)
+	    /* We couldn't parse the entry */
+            return NSS_STATUS_NOTFOUND;
+	  else
+	    return status;
+	}
+    }
+  return NSS_STATUS_SUCCESS;
+}
+
+
+enum nss_status
+_nss_compat_getspnam_r (const char *name, struct spwd *pwd,
+			char *buffer, size_t buflen, int *errnop)
+{
+  enum nss_status result;
+  ent_t ent = { false, true, false, NSS_STATUS_SUCCESS, NULL, { NULL, 0, 0},
+		{ NULL, NULL, 0, 0, 0, 0, 0, 0, 0}};
+
+  if (name[0] == '-' || name[0] == '+')
+    return NSS_STATUS_NOTFOUND;
+
+  __libc_lock_lock (lock);
+
+  if (ni == NULL)
+    init_nss_interface ();
+
+  __libc_lock_unlock (lock);
+
+  result = internal_setspent (&ent, 0, 0);
+
+  if (result == NSS_STATUS_SUCCESS)
+    result = internal_getspnam_r (name, pwd, &ent, buffer, buflen, errnop);
+
+  internal_endspent (&ent);
+
+  return result;
+}
+
+
+/* Support routines for remembering -@netgroup and -user entries.
+   The names are stored in a single string with `|' as separator. */
+static void
+blacklist_store_name (const char *name, ent_t *ent)
+{
+  int namelen = strlen (name);
+  char *tmp;
+
+  /* first call, setup cache */
+  if (ent->blacklist.size == 0)
+    {
+      ent->blacklist.size = MAX (BLACKLIST_INITIAL_SIZE, 2 * namelen);
+      ent->blacklist.data = malloc (ent->blacklist.size);
+      if (ent->blacklist.data == NULL)
+	return;
+      ent->blacklist.data[0] = '|';
+      ent->blacklist.data[1] = '\0';
+      ent->blacklist.current = 1;
+    }
+  else
+    {
+      if (in_blacklist (name, namelen, ent))
+	return;			/* no duplicates */
+
+      if (ent->blacklist.current + namelen + 1 >= ent->blacklist.size)
+	{
+	  ent->blacklist.size += MAX (BLACKLIST_INCREMENT, 2 * namelen);
+	  tmp = realloc (ent->blacklist.data, ent->blacklist.size);
+	  if (tmp == NULL)
+	    {
+	      free (ent->blacklist.data);
+	      ent->blacklist.size = 0;
+	      return;
+	    }
+	  ent->blacklist.data = tmp;
+	}
+    }
+
+  tmp = stpcpy (ent->blacklist.data + ent->blacklist.current, name);
+  *tmp++ = '|';
+  *tmp = '\0';
+  ent->blacklist.current += namelen + 1;
+
+  return;
+}
+
+
+/* Returns TRUE if ent->blacklist contains name, else FALSE.  */
+static bool_t
+in_blacklist (const char *name, int namelen, ent_t *ent)
+{
+  char buf[namelen + 3];
+  char *cp;
+
+  if (ent->blacklist.data == NULL)
+    return false;
+
+  buf[0] = '|';
+  cp = stpcpy (&buf[1], name);
+  *cp++ = '|';
+  *cp = '\0';
+  return strstr (ent->blacklist.data, buf) != NULL;
+}
diff --git a/REORG.TODO/nis/nss_nis/nis-alias.c b/REORG.TODO/nis/nss_nis/nis-alias.c
new file mode 100644
index 0000000000..c9c89db6ce
--- /dev/null
+++ b/REORG.TODO/nis/nss_nis/nis-alias.c
@@ -0,0 +1,281 @@
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <nss.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <aliases.h>
+#include <libc-lock.h>
+#include <rpcsvc/yp.h>
+#include <rpcsvc/ypclnt.h>
+
+#include "nss-nis.h"
+
+__libc_lock_define_initialized (static, lock)
+
+static bool_t new_start = 1;
+static char *oldkey;
+static int oldkeylen;
+
+static int
+_nss_nis_parse_aliasent (const char *key, char *alias, struct aliasent *result,
+			 char *buffer, size_t buflen, int *errnop)
+{
+  char *first_unused = buffer + strlen (alias) + 1;
+  size_t room_left =
+    buflen - (buflen % __alignof__ (char *)) - strlen (alias) - 2;
+  char *line;
+  char *cp;
+
+  result->alias_members_len = 0;
+  *first_unused = '\0';
+  first_unused++;
+  strcpy (first_unused, key);
+
+  if (first_unused[room_left - 1] != '\0')
+    {
+      /* The line is too long for our buffer.  */
+    no_more_room:
+      *errnop = ERANGE;
+      return -1;
+    }
+
+  result->alias_name = first_unused;
+
+  /* Terminate the line for any case.  */
+  cp = strpbrk (alias, "#\n");
+  if (cp != NULL)
+    *cp = '\0';
+
+  first_unused += strlen (result->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 *));
+  result->alias_members = (char **) first_unused;
+
+  line = alias;
+
+  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 *);
+      result->alias_members[result->alias_members_len] = line;
+
+      while (*line != '\0' && *line != ',')
+	line++;
+
+      if (line != result->alias_members[result->alias_members_len])
+	{
+	  *line = '\0';
+	  line++;
+	  result->alias_members_len++;
+	}
+    }
+  return result->alias_members_len == 0 ? 0 : 1;
+}
+
+enum nss_status
+_nss_nis_setaliasent (void)
+{
+  __libc_lock_lock (lock);
+
+  new_start = 1;
+  if (oldkey != NULL)
+    {
+      free (oldkey);
+      oldkey = NULL;
+      oldkeylen = 0;
+    }
+
+  __libc_lock_unlock (lock);
+
+  return NSS_STATUS_SUCCESS;
+}
+/* The 'endaliasent' function is identical.  */
+strong_alias (_nss_nis_setaliasent, _nss_nis_endaliasent)
+
+static enum nss_status
+internal_nis_getaliasent_r (struct aliasent *alias, char *buffer,
+			    size_t buflen, int *errnop)
+{
+  char *domain;
+
+  if (__glibc_unlikely (yp_get_default_domain (&domain)))
+    return NSS_STATUS_UNAVAIL;
+
+  alias->alias_local = 0;
+
+  /* Get the next entry until we found a correct one. */
+  int parse_res;
+  do
+    {
+      char *result;
+      int len;
+      char *outkey;
+      int keylen;
+      int yperr;
+
+      if (new_start)
+	yperr = yp_first (domain, "mail.aliases", &outkey, &keylen, &result,
+			  &len);
+      else
+	yperr = yp_next (domain, "mail.aliases", oldkey, oldkeylen, &outkey,
+			 &keylen, &result, &len);
+
+      if (__glibc_unlikely (yperr != YPERR_SUCCESS))
+	{
+	  enum nss_status retval = yperr2nss (yperr);
+
+	  if (retval == NSS_STATUS_TRYAGAIN)
+	    *errnop = errno;
+	  return retval;
+	}
+
+      if (__glibc_unlikely ((size_t) (len + 1) > buflen))
+	{
+	  free (result);
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+      char *p = strncpy (buffer, result, len);
+      buffer[len] = '\0';
+      while (isspace (*p))
+	++p;
+      free (result);
+
+      parse_res = _nss_nis_parse_aliasent (outkey, p, alias, buffer,
+					   buflen, errnop);
+      if (__glibc_unlikely (parse_res == -1))
+	{
+	  free (outkey);
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+
+      free (oldkey);
+      oldkey = outkey;
+      oldkeylen = keylen;
+      new_start = 0;
+    }
+  while (!parse_res);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nis_getaliasent_r (struct aliasent *alias, char *buffer, size_t buflen,
+			int *errnop)
+{
+  enum nss_status status;
+
+  __libc_lock_lock (lock);
+
+  status = internal_nis_getaliasent_r (alias, buffer, buflen, errnop);
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+enum nss_status
+_nss_nis_getaliasbyname_r (const char *name, struct aliasent *alias,
+			   char *buffer, size_t buflen, int *errnop)
+{
+  if (name == NULL)
+    {
+      *errnop = EINVAL;
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  char *domain;
+  if (__glibc_unlikely (yp_get_default_domain (&domain)))
+    return NSS_STATUS_UNAVAIL;
+
+  size_t namlen = strlen (name);
+  char *name2;
+  int use_alloca = __libc_use_alloca (namlen + 1);
+  if (use_alloca)
+    name2 = __alloca (namlen + 1);
+  else
+    {
+      name2 = malloc (namlen + 1);
+      if (name2 == NULL)
+	{
+	  *errnop = ENOMEM;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+    }
+
+  /* Convert name to lowercase.  */
+  size_t i;
+  for (i = 0; i < namlen; ++i)
+    name2[i] = _tolower (name[i]);
+  name2[i] = '\0';
+
+  char *result;
+  int len;
+  int yperr = yp_match (domain, "mail.aliases", name2, namlen, &result, &len);
+
+  if (!use_alloca)
+    free (name2);
+
+  if (__glibc_unlikely (yperr != YPERR_SUCCESS))
+    {
+      enum nss_status retval = yperr2nss (yperr);
+
+      if (retval == NSS_STATUS_TRYAGAIN)
+	*errnop = errno;
+      return retval;
+    }
+
+  if (__glibc_unlikely ((size_t) (len + 1) > buflen))
+    {
+      free (result);
+      *errnop = ERANGE;
+      return NSS_STATUS_TRYAGAIN;
+    }
+
+  char *p = strncpy (buffer, result, len);
+  buffer[len] = '\0';
+  while (isspace (*p))
+    ++p;
+  free (result);
+
+  alias->alias_local = 0;
+  int parse_res = _nss_nis_parse_aliasent (name, p, alias, buffer, buflen,
+					   errnop);
+  if (__glibc_unlikely (parse_res < 1))
+    {
+      if (parse_res == -1)
+	return NSS_STATUS_TRYAGAIN;
+      else
+	return NSS_STATUS_NOTFOUND;
+    }
+
+  return NSS_STATUS_SUCCESS;
+}
diff --git a/REORG.TODO/nis/nss_nis/nis-ethers.c b/REORG.TODO/nis/nss_nis/nis-ethers.c
new file mode 100644
index 0000000000..2a466626e8
--- /dev/null
+++ b/REORG.TODO/nis/nss_nis/nis-ethers.c
@@ -0,0 +1,292 @@
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <nss.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <libc-lock.h>
+#include <rpcsvc/yp.h>
+#include <rpcsvc/ypclnt.h>
+#include <netinet/ether.h>
+#include <netinet/if_ether.h>
+
+#include "nss-nis.h"
+
+/* Protect global state against multiple changers */
+__libc_lock_define_initialized (static, lock)
+
+/* Get the declaration of the parser function.  */
+#define ENTNAME etherent
+#define STRUCTURE etherent
+#define EXTERN_PARSER
+#include <nss/nss_files/files-parse.c>
+
+struct response
+{
+  struct response *next;
+  char val[0];
+};
+
+static struct response *start;
+static struct response *next;
+
+static int
+saveit (int instatus, char *inkey, int inkeylen, char *inval,
+	int invallen, char *indata)
+{
+  if (instatus != YP_TRUE)
+    return 1;
+
+  if (inkey && inkeylen > 0 && inval && invallen > 0)
+    {
+      struct response *newp = malloc (sizeof (struct response) + invallen + 1);
+      if (newp == NULL)
+	return 1; /* We have no error code for out of memory */
+
+      if (start == NULL)
+	start = newp;
+      else
+	next->next = newp;
+      next = newp;
+
+      newp->next = NULL;
+      *((char *) mempcpy (newp->val, inval, invallen)) = '\0';
+    }
+
+  return 0;
+}
+
+static void
+internal_nis_endetherent (void)
+{
+  while (start != NULL)
+    {
+      next = start;
+      start = start->next;
+      free (next);
+    }
+}
+
+enum nss_status
+_nss_nis_endetherent (void)
+{
+  __libc_lock_lock (lock);
+
+  internal_nis_endetherent ();
+  next = NULL;
+
+  __libc_lock_unlock (lock);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+static enum nss_status
+internal_nis_setetherent (void)
+{
+  char *domainname;
+  struct ypall_callback ypcb;
+  enum nss_status status;
+
+  yp_get_default_domain (&domainname);
+
+  internal_nis_endetherent ();
+
+  ypcb.foreach = saveit;
+  ypcb.data = NULL;
+  status = yperr2nss (yp_all (domainname, "ethers.byname", &ypcb));
+  next = start;
+
+  return status;
+}
+
+enum nss_status
+_nss_nis_setetherent (int stayopen)
+{
+  enum nss_status result;
+
+  __libc_lock_lock (lock);
+
+  result = internal_nis_setetherent ();
+
+  __libc_lock_unlock (lock);
+
+  return result;
+}
+
+static enum nss_status
+internal_nis_getetherent_r (struct etherent *eth, char *buffer, size_t buflen,
+			    int *errnop)
+{
+  struct parser_data *data = (void *) buffer;
+  int parse_res;
+
+  if (start == NULL)
+    internal_nis_setetherent ();
+
+  /* Get the next entry until we found a correct one. */
+  do
+    {
+      char *p;
+
+      if (next == NULL)
+	return NSS_STATUS_NOTFOUND;
+
+      p = strncpy (buffer, next->val, buflen);
+
+      while (isspace (*p))
+        ++p;
+
+      parse_res = _nss_files_parse_etherent (p, eth, data, buflen, errnop);
+      if (parse_res == -1)
+	return NSS_STATUS_TRYAGAIN;
+      next = next->next;
+    }
+  while (!parse_res);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nis_getetherent_r (struct etherent *result, char *buffer, size_t buflen,
+			int *errnop)
+{
+  int status;
+
+  __libc_lock_lock (lock);
+
+  status = internal_nis_getetherent_r (result, buffer, buflen, errnop);
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+enum nss_status
+_nss_nis_gethostton_r (const char *name, struct etherent *eth,
+		       char *buffer, size_t buflen, int *errnop)
+{
+  if (name == NULL)
+    {
+      *errnop = EINVAL;
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  char *domain;
+  if (__glibc_unlikely (yp_get_default_domain (&domain)))
+    return NSS_STATUS_UNAVAIL;
+
+  char *result;
+  int len;
+  int yperr = yp_match (domain, "ethers.byname", name, strlen (name), &result,
+			&len);
+
+  if (__glibc_unlikely (yperr != YPERR_SUCCESS))
+    {
+      enum nss_status retval = yperr2nss (yperr);
+
+      if (retval == NSS_STATUS_TRYAGAIN)
+        *errnop = errno;
+      return retval;
+    }
+
+  if (__glibc_unlikely ((size_t) (len + 1) > buflen))
+    {
+      free (result);
+      *errnop = ERANGE;
+      return NSS_STATUS_TRYAGAIN;
+    }
+
+  char *p = strncpy (buffer, result, len);
+  buffer[len] = '\0';
+  while (isspace (*p))
+    ++p;
+  free (result);
+
+  int parse_res = _nss_files_parse_etherent (p, eth, (void *) buffer, buflen,
+					     errnop);
+  if (__glibc_unlikely (parse_res < 1))
+    {
+      if (parse_res == -1)
+	return NSS_STATUS_TRYAGAIN;
+      else
+	return NSS_STATUS_NOTFOUND;
+    }
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nis_getntohost_r (const struct ether_addr *addr, struct etherent *eth,
+		       char *buffer, size_t buflen, int *errnop)
+{
+  if (addr == NULL)
+    {
+      *errnop = EINVAL;
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  char *domain;
+  if (__glibc_unlikely (yp_get_default_domain (&domain)))
+    return NSS_STATUS_UNAVAIL;
+
+  char buf[33];
+  int nlen = snprintf (buf, sizeof (buf), "%x:%x:%x:%x:%x:%x",
+		      (int) addr->ether_addr_octet[0],
+		      (int) addr->ether_addr_octet[1],
+		      (int) addr->ether_addr_octet[2],
+		      (int) addr->ether_addr_octet[3],
+		      (int) addr->ether_addr_octet[4],
+		      (int) addr->ether_addr_octet[5]);
+
+  char *result;
+  int len;
+  int yperr = yp_match (domain, "ethers.byaddr", buf, nlen, &result, &len);
+
+  if (__glibc_unlikely (yperr != YPERR_SUCCESS))
+    {
+      enum nss_status retval = yperr2nss (yperr);
+
+      if (retval == NSS_STATUS_TRYAGAIN)
+        *errnop = errno;
+      return retval;
+    }
+
+  if (__glibc_unlikely ((size_t) (len + 1) > buflen))
+    {
+      free (result);
+      *errnop = ERANGE;
+      return NSS_STATUS_TRYAGAIN;
+    }
+
+  char *p = strncpy (buffer, result, len);
+  buffer[len] = '\0';
+  while (isspace (*p))
+    ++p;
+  free (result);
+
+  int parse_res = _nss_files_parse_etherent (p, eth, (void *) buffer, buflen,
+					     errnop);
+  if (__glibc_unlikely (parse_res < 1))
+    {
+      if (parse_res == -1)
+	return NSS_STATUS_TRYAGAIN;
+      else
+	return NSS_STATUS_NOTFOUND;
+    }
+  return NSS_STATUS_SUCCESS;
+}
diff --git a/REORG.TODO/nis/nss_nis/nis-grp.c b/REORG.TODO/nis/nss_nis/nis-grp.c
new file mode 100644
index 0000000000..05b33920fc
--- /dev/null
+++ b/REORG.TODO/nis/nss_nis/nis-grp.c
@@ -0,0 +1,359 @@
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <ctype.h>
+#include <errno.h>
+#include <grp.h>
+#include <nss.h>
+#include <string.h>
+#include <libc-lock.h>
+#include <rpcsvc/yp.h>
+#include <rpcsvc/ypclnt.h>
+
+#include "nss-nis.h"
+#include <libnsl.h>
+
+/* Get the declaration of the parser function.  */
+#define ENTNAME grent
+#define STRUCTURE group
+#define EXTERN_PARSER
+#include <nss/nss_files/files-parse.c>
+
+/* Protect global state against multiple changers */
+__libc_lock_define_initialized (static, lock)
+
+static bool_t new_start = 1;
+static char *oldkey;
+static int oldkeylen;
+static intern_t intern;
+
+
+static void
+internal_nis_endgrent (void)
+{
+  new_start = 1;
+  if (oldkey != NULL)
+    {
+      free (oldkey);
+      oldkey = NULL;
+      oldkeylen = 0;
+    }
+
+  struct response_t *curr = intern.start;
+
+  while (curr != NULL)
+    {
+      struct response_t *last = curr;
+      curr = curr->next;
+      free (last);
+    }
+
+  intern.next = intern.start = NULL;
+}
+
+
+enum nss_status
+_nss_nis_endgrent (void)
+{
+  __libc_lock_lock (lock);
+
+  internal_nis_endgrent ();
+
+  __libc_lock_unlock (lock);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+
+enum nss_status
+internal_nis_setgrent (void)
+{
+  /* We have to read all the data now.  */
+  char *domain;
+  if (__glibc_unlikely (yp_get_default_domain (&domain)))
+    return NSS_STATUS_UNAVAIL;
+
+  struct ypall_callback ypcb;
+
+  ypcb.foreach = _nis_saveit;
+  ypcb.data = (char *) &intern;
+  enum nss_status status = yperr2nss (yp_all (domain, "group.byname", &ypcb));
+
+
+  /* Mark the last buffer as full.  */
+  if (intern.next != NULL)
+    intern.next->size = intern.offset;
+
+  intern.next = intern.start;
+  intern.offset = 0;
+
+  return status;
+}
+
+
+enum nss_status
+_nss_nis_setgrent (int stayopen)
+{
+  enum nss_status result = NSS_STATUS_SUCCESS;
+
+  __libc_lock_lock (lock);
+
+  internal_nis_endgrent ();
+
+  if (_nsl_default_nss () & NSS_FLAG_SETENT_BATCH_READ)
+    result = internal_nis_setgrent ();
+
+  __libc_lock_unlock (lock);
+
+  return result;
+}
+
+
+static enum nss_status
+internal_nis_getgrent_r (struct group *grp, char *buffer, size_t buflen,
+			 int *errnop)
+{
+  /* If we read the entire database at setpwent time we just iterate
+     over the data we have in memory.  */
+  bool batch_read = intern.start != NULL;
+
+  char *domain = NULL;
+  if (!batch_read && __builtin_expect (yp_get_default_domain (&domain), 0))
+    return NSS_STATUS_UNAVAIL;
+
+  /* Get the next entry until we found a correct one. */
+  int parse_res;
+  do
+    {
+      char *result;
+      char *outkey;
+      int len;
+      int keylen;
+
+      if (batch_read)
+	{
+	  struct response_t *bucket;
+
+	handle_batch_read:
+	  bucket = intern.next;
+
+	  if (__glibc_unlikely (intern.offset >= bucket->size))
+	    {
+	      if (bucket->next == NULL)
+		return NSS_STATUS_NOTFOUND;
+
+	      /* We look at all the content in the current bucket.  Go on
+		 to the next.  */
+	      bucket = intern.next = bucket->next;
+	      intern.offset = 0;
+	    }
+
+	  for (result = &bucket->mem[intern.offset]; isspace (*result);
+	       ++result)
+	    ++intern.offset;
+
+	  len = strlen (result);
+	}
+      else
+	{
+	  int yperr;
+
+	  if (new_start)
+	    {
+	      /* Maybe we should read the database in one piece.  */
+	      if ((_nsl_default_nss () & NSS_FLAG_SETENT_BATCH_READ)
+		  && internal_nis_setgrent () == NSS_STATUS_SUCCESS
+		  && intern.start != NULL)
+		{
+		  batch_read = true;
+		  goto handle_batch_read;
+		}
+
+	      yperr = yp_first (domain, "group.byname", &outkey, &keylen,
+				&result, &len);
+	    }
+	  else
+	    yperr = yp_next (domain, "group.byname", oldkey, oldkeylen,
+			     &outkey, &keylen, &result, &len);
+
+	  if (__glibc_unlikely (yperr != YPERR_SUCCESS))
+	    {
+	      enum nss_status retval = yperr2nss (yperr);
+
+	      if (retval == NSS_STATUS_TRYAGAIN)
+		*errnop = errno;
+	      return retval;
+	    }
+	}
+
+      if (__glibc_unlikely ((size_t) (len + 1) > buflen))
+	{
+	  if (!batch_read)
+	    free (result);
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+
+      char *p = strncpy (buffer, result, len);
+      buffer[len] = '\0';
+      while (isspace (*p))
+	++p;
+      if (!batch_read)
+	free (result);
+
+      parse_res = _nss_files_parse_grent (p, grp, (void *) buffer, buflen,
+					  errnop);
+      if (__glibc_unlikely (parse_res == -1))
+	{
+	  if (!batch_read)
+	    free (outkey);
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+
+      if (batch_read)
+	intern.offset += len + 1;
+      else
+	{
+	  free (oldkey);
+	  oldkey = outkey;
+	  oldkeylen = keylen;
+	  new_start = 0;
+	}
+    }
+  while (parse_res < 1);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nis_getgrent_r (struct group *result, char *buffer, size_t buflen,
+		     int *errnop)
+{
+  int status;
+
+  __libc_lock_lock (lock);
+
+  status = internal_nis_getgrent_r (result, buffer, buflen, errnop);
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+enum nss_status
+_nss_nis_getgrnam_r (const char *name, struct group *grp,
+		     char *buffer, size_t buflen, int *errnop)
+{
+  if (name == NULL)
+    {
+      *errnop = EINVAL;
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  char *domain;
+  if (__glibc_unlikely (yp_get_default_domain (&domain)))
+    return NSS_STATUS_UNAVAIL;
+
+  char *result;
+  int len;
+  int yperr = yp_match (domain, "group.byname", name, strlen (name), &result,
+			&len);
+
+  if (__glibc_unlikely (yperr != YPERR_SUCCESS))
+    {
+      enum nss_status retval = yperr2nss (yperr);
+
+      if (retval == NSS_STATUS_TRYAGAIN)
+	*errnop = errno;
+      return retval;
+    }
+
+  if (__glibc_unlikely ((size_t) (len + 1) > buflen))
+    {
+      free (result);
+      *errnop = ERANGE;
+      return NSS_STATUS_TRYAGAIN;
+    }
+
+  char *p = strncpy (buffer, result, len);
+  buffer[len] = '\0';
+  while (isspace (*p))
+    ++p;
+  free (result);
+
+  int parse_res = _nss_files_parse_grent (p, grp, (void *) buffer, buflen,
+					  errnop);
+  if (__builtin_expect  (parse_res < 1, 0))
+    {
+      if (parse_res == -1)
+	return NSS_STATUS_TRYAGAIN;
+      else
+	return NSS_STATUS_NOTFOUND;
+    }
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nis_getgrgid_r (gid_t gid, struct group *grp,
+		     char *buffer, size_t buflen, int *errnop)
+{
+  char *domain;
+  if (__glibc_unlikely (yp_get_default_domain (&domain)))
+    return NSS_STATUS_UNAVAIL;
+
+  char buf[32];
+  int nlen = sprintf (buf, "%lu", (unsigned long int) gid);
+
+  char *result;
+  int len;
+  int yperr = yp_match (domain, "group.bygid", buf, nlen, &result, &len);
+
+  if (__glibc_unlikely (yperr != YPERR_SUCCESS))
+    {
+      enum nss_status retval = yperr2nss (yperr);
+
+      if (retval == NSS_STATUS_TRYAGAIN)
+	*errnop = errno;
+      return retval;
+    }
+
+  if (__glibc_unlikely ((size_t) (len + 1) > buflen))
+    {
+      free (result);
+      *errnop = ERANGE;
+      return NSS_STATUS_TRYAGAIN;
+    }
+
+  char *p = strncpy (buffer, result, len);
+  buffer[len] = '\0';
+  while (isspace (*p))
+    ++p;
+  free (result);
+
+  int parse_res = _nss_files_parse_grent (p, grp, (void *) buffer, buflen,
+					  errnop);
+  if (__glibc_unlikely (parse_res < 1))
+    {
+      if (parse_res == -1)
+	return NSS_STATUS_TRYAGAIN;
+      else
+	return NSS_STATUS_NOTFOUND;
+    }
+  return NSS_STATUS_SUCCESS;
+}
diff --git a/REORG.TODO/nis/nss_nis/nis-hosts.c b/REORG.TODO/nis/nss_nis/nis-hosts.c
new file mode 100644
index 0000000000..f64dbdaecb
--- /dev/null
+++ b/REORG.TODO/nis/nss_nis/nis-hosts.c
@@ -0,0 +1,567 @@
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <assert.h>
+#include <nss.h>
+#include <ctype.h>
+/* The following is an ugly trick to avoid a prototype declaration for
+   _nss_nis_endgrent.  */
+#define _nss_nis_endhostent _nss_nis_endhostent_XXX
+#include <netdb.h>
+#undef _nss_nis_endhostent
+#include <string.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <resolv/resolv-internal.h>
+#include <libc-lock.h>
+#include <rpcsvc/yp.h>
+#include <rpcsvc/ypclnt.h>
+
+#include "nss-nis.h"
+
+/* Get implementation for some internal functions. */
+#include <resolv/mapv4v6addr.h>
+
+#define ENTNAME         hostent
+#define DATABASE        "hosts"
+#define NEED_H_ERRNO
+
+#define EXTRA_ARGS      , af, flags
+#define EXTRA_ARGS_DECL , int af, int flags
+
+#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);
+
+   assert (af == AF_INET || af == AF_INET6 || af == AF_UNSPEC);
+
+   /* Parse address.  */
+   if (af != AF_INET6 && inet_pton (AF_INET, addr, entdata->host_addr) > 0)
+     {
+       assert ((flags & AI_V4MAPPED) == 0 || af != AF_UNSPEC);
+       if (flags & AI_V4MAPPED)
+	 {
+	   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 if (af != AF_INET
+	    && inet_pton (AF_INET6, addr, entdata->host_addr) > 0)
+     {
+       result->h_addrtype = AF_INET6;
+       result->h_length = IN6ADDRSZ;
+     }
+   else
+     /* Illegal address: ignore line.  */
+     return 0;
+
+   /* Store a pointer to the address in the expected form.  */
+   entdata->h_addr_ptrs[0] = (char *) entdata->host_addr;
+   entdata->h_addr_ptrs[1] = NULL;
+   result->h_addr_list = entdata->h_addr_ptrs;
+
+   STRING_FIELD (result->h_name, isspace, 1);
+ })
+
+
+__libc_lock_define_initialized (static, lock)
+
+static bool_t new_start = 1;
+static char *oldkey = NULL;
+static int oldkeylen = 0;
+
+
+enum nss_status
+_nss_nis_sethostent (int stayopen)
+{
+  __libc_lock_lock (lock);
+
+  new_start = 1;
+  if (oldkey != NULL)
+    {
+      free (oldkey);
+      oldkey = NULL;
+      oldkeylen = 0;
+    }
+
+  __libc_lock_unlock (lock);
+
+  return NSS_STATUS_SUCCESS;
+}
+/* Make _nss_nis_endhostent an alias of _nss_nis_sethostent.  We do this
+   even though the prototypes don't match.  The argument of sethostent
+   is used so this makes no difference.  */
+strong_alias (_nss_nis_sethostent, _nss_nis_endhostent)
+
+
+/* The calling function always need to get a lock first. */
+static enum nss_status
+internal_nis_gethostent_r (struct hostent *host, char *buffer,
+			   size_t buflen, int *errnop, int *h_errnop,
+			   int af, int flags)
+{
+  char *domain;
+  if (__glibc_unlikely (yp_get_default_domain (&domain)))
+    return NSS_STATUS_UNAVAIL;
+
+  uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct parser_data);
+  buffer += pad;
+
+  struct parser_data *data = (void *) buffer;
+  if (__glibc_unlikely (buflen < sizeof *data + 1 + pad))
+    {
+      *errnop = ERANGE;
+      *h_errnop = NETDB_INTERNAL;
+      return NSS_STATUS_TRYAGAIN;
+    }
+  buflen -= pad;
+
+  /* Get the next entry until we found a correct one. */
+  const size_t linebuflen = buffer + buflen - data->linebuffer;
+  int parse_res;
+  do
+    {
+      char *result;
+      int len;
+      char *outkey;
+      int keylen;
+      int yperr;
+      if (new_start)
+	yperr = yp_first (domain, "hosts.byname", &outkey, &keylen, &result,
+			  &len);
+      else
+	yperr = yp_next (domain, "hosts.byname", oldkey, oldkeylen, &outkey,
+			 &keylen, &result, &len);
+
+      if (__glibc_unlikely (yperr != YPERR_SUCCESS))
+	{
+	  enum nss_status retval = yperr2nss (yperr);
+
+	  switch (retval)
+	    {
+	    case NSS_STATUS_TRYAGAIN:
+	      *errnop = errno;
+	      *h_errnop = TRY_AGAIN;
+	      break;
+	    case NSS_STATUS_NOTFOUND:
+	      *h_errnop = HOST_NOT_FOUND;
+	      break;
+	    default:
+	      *h_errnop = NO_RECOVERY;
+	      break;
+	    }
+	  return retval;
+	}
+
+      if (__glibc_unlikely ((size_t) (len + 1) > linebuflen))
+	{
+	  free (result);
+	  *h_errnop = NETDB_INTERNAL;
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+
+      char *p = strncpy (data->linebuffer, result, len);
+      data->linebuffer[len] = '\0';
+      while (isspace (*p))
+	++p;
+      free (result);
+
+      parse_res = parse_line (p, host, data, buflen, errnop, af, flags);
+      if (__glibc_unlikely (parse_res == -1))
+	{
+	  free (outkey);
+	  *h_errnop = NETDB_INTERNAL;
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+      free (oldkey);
+      oldkey = outkey;
+      oldkeylen = keylen;
+      new_start = 0;
+    }
+  while (!parse_res);
+
+  *h_errnop = NETDB_SUCCESS;
+  return NSS_STATUS_SUCCESS;
+}
+
+
+enum nss_status
+_nss_nis_gethostent_r (struct hostent *host, char *buffer, size_t buflen,
+		       int *errnop, int *h_errnop)
+{
+  enum nss_status status;
+
+  __libc_lock_lock (lock);
+
+  status = internal_nis_gethostent_r (host, buffer, buflen, errnop, h_errnop,
+			(res_use_inet6 () ? AF_INET6 : AF_INET),
+			(res_use_inet6 () ? AI_V4MAPPED : 0 ));
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+
+static enum nss_status
+internal_gethostbyname2_r (const char *name, int af, struct hostent *host,
+			   char *buffer, size_t buflen, int *errnop,
+			   int *h_errnop, int flags)
+{
+  uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct parser_data);
+  buffer += pad;
+
+  struct parser_data *data = (void *) buffer;
+
+  if (name == NULL)
+    {
+      *errnop = EINVAL;
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  char *domain;
+  if (yp_get_default_domain (&domain))
+    return NSS_STATUS_UNAVAIL;
+
+  if (buflen < sizeof *data + 1 + pad)
+    {
+      *h_errnop = NETDB_INTERNAL;
+      *errnop = ERANGE;
+      return NSS_STATUS_TRYAGAIN;
+    }
+  buflen -= pad;
+
+  /* Convert name to lowercase.  */
+  size_t namlen = strlen (name);
+  /* Limit name length to the maximum size of an RPC packet.  */
+  if (namlen > UDPMSGSIZE)
+    {
+      *errnop = ERANGE;
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  char name2[namlen + 1];
+  size_t i;
+
+  for (i = 0; i < namlen; ++i)
+    name2[i] = tolower (name[i]);
+  name2[i] = '\0';
+
+  char *result;
+  int len;
+  int yperr = yp_match (domain, "hosts.byname", name2, namlen, &result, &len);
+
+  if (__glibc_unlikely (yperr != YPERR_SUCCESS))
+    {
+      enum nss_status retval = yperr2nss (yperr);
+
+      if (retval == NSS_STATUS_TRYAGAIN)
+	{
+	  *h_errnop = TRY_AGAIN;
+	  *errnop = errno;
+	}
+      if (retval == NSS_STATUS_NOTFOUND)
+	*h_errnop = HOST_NOT_FOUND;
+      return retval;
+    }
+
+  const size_t linebuflen = buffer + buflen - data->linebuffer;
+  if (__glibc_unlikely ((size_t) (len + 1) > linebuflen))
+    {
+      free (result);
+      *h_errnop = NETDB_INTERNAL;
+      *errnop = ERANGE;
+      return NSS_STATUS_TRYAGAIN;
+    }
+
+  char *p = strncpy (data->linebuffer, result, len);
+  data->linebuffer[len] = '\0';
+  while (isspace (*p))
+    ++p;
+  free (result);
+
+  int parse_res = parse_line (p, host, data, buflen, errnop, af, flags);
+
+  if (__glibc_unlikely (parse_res < 1 || host->h_addrtype != af))
+    {
+      if (parse_res == -1)
+	{
+	  *h_errnop = NETDB_INTERNAL;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+      else
+	{
+	  *h_errnop = HOST_NOT_FOUND;
+	  return NSS_STATUS_NOTFOUND;
+	}
+    }
+
+  *h_errnop = NETDB_SUCCESS;
+  return NSS_STATUS_SUCCESS;
+}
+
+
+enum nss_status
+_nss_nis_gethostbyname2_r (const char *name, int af, struct hostent *host,
+			   char *buffer, size_t buflen, int *errnop,
+			   int *h_errnop)
+{
+  if (af != AF_INET && af != AF_INET6)
+    {
+      *h_errnop = HOST_NOT_FOUND;
+      return NSS_STATUS_NOTFOUND;
+    }
+
+  return internal_gethostbyname2_r (name, af, host, buffer, buflen, errnop,
+				    h_errnop,
+			(res_use_inet6 () ? AI_V4MAPPED : 0));
+}
+
+
+enum nss_status
+_nss_nis_gethostbyname_r (const char *name, struct hostent *host, char *buffer,
+			  size_t buflen, int *errnop, int *h_errnop)
+{
+  if (res_use_inet6 ())
+    {
+      enum nss_status status;
+
+      status = internal_gethostbyname2_r (name, AF_INET6, host, buffer, buflen,
+					  errnop, h_errnop, AI_V4MAPPED);
+      if (status == NSS_STATUS_SUCCESS)
+	return status;
+    }
+
+  return internal_gethostbyname2_r (name, AF_INET, host, buffer, buflen,
+				    errnop, h_errnop, 0);
+}
+
+
+enum nss_status
+_nss_nis_gethostbyaddr_r (const void *addr, socklen_t addrlen, int af,
+			  struct hostent *host, char *buffer, size_t buflen,
+			  int *errnop, int *h_errnop)
+{
+  char *domain;
+  if (__glibc_unlikely (yp_get_default_domain (&domain)))
+    return NSS_STATUS_UNAVAIL;
+
+  uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct parser_data);
+  buffer += pad;
+
+  struct parser_data *data = (void *) buffer;
+  if (__glibc_unlikely (buflen < sizeof *data + 1 + pad))
+    {
+      *errnop = ERANGE;
+      *h_errnop = NETDB_INTERNAL;
+      return NSS_STATUS_TRYAGAIN;
+    }
+  buflen -= pad;
+
+  char *buf = inet_ntoa (*(const struct in_addr *) addr);
+
+  char *result;
+  int len;
+  int yperr = yp_match (domain, "hosts.byaddr", buf, strlen (buf), &result,
+			&len);
+
+  if (__glibc_unlikely (yperr != YPERR_SUCCESS))
+    {
+      enum nss_status retval = yperr2nss (yperr);
+
+      if (retval == NSS_STATUS_TRYAGAIN)
+	{
+	  *h_errnop = TRY_AGAIN;
+	  *errnop = errno;
+	}
+      else if (retval == NSS_STATUS_NOTFOUND)
+	*h_errnop = HOST_NOT_FOUND;
+
+      return retval;
+    }
+
+  const size_t linebuflen = buffer + buflen - data->linebuffer;
+  if (__glibc_unlikely ((size_t) (len + 1) > linebuflen))
+    {
+      free (result);
+      *errnop = ERANGE;
+      *h_errnop = NETDB_INTERNAL;
+      return NSS_STATUS_TRYAGAIN;
+    }
+
+  char *p = strncpy (data->linebuffer, result, len);
+  data->linebuffer[len] = '\0';
+  while (isspace (*p))
+    ++p;
+  free (result);
+
+  int parse_res = parse_line (p, host, data, buflen, errnop, af,
+			      (res_use_inet6 () ? AI_V4MAPPED : 0));
+  if (__glibc_unlikely (parse_res < 1))
+    {
+      if (parse_res == -1)
+	{
+	  *h_errnop = NETDB_INTERNAL;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+      else
+	{
+	  *h_errnop = HOST_NOT_FOUND;
+	  return NSS_STATUS_NOTFOUND;
+	}
+    }
+
+  *h_errnop = NETDB_SUCCESS;
+  return NSS_STATUS_SUCCESS;
+}
+
+
+enum nss_status
+_nss_nis_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
+			   char *buffer, size_t buflen, int *errnop,
+			   int *herrnop, int32_t *ttlp)
+{
+  char *domain;
+  if (yp_get_default_domain (&domain))
+    {
+      *herrnop = NO_DATA;
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  /* Convert name to lowercase.  */
+  size_t namlen = strlen (name);
+  /* Limit name length to the maximum size of an RPC packet.  */
+  if (namlen > UDPMSGSIZE)
+    {
+      *errnop = ERANGE;
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  char name2[namlen + 1];
+  size_t i;
+
+  for (i = 0; i < namlen; ++i)
+    name2[i] = tolower (name[i]);
+  name2[i] = '\0';
+
+  char *result;
+  int len;
+  int yperr = yp_match (domain, "hosts.byname", name2, namlen, &result, &len);
+
+  if (__glibc_unlikely (yperr != YPERR_SUCCESS))
+    {
+      enum nss_status retval = yperr2nss (yperr);
+
+      if (retval == NSS_STATUS_TRYAGAIN)
+	{
+	  *herrnop = TRY_AGAIN;
+	  *errnop = errno;
+	}
+      if (retval == NSS_STATUS_NOTFOUND)
+	*herrnop = HOST_NOT_FOUND;
+      return retval;
+    }
+
+  if (*pat == NULL)
+    {
+      uintptr_t pad = (-(uintptr_t) buffer
+		       % __alignof__ (struct gaih_addrtuple));
+      buffer += pad;
+      buflen = buflen > pad ? buflen - pad : 0;
+
+      if (__glibc_unlikely (buflen < sizeof (struct gaih_addrtuple)))
+	{
+	erange:
+	  free (result);
+	  *errnop = ERANGE;
+	  *herrnop = NETDB_INTERNAL;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+
+      *pat = (struct gaih_addrtuple *) buffer;
+      buffer += sizeof (struct gaih_addrtuple);
+      buflen -= sizeof (struct gaih_addrtuple);
+    }
+
+  uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct parser_data);
+  buffer += pad;
+
+  struct parser_data *data = (void *) buffer;
+
+  if (__glibc_unlikely (buflen < sizeof *data + 1 + pad))
+    goto erange;
+  buflen -= pad;
+
+  struct hostent host;
+  int parse_res = parse_line (result, &host, data, buflen, errnop, AF_UNSPEC,
+			      0);
+  if (__glibc_unlikely (parse_res < 1))
+    {
+      if (parse_res == -1)
+	{
+	  *herrnop = NETDB_INTERNAL;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+      else
+	{
+	  *herrnop = HOST_NOT_FOUND;
+	  return NSS_STATUS_NOTFOUND;
+	}
+    }
+
+  (*pat)->next = NULL;
+  (*pat)->family = host.h_addrtype;
+  memcpy ((*pat)->addr, host.h_addr_list[0], host.h_length);
+  (*pat)->scopeid = 0;
+  assert (host.h_addr_list[1] == NULL);
+
+  /* Undo the alignment for parser_data.  */
+  buffer -= pad;
+  buflen += pad;
+
+  size_t h_name_len = strlen (host.h_name) + 1;
+  if (h_name_len >= buflen)
+    goto erange;
+  (*pat)->name = memcpy (buffer, host.h_name, h_name_len);
+
+  free (result);
+
+  return NSS_STATUS_SUCCESS;
+}
diff --git a/REORG.TODO/nis/nss_nis/nis-initgroups.c b/REORG.TODO/nis/nss_nis/nis-initgroups.c
new file mode 100644
index 0000000000..3784c101f7
--- /dev/null
+++ b/REORG.TODO/nis/nss_nis/nis-initgroups.c
@@ -0,0 +1,336 @@
+/* Copyright (C) 1998-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <alloca.h>
+#include <ctype.h>
+#include <errno.h>
+#include <grp.h>
+#include <nss.h>
+#include <pwd.h>
+#include <string.h>
+#include <unistd.h>
+#include <rpcsvc/yp.h>
+#include <rpcsvc/ypclnt.h>
+#include <sys/param.h>
+
+#include "nss-nis.h"
+#include <libnsl.h>
+
+/* Get the declaration of the parser function.  */
+#define ENTNAME grent
+#define STRUCTURE group
+#define EXTERN_PARSER
+#include <nss/nss_files/files-parse.c>
+
+
+static enum nss_status
+internal_setgrent (char *domainname, intern_t *intern)
+{
+  struct ypall_callback ypcb;
+  enum nss_status status;
+
+  ypcb.foreach = _nis_saveit;
+  ypcb.data = (char *) intern;
+  status = yperr2nss (yp_all (domainname, "group.byname", &ypcb));
+
+  /* Mark the last buffer as full.  */
+  if (intern->next != NULL)
+    intern->next->size = intern->offset;
+
+  intern->next = intern->start;
+  intern->offset = 0;
+
+  return status;
+}
+
+
+static enum nss_status
+internal_getgrent_r (struct group *grp, char *buffer, size_t buflen,
+		     int *errnop, intern_t *intern)
+{
+  if (intern->start == NULL)
+    return NSS_STATUS_NOTFOUND;
+
+  /* Get the next entry until we found a correct one. */
+  int parse_res;
+  do
+    {
+      struct response_t *bucket = intern->next;
+
+      if (__glibc_unlikely (intern->offset >= bucket->size))
+	{
+	  if (bucket->next == NULL)
+	    return NSS_STATUS_NOTFOUND;
+
+	  /* We look at all the content in the current bucket.  Go on
+	     to the next.  */
+	  bucket = intern->next = bucket->next;
+	  intern->offset = 0;
+	}
+
+      char *p;
+      for (p = &bucket->mem[intern->offset]; isspace (*p); ++p)
+        ++intern->offset;
+
+      size_t len = strlen (p) + 1;
+      if (__glibc_unlikely (len > buflen))
+	{
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+
+      /* We unfortunately have to copy the data in the user-provided
+	 buffer because that buffer might be around for a very long
+	 time and the servent structure must remain valid.  If we would
+	 rely on the BUCKET memory the next 'setservent' or 'endservent'
+	 call would destroy it.
+
+	 The important thing is that it is a single NUL-terminated
+	 string.  This is what the parsing routine expects.  */
+      p = memcpy (buffer, &bucket->mem[intern->offset], len);
+
+      parse_res = _nss_files_parse_grent (p, grp, (void *) buffer, buflen,
+					  errnop);
+      if (__glibc_unlikely (parse_res == -1))
+        return NSS_STATUS_TRYAGAIN;
+
+      intern->offset += len;
+    }
+  while (!parse_res);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+
+static int
+get_uid (const char *user, uid_t *uidp)
+{
+  size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
+  char *buf = (char *) alloca (buflen);
+
+  while (1)
+    {
+      struct passwd result;
+      struct passwd *resp;
+
+      int r = getpwnam_r (user, &result, buf, buflen, &resp);
+      if (r == 0 && resp != NULL)
+	{
+	  *uidp = resp->pw_uid;
+	  return 0;
+	}
+
+      if (r != ERANGE)
+	break;
+
+      buf = extend_alloca (buf, buflen, 2 * buflen);
+    }
+
+  return 1;
+}
+
+
+static enum nss_status
+initgroups_netid (uid_t uid, gid_t group, long int *start, long int *size,
+		  gid_t **groupsp, long int limit, int *errnop,
+		  const char *domainname)
+{
+  /* Limit domainname length to the maximum size of an RPC packet.  */
+  if (strlen (domainname) > UDPMSGSIZE)
+    {
+      *errnop = ERANGE;
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  /* Prepare the key.  The form is "unix.UID@DOMAIN" with the UID and
+     DOMAIN field filled in appropriately.  */
+  char key[sizeof ("unix.@") + sizeof (uid_t) * 3 + strlen (domainname)];
+  ssize_t keylen = snprintf (key, sizeof (key), "unix.%lu@%s",
+			     (unsigned long int) uid, domainname);
+
+  char *result;
+  int reslen;
+  int yperr = yp_match (domainname, "netid.byname", key, keylen, &result,
+			&reslen);
+  if (__glibc_unlikely (yperr != YPERR_SUCCESS))
+    return yperr2nss (yperr);
+
+  /* Parse the result: following the colon is a comma separated list of
+     group IDs.  */
+  char *cp = strchr (result, ':');
+  if (cp == NULL)
+    {
+    errout:
+      free (result);
+      return NSS_STATUS_NOTFOUND;
+    }
+  /* Skip the colon.  */
+  ++cp;
+
+  gid_t *groups = *groupsp;
+  while (*cp != '\0')
+    {
+      char *endp;
+      unsigned long int gid = strtoul (cp, &endp, 0);
+      if (cp == endp)
+	goto errout;
+      if (*endp == ',')
+	++endp;
+      else if (*endp != '\0')
+	goto errout;
+      cp = endp;
+
+      if (gid == group)
+	/* We do not need this group again.  */
+	continue;
+
+      /* Insert this group.  */
+      if (*start == *size)
+	{
+	  /* Need a bigger buffer.  */
+	  long int newsize;
+
+	  if (limit > 0 && *size == limit)
+	    /* We reached the maximum.  */
+	    break;
+
+	  if (limit <= 0)
+	    newsize = 2 * *size;
+	  else
+	    newsize = MIN (limit, 2 * *size);
+
+	  gid_t *newgroups = realloc (groups, newsize * sizeof (*groups));
+	  if (newgroups == NULL)
+	    goto errout;
+	  *groupsp = groups = newgroups;
+	  *size = newsize;
+	}
+
+      groups[*start] = gid;
+      *start += 1;
+    }
+
+  free (result);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+
+enum nss_status
+_nss_nis_initgroups_dyn (const char *user, gid_t group, long int *start,
+			 long int *size, gid_t **groupsp, long int limit,
+			 int *errnop)
+{
+  /* We always need the domain name.  */
+  char *domainname;
+  if (yp_get_default_domain (&domainname))
+    return NSS_STATUS_UNAVAIL;
+
+  /* Check whether we are supposed to use the netid.byname map.  */
+  if (_nsl_default_nss () & NSS_FLAG_NETID_AUTHORITATIVE)
+    {
+      /* We need the user ID.  */
+      uid_t uid;
+
+      if (get_uid (user, &uid) == 0
+	  && initgroups_netid (uid, group, start, size, groupsp, limit,
+			       errnop, domainname) == NSS_STATUS_SUCCESS)
+	return NSS_STATUS_SUCCESS;
+    }
+
+  struct group grpbuf, *g;
+  size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
+  char *tmpbuf;
+  enum nss_status status;
+  intern_t intern = { NULL, NULL, 0 };
+  gid_t *groups = *groupsp;
+
+  status = internal_setgrent (domainname, &intern);
+  if (status != NSS_STATUS_SUCCESS)
+    return status;
+
+  tmpbuf = __alloca (buflen);
+
+  while (1)
+    {
+      while ((status =
+	      internal_getgrent_r (&grpbuf, tmpbuf, buflen, errnop,
+				   &intern)) == NSS_STATUS_TRYAGAIN
+             && *errnop == ERANGE)
+	tmpbuf = extend_alloca (tmpbuf, buflen, 2 * buflen);
+
+      if (status != NSS_STATUS_SUCCESS)
+	{
+	  if (status == NSS_STATUS_NOTFOUND)
+	    status = NSS_STATUS_SUCCESS;
+	  goto done;
+	}
+
+      g = &grpbuf;
+      if (g->gr_gid != group)
+        {
+          char **m;
+
+          for (m = g->gr_mem; *m != NULL; ++m)
+            if (strcmp (*m, user) == 0)
+              {
+                /* Matches user.  Insert this group.  */
+                if (*start == *size)
+                  {
+                    /* Need a bigger buffer.  */
+		    gid_t *newgroups;
+		    long int newsize;
+
+		    if (limit > 0 && *size == limit)
+		      /* We reached the maximum.  */
+		      goto done;
+
+		    if (limit <= 0)
+		      newsize = 2 * *size;
+		    else
+		      newsize = MIN (limit, 2 * *size);
+
+		    newgroups = realloc (groups, newsize * sizeof (*groups));
+		    if (newgroups == NULL)
+		      {
+			status = NSS_STATUS_TRYAGAIN;
+			*errnop = errno;
+			goto done;
+		      }
+		    *groupsp = groups = newgroups;
+                    *size = newsize;
+                  }
+
+                groups[*start] = g->gr_gid;
+		*start += 1;
+
+                break;
+              }
+        }
+    }
+
+done:
+  while (intern.start != NULL)
+    {
+      intern.next = intern.start;
+      intern.start = intern.start->next;
+      free (intern.next);
+    }
+
+  return status;
+}
diff --git a/REORG.TODO/nis/nss_nis/nis-netgrp.c b/REORG.TODO/nis/nss_nis/nis-netgrp.c
new file mode 100644
index 0000000000..ab3835fffa
--- /dev/null
+++ b/REORG.TODO/nis/nss_nis/nis-netgrp.c
@@ -0,0 +1,98 @@
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <malloc.h>
+#include <netdb.h>
+#include <nss.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netgroup.h>
+#include <rpcsvc/yp.h>
+#include <rpcsvc/ypclnt.h>
+
+#include "nss-nis.h"
+
+extern enum nss_status
+_nss_netgroup_parseline (char **cursor, struct __netgrent *netgrp,
+			 char *buffer, size_t buflen, int *errnop);
+
+
+static void
+internal_nis_endnetgrent (struct __netgrent *netgrp)
+{
+  free (netgrp->data);
+  netgrp->data = NULL;
+  netgrp->data_size = 0;
+  netgrp->cursor = NULL;
+}
+
+
+enum nss_status
+_nss_nis_setnetgrent (const char *group, struct __netgrent *netgrp)
+{
+  int len;
+  enum nss_status status;
+
+  status = NSS_STATUS_SUCCESS;
+
+  if (__glibc_unlikely (group == NULL || group[0] == '\0'))
+    return NSS_STATUS_UNAVAIL;
+
+  char *domain;
+  if (__glibc_unlikely (yp_get_default_domain (&domain)))
+    return NSS_STATUS_UNAVAIL;
+
+  status = yperr2nss (yp_match (domain, "netgroup", group, strlen (group),
+				&netgrp->data, &len));
+  if (__glibc_likely (status == NSS_STATUS_SUCCESS))
+    {
+      /* Our implementation of yp_match already allocates a buffer
+	 which is one byte larger than the value in LEN specifies
+	 and the last byte is filled with NUL.  So we can simply
+	 use that buffer.  */
+      assert (len >= 0);
+      assert (netgrp->data[len] == '\0');
+
+      netgrp->data_size = len;
+      netgrp->cursor = netgrp->data;
+    }
+
+  return status;
+}
+
+
+enum nss_status
+_nss_nis_endnetgrent (struct __netgrent *netgrp)
+{
+  internal_nis_endnetgrent (netgrp);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+
+enum nss_status
+_nss_nis_getnetgrent_r (struct __netgrent *result, char *buffer, size_t buflen,
+			int *errnop)
+{
+  return _nss_netgroup_parseline (&result->cursor, result, buffer, buflen,
+				  errnop);
+}
diff --git a/REORG.TODO/nis/nss_nis/nis-network.c b/REORG.TODO/nis/nss_nis/nis-network.c
new file mode 100644
index 0000000000..baf0ce4b8a
--- /dev/null
+++ b/REORG.TODO/nis/nss_nis/nis-network.c
@@ -0,0 +1,315 @@
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <nss.h>
+/* The following is an ugly trick to avoid a prototype declaration for
+   _nss_nis_endgrent.  */
+#define _nss_nis_endnetent _nss_nis_endnetent_XXX
+#include <netdb.h>
+#undef _nss_nis_endnetent
+#include <ctype.h>
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <libc-lock.h>
+#include <rpcsvc/yp.h>
+#include <rpcsvc/ypclnt.h>
+
+#include "nss-nis.h"
+
+/* Get the declaration of the parser function.  */
+#define ENTNAME netent
+#define EXTERN_PARSER
+#include <nss/nss_files/files-parse.c>
+
+__libc_lock_define_initialized (static, lock)
+
+static bool_t new_start = 1;
+static char *oldkey;
+static int oldkeylen;
+
+enum nss_status
+_nss_nis_setnetent (int stayopen)
+{
+  __libc_lock_lock (lock);
+
+  new_start = 1;
+  if (oldkey != NULL)
+    {
+      free (oldkey);
+      oldkey = NULL;
+      oldkeylen = 0;
+    }
+
+  __libc_lock_unlock (lock);
+
+  return NSS_STATUS_SUCCESS;
+}
+/* Make _nss_nis_endnetent an alias of _nss_nis_setnetent.  We do this
+   even though the prototypes don't match.  The argument of setnetent
+   is not used so this makes no difference.  */
+strong_alias (_nss_nis_setnetent, _nss_nis_endnetent)
+
+static enum nss_status
+internal_nis_getnetent_r (struct netent *net, char *buffer, size_t buflen,
+			  int *errnop, int *herrnop)
+{
+  struct parser_data *data = (void *) buffer;
+
+  char *domain;
+  if (__glibc_unlikely (yp_get_default_domain (&domain)))
+    return NSS_STATUS_UNAVAIL;
+
+  /* Get the next entry until we found a correct one. */
+  int parse_res;
+  do
+    {
+      char *result;
+      char *outkey;
+      int len;
+      int keylen;
+      int yperr;
+
+      if (new_start)
+        yperr = yp_first (domain, "networks.byname", &outkey, &keylen, &result,
+			  &len);
+      else
+        yperr = yp_next (domain, "networks.byname", oldkey, oldkeylen, &outkey,
+			 &keylen, &result, &len);
+
+      if (__glibc_unlikely (yperr != YPERR_SUCCESS))
+        {
+	  enum nss_status retval = yperr2nss (yperr);
+
+          if (retval == NSS_STATUS_TRYAGAIN)
+	    {
+	      *herrnop = NETDB_INTERNAL;
+	      *errnop = errno;
+	    }
+          return retval;
+        }
+
+      if (__glibc_unlikely ((size_t) (len + 1) > buflen))
+        {
+          free (result);
+	  *errnop = ERANGE;
+	  *herrnop = NETDB_INTERNAL;
+          return NSS_STATUS_TRYAGAIN;
+        }
+
+      char *p = strncpy (buffer, result, len);
+      buffer[len] = '\0';
+      while (isspace (*p))
+        ++p;
+      free (result);
+
+      parse_res = _nss_files_parse_netent (p, net, data, buflen, errnop);
+      if (__glibc_unlikely (parse_res == -1))
+	{
+	  free (outkey);
+	  *herrnop = NETDB_INTERNAL;
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+
+      free (oldkey);
+      oldkey = outkey;
+      oldkeylen = keylen;
+      new_start = 0;
+    }
+  while (!parse_res);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nis_getnetent_r (struct netent *net, char *buffer, size_t buflen,
+		      int *errnop, int *herrnop)
+{
+  enum nss_status status;
+
+  __libc_lock_lock (lock);
+
+  status = internal_nis_getnetent_r (net, buffer, buflen, errnop, herrnop);
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+enum nss_status
+_nss_nis_getnetbyname_r (const char *name, struct netent *net, char *buffer,
+			 size_t buflen, int *errnop, int *herrnop)
+{
+  if (name == NULL)
+    {
+      *errnop = EINVAL;
+      *herrnop = NETDB_INTERNAL;
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  char *domain;
+  if (__glibc_unlikely (yp_get_default_domain (&domain)))
+    return NSS_STATUS_UNAVAIL;
+
+  struct parser_data *data = (void *) buffer;
+  if (buflen < sizeof *data + 1)
+    {
+      *herrnop = NETDB_INTERNAL;
+      *errnop = ERANGE;
+      return NSS_STATUS_TRYAGAIN;
+    }
+
+  /* Convert name to lowercase.  */
+  size_t namlen = strlen (name);
+  /* Limit name length to the maximum size of an RPC packet.  */
+  if (namlen > UDPMSGSIZE)
+    {
+      *errnop = ERANGE;
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  char name2[namlen + 1];
+  size_t i;
+
+  for (i = 0; i < namlen; ++i)
+    name2[i] = _tolower (name[i]);
+  name2[i] = '\0';
+
+  char *result;
+  int len;
+  int yperr = yp_match (domain, "networks.byname", name2, namlen, &result,
+			&len);
+
+  if (__glibc_unlikely (yperr != YPERR_SUCCESS))
+    {
+      enum nss_status retval = yperr2nss (yperr);
+
+      if (retval == NSS_STATUS_TRYAGAIN)
+	{
+	  *errnop = errno;
+	  *herrnop = NETDB_INTERNAL;
+	}
+      return retval;
+    }
+
+  if (__glibc_unlikely ((size_t) (len + 1) > buflen))
+    {
+      free (result);
+      *errnop = ERANGE;
+      *herrnop = NETDB_INTERNAL;
+      return NSS_STATUS_TRYAGAIN;
+    }
+
+  char *p = strncpy (buffer, result, len);
+  buffer[len] = '\0';
+  while (isspace (*p))
+    ++p;
+  free (result);
+
+  int parse_res = _nss_files_parse_netent (p, net, data, buflen, errnop);
+
+  if (__glibc_unlikely (parse_res < 1))
+    {
+      *herrnop = NETDB_INTERNAL;
+      if (parse_res == -1)
+	return NSS_STATUS_TRYAGAIN;
+      else
+	return NSS_STATUS_NOTFOUND;
+    }
+  else
+    return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nis_getnetbyaddr_r (uint32_t addr, int type, struct netent *net,
+			 char *buffer, size_t buflen, int *errnop,
+			 int *herrnop)
+{
+  char *domain;
+  if (__glibc_unlikely (yp_get_default_domain (&domain)))
+    return NSS_STATUS_UNAVAIL;
+
+  struct in_addr in = { .s_addr = htonl (addr) };
+  char *buf = inet_ntoa (in);
+  size_t blen = strlen (buf);
+
+  while (1)
+    {
+      char *result;
+      int len;
+
+      int yperr = yp_match (domain, "networks.byaddr", buf, blen, &result,
+			    &len);
+
+      if (__glibc_unlikely (yperr != YPERR_SUCCESS))
+	  {
+	    enum nss_status retval = yperr2nss (yperr);
+
+	    if (retval == NSS_STATUS_NOTFOUND)
+	      {
+		if (buf[blen - 2] == '.' && buf[blen - 1] == '0')
+		  {
+		    /* Try again, but with trailing dot(s)
+		       removed (one by one) */
+		    buf[blen - 2] = '\0';
+		    blen -= 2;
+		    continue;
+		  }
+		else
+		  return NSS_STATUS_NOTFOUND;
+	      }
+	    else
+	      {
+		if (retval == NSS_STATUS_TRYAGAIN)
+		  *errnop = errno;
+		return retval;
+	      }
+	  }
+
+      if (__glibc_unlikely ((size_t) (len + 1) > buflen))
+	{
+	  free (result);
+	  *errnop = ERANGE;
+	  *herrnop = NETDB_INTERNAL;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+
+        char *p = strncpy (buffer, result, len);
+	buffer[len] = '\0';
+	while (isspace (*p))
+	  ++p;
+	free (result);
+
+	int parse_res = _nss_files_parse_netent (p, net, (void *) buffer,
+						 buflen, errnop);
+
+	if (__glibc_unlikely (parse_res < 1))
+	  {
+	    *herrnop = NETDB_INTERNAL;
+	    if (parse_res == -1)
+	      return NSS_STATUS_TRYAGAIN;
+	    else
+	      return NSS_STATUS_NOTFOUND;
+	  }
+	else
+	  return NSS_STATUS_SUCCESS;
+    }
+}
diff --git a/REORG.TODO/nis/nss_nis/nis-proto.c b/REORG.TODO/nis/nss_nis/nis-proto.c
new file mode 100644
index 0000000000..df0739aaad
--- /dev/null
+++ b/REORG.TODO/nis/nss_nis/nis-proto.c
@@ -0,0 +1,278 @@
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <nss.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <libc-lock.h>
+#include <rpcsvc/yp.h>
+#include <rpcsvc/ypclnt.h>
+
+#include "nss-nis.h"
+
+/* Get the declaration of the parser function.  */
+#define ENTNAME protoent
+#define EXTERN_PARSER
+#include <nss/nss_files/files-parse.c>
+
+__libc_lock_define_initialized (static, lock)
+
+struct response
+{
+  struct response *next;
+  char val[0];
+};
+
+static struct response *start;
+static struct response *next;
+
+static int
+saveit (int instatus, char *inkey, int inkeylen, char *inval,
+        int invallen, char *indata)
+{
+  if (instatus != YP_TRUE)
+    return 1;
+
+  if (inkey && inkeylen > 0 && inval && invallen > 0)
+    {
+      struct response *newp = malloc (sizeof (struct response) + invallen + 1);
+      if (newp == NULL)
+	return 1; /* We have no error code for out of memory */
+
+      if (start == NULL)
+	start = newp;
+      else
+	next->next = newp;
+      next = newp;
+
+      newp->next = NULL;
+      *((char *) mempcpy (newp->val, inval, invallen)) = '\0';
+    }
+
+  return 0;
+}
+
+static void
+internal_nis_endprotoent (void)
+{
+  while (start != NULL)
+    {
+      next = start;
+      start = start->next;
+      free (next);
+    }
+}
+
+static enum nss_status
+internal_nis_setprotoent (void)
+{
+  char *domainname;
+  struct ypall_callback ypcb;
+  enum nss_status status;
+
+  yp_get_default_domain (&domainname);
+
+  internal_nis_endprotoent ();
+
+  ypcb.foreach = saveit;
+  ypcb.data = NULL;
+  status = yperr2nss (yp_all (domainname, "protocols.bynumber", &ypcb));
+  next = start;
+
+  return status;
+}
+
+enum nss_status
+_nss_nis_setprotoent (int stayopen)
+{
+  enum nss_status status;
+
+  __libc_lock_lock (lock);
+
+  status = internal_nis_setprotoent ();
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+enum nss_status
+_nss_nis_endprotoent (void)
+{
+  __libc_lock_lock (lock);
+
+  internal_nis_endprotoent ();
+  next = NULL;
+
+  __libc_lock_unlock (lock);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+static enum nss_status
+internal_nis_getprotoent_r (struct protoent *proto,
+			    char *buffer, size_t buflen, int *errnop)
+{
+  struct parser_data *data = (void *) buffer;
+  int parse_res;
+
+  if (start == NULL)
+    internal_nis_setprotoent ();
+
+  /* Get the next entry until we found a correct one. */
+  do
+    {
+      char *p;
+
+      if (next == NULL)
+	return NSS_STATUS_NOTFOUND;
+
+      p = strncpy (buffer, next->val, buflen);
+
+      while (isspace (*p))
+        ++p;
+
+      parse_res = _nss_files_parse_protoent (p, proto, data, buflen, errnop);
+      if (parse_res == -1)
+        return NSS_STATUS_TRYAGAIN;
+      next = next->next;
+    }
+  while (!parse_res);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nis_getprotoent_r (struct protoent *proto, char *buffer, size_t buflen,
+			int *errnop)
+{
+  enum nss_status status;
+
+  __libc_lock_lock (lock);
+
+  status = internal_nis_getprotoent_r (proto, buffer, buflen, errnop);
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+enum nss_status
+_nss_nis_getprotobyname_r (const char *name, struct protoent *proto,
+			   char *buffer, size_t buflen, int *errnop)
+{
+  if (name == NULL)
+    {
+      *errnop = EINVAL;
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  char *domain;
+  if (__glibc_unlikely (yp_get_default_domain (&domain)))
+    return NSS_STATUS_UNAVAIL;
+
+  char *result;
+  int len;
+  int yperr = yp_match (domain, "protocols.byname", name, strlen (name),
+			&result, &len);
+
+  if (__glibc_unlikely (yperr != YPERR_SUCCESS))
+    {
+      enum nss_status retval = yperr2nss (yperr);
+
+      if (retval == NSS_STATUS_TRYAGAIN)
+	*errnop = errno;
+      return retval;
+    }
+
+  if (__glibc_unlikely ((size_t) (len + 1) > buflen))
+    {
+      free (result);
+      *errnop = ERANGE;
+      return NSS_STATUS_TRYAGAIN;
+    }
+
+  char *p = strncpy (buffer, result, len);
+  buffer[len] = '\0';
+  while (isspace (*p))
+    ++p;
+  free (result);
+
+  int parse_res = _nss_files_parse_protoent (p, proto, (void *) buffer, buflen,
+					     errnop);
+  if (__glibc_unlikely (parse_res < 1))
+    {
+      if (parse_res == -1)
+	return NSS_STATUS_TRYAGAIN;
+      else
+	return NSS_STATUS_NOTFOUND;
+    }
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nis_getprotobynumber_r (int number, struct protoent *proto,
+			     char *buffer, size_t buflen, int *errnop)
+{
+  char *domain;
+  if (__glibc_unlikely (yp_get_default_domain (&domain)))
+    return NSS_STATUS_UNAVAIL;
+
+  char buf[32];
+  int nlen = snprintf (buf, sizeof (buf), "%d", number);
+
+  char *result;
+  int len;
+  int yperr = yp_match (domain, "protocols.bynumber", buf, nlen, &result,
+			&len);
+
+  if (__glibc_unlikely (yperr != YPERR_SUCCESS))
+    {
+      enum nss_status retval = yperr2nss (yperr);
+
+      if (retval == NSS_STATUS_TRYAGAIN)
+	*errnop = errno;
+      return retval;
+    }
+
+  if (__glibc_unlikely ((size_t) (len + 1) > buflen))
+    {
+      free (result);
+      *errnop = ERANGE;
+      return NSS_STATUS_TRYAGAIN;
+    }
+
+  char *p = strncpy (buffer, result, len);
+  buffer[len] = '\0';
+  while (isspace (*p))
+    ++p;
+  free (result);
+
+  int parse_res = _nss_files_parse_protoent (p, proto, (void *) buffer, buflen,
+					     errnop);
+  if (__glibc_unlikely (parse_res < 1))
+    {
+      if (parse_res == -1)
+	return NSS_STATUS_TRYAGAIN;
+      else
+	return NSS_STATUS_NOTFOUND;
+    }
+  return NSS_STATUS_SUCCESS;
+}
diff --git a/REORG.TODO/nis/nss_nis/nis-publickey.c b/REORG.TODO/nis/nss_nis/nis-publickey.c
new file mode 100644
index 0000000000..188e80cd5d
--- /dev/null
+++ b/REORG.TODO/nis/nss_nis/nis-publickey.c
@@ -0,0 +1,234 @@
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <nss.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <syslog.h>
+#include <rpc/rpc.h>
+#include <rpcsvc/yp.h>
+#include <rpcsvc/ypclnt.h>
+#include <rpc/key_prot.h>
+#include <rpc/des_crypt.h>
+
+#include "nss-nis.h"
+
+/* If we haven't found the entry, we give a SUCCESS and an empty key back.
+   Solaris docu says: sizeof (pkey) == HEXKEYBYTES + 1.
+*/
+enum nss_status
+_nss_nis_getpublickey (const char *netname, char *pkey, int *errnop)
+{
+  pkey[0] = 0;
+
+  if (netname == NULL)
+    {
+      *errnop = EINVAL;
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  char *domain = strchr (netname, '@');
+  if (domain == NULL)
+    {
+      *errnop = EINVAL;
+      return NSS_STATUS_UNAVAIL;
+    }
+  ++domain;
+
+  char *result;
+  int len;
+  int yperr = yp_match (domain, "publickey.byname", netname, strlen (netname),
+			&result, &len);
+
+  if (__glibc_unlikely (yperr != YPERR_SUCCESS))
+    {
+      enum nss_status retval = yperr2nss (yperr);
+
+      if (retval == NSS_STATUS_TRYAGAIN)
+	*errnop = errno;
+      return retval;
+    }
+
+  if (result != NULL)
+    {
+      char *p = strchr (result, ':');
+      if (p != NULL)
+	*p = 0;
+      strncpy (pkey, result, HEXKEYBYTES + 1);
+      pkey[HEXKEYBYTES] = '\0';
+      free (result);
+    }
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nis_getsecretkey (const char *netname, char *skey, char *passwd,
+		       int *errnop)
+{
+  skey[0] = 0;
+
+  if (netname == NULL || passwd == NULL)
+    {
+      *errnop = EINVAL;
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  char *domain = strchr (netname, '@');
+  if (domain == NULL)
+    {
+      *errnop = EINVAL;
+      return NSS_STATUS_UNAVAIL;
+    }
+  ++domain;
+
+  char *result;
+  int len;
+  int yperr = yp_match (domain, "publickey.byname", netname, strlen (netname),
+			&result, &len);
+
+  if (__glibc_unlikely (yperr != YPERR_SUCCESS))
+    {
+      enum nss_status retval = yperr2nss (yperr);
+
+      if (retval == NSS_STATUS_TRYAGAIN)
+	*errnop = errno;
+      return retval;
+    }
+
+  if (result != NULL)
+    {
+      char *p = strchr (result, ':');
+      if (p != NULL)
+	{
+	  char buf[2 * (HEXKEYBYTES + 1)];
+
+	  ++p;
+	  strncpy (buf, p, 2 * (HEXKEYBYTES + 1));
+	  buf[2 * HEXKEYBYTES + 1] = '\0';
+	  if (xdecrypt (buf, passwd)
+	      && memcmp (buf, &(buf[HEXKEYBYTES]), KEYCHECKSUMSIZE) == 0)
+	    {
+	      buf[HEXKEYBYTES] = '\0';
+	      strcpy (skey, buf);
+	    }
+	}
+
+      free (result);
+    }
+  return NSS_STATUS_SUCCESS;
+}
+
+/* Parse uid and group information from the passed string.
+   The format of the string passed is uid:gid,grp,grp, ...  */
+static enum nss_status
+parse_netid_str (const char *s, uid_t *uidp, gid_t *gidp, int *gidlenp,
+		 gid_t *gidlist)
+{
+  char *p, *ep;
+  int gidlen;
+
+  if (!s || !isdigit (*s))
+    {
+      syslog (LOG_ERR, "netname2user: expecting uid '%s'", s);
+      return NSS_STATUS_NOTFOUND;	/* XXX need a better error */
+    }
+
+  /* Fetch the uid */
+  *uidp = strtoul (s, NULL, 10);
+
+  if (*uidp == 0)
+    {
+      syslog (LOG_ERR, "netname2user: should not have uid 0");
+      return NSS_STATUS_NOTFOUND;
+    }
+
+  /* Now get the group list */
+  p = strchr (s, ':');
+  if (!p)
+    {
+      syslog (LOG_ERR, "netname2user: missing group id list in '%s'", s);
+      return NSS_STATUS_NOTFOUND;
+    }
+  ++p;				/* skip ':' */
+  if (!p || (!isdigit (*p)))
+    {
+      syslog (LOG_ERR, "netname2user: missing group id list in '%s'.", p);
+      return NSS_STATUS_NOTFOUND;
+    }
+
+  *gidp = strtoul (p, &ep, 10);
+
+  gidlen = 0;
+
+  /* After strtoul() ep should point to the first invalid character.
+     This is the marker "," we search for the next value.  */
+  while (ep != NULL && *ep == ',')
+    {
+      ep++;
+      p = ep;
+      gidlist[gidlen++] = strtoul (p, &ep, 10);
+    }
+
+  *gidlenp = gidlen;
+
+  return NSS_STATUS_SUCCESS;
+}
+
+
+enum nss_status
+_nss_nis_netname2user (char netname[MAXNETNAMELEN + 1], uid_t *uidp,
+		       gid_t *gidp, int *gidlenp, gid_t *gidlist, int *errnop)
+{
+  char *domain = strchr (netname, '@');
+  if (domain == NULL)
+    {
+      *errnop = EINVAL;
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  /* Point past the '@' character */
+  ++domain;
+  char *lookup = NULL;
+  int len;
+  int yperr = yp_match (domain, "netid.byname", netname, strlen (netname),
+			&lookup, &len);
+  switch (yperr)
+    {
+    case YPERR_SUCCESS:
+      break;			/* the successful case */
+    case YPERR_DOMAIN:
+    case YPERR_KEY:
+      return NSS_STATUS_NOTFOUND;
+    case YPERR_MAP:
+    default:
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  if (lookup == NULL)
+    return NSS_STATUS_NOTFOUND;
+
+
+  lookup[len] = '\0';
+
+  enum nss_status err = parse_netid_str (lookup, uidp, gidp, gidlenp, gidlist);
+
+  free (lookup);
+
+  return err;
+}
diff --git a/REORG.TODO/nis/nss_nis/nis-pwd.c b/REORG.TODO/nis/nss_nis/nis-pwd.c
new file mode 100644
index 0000000000..6a759eeaec
--- /dev/null
+++ b/REORG.TODO/nis/nss_nis/nis-pwd.c
@@ -0,0 +1,581 @@
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <nss.h>
+#include <pwd.h>
+#include <string.h>
+#include <libc-lock.h>
+#include <rpcsvc/yp.h>
+#include <rpcsvc/ypclnt.h>
+
+#include "nss-nis.h"
+#include <libnsl.h>
+
+/* Get the declaration of the parser function.  */
+#define ENTNAME pwent
+#define STRUCTURE passwd
+#define EXTERN_PARSER
+#include <nss/nss_files/files-parse.c>
+
+/* Protect global state against multiple changers */
+__libc_lock_define_initialized (static, lock)
+
+static bool new_start = true;
+static char *oldkey;
+static int oldkeylen;
+static intern_t intern;
+
+
+int
+_nis_saveit (int instatus, char *inkey, int inkeylen, char *inval,
+	     int invallen, char *indata)
+{
+  intern_t *intern = (intern_t *) indata;
+
+  if (instatus != YP_TRUE)
+    return 1;
+
+  if (inkey && inkeylen > 0 && inval && invallen > 0)
+    {
+      struct response_t *bucket = intern->next;
+
+      if (__glibc_unlikely (bucket == NULL))
+	{
+#define MINSIZE 4096 - 4 * sizeof (void *)
+	  const size_t minsize = MAX (MINSIZE, 2 * (invallen + 1));
+	  bucket = malloc (sizeof (struct response_t) + minsize);
+	  if (bucket == NULL)
+	    /* We have no error code for out of memory.  */
+	    return 1;
+
+	  bucket->next = NULL;
+	  bucket->size = minsize;
+	  intern->start = intern->next = bucket;
+	  intern->offset = 0;
+	}
+      else if (__builtin_expect (invallen + 1 > bucket->size - intern->offset,
+				 0))
+	{
+	  /* We need a new (larger) buffer.  */
+	  const size_t newsize = 2 * MAX (bucket->size, invallen + 1);
+	  struct response_t *newp = malloc (sizeof (struct response_t)
+					    + newsize);
+	  if (newp == NULL)
+	    /* We have no error code for out of memory.  */
+	    return 1;
+
+	  /* Mark the old bucket as full.  */
+	  bucket->size = intern->offset;
+
+	  newp->next = NULL;
+	  newp->size = newsize;
+	  bucket = intern->next = bucket->next = newp;
+	  intern->offset = 0;
+	}
+
+      char *p = mempcpy (&bucket->mem[intern->offset], inval, invallen);
+      if (__glibc_unlikely (p[-1] != '\0'))
+	{
+	  *p = '\0';
+	  ++invallen;
+	}
+      intern->offset += invallen;
+    }
+
+  return 0;
+}
+
+
+static void
+internal_nis_endpwent (void)
+{
+  new_start = true;
+  free (oldkey);
+  oldkey = NULL;
+  oldkeylen = 0;
+
+  struct response_t *curr = intern.start;
+
+  while (curr != NULL)
+    {
+      struct response_t *last = curr;
+      curr = curr->next;
+      free (last);
+    }
+
+  intern.next = intern.start = NULL;
+}
+
+
+enum nss_status
+_nss_nis_endpwent (void)
+{
+  __libc_lock_lock (lock);
+
+  internal_nis_endpwent ();
+
+  __libc_lock_unlock (lock);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+
+enum nss_status
+internal_nis_setpwent (void)
+{
+  /* We have to read all the data now.  */
+  char *domain;
+  if (__glibc_unlikely (yp_get_default_domain (&domain)))
+    return NSS_STATUS_UNAVAIL;
+
+  struct ypall_callback ypcb;
+
+  ypcb.foreach = _nis_saveit;
+  ypcb.data = (char *) &intern;
+  enum nss_status status = yperr2nss (yp_all (domain, "passwd.byname", &ypcb));
+
+
+  /* Mark the last buffer as full.  */
+  if (intern.next != NULL)
+    intern.next->size = intern.offset;
+
+  intern.next = intern.start;
+  intern.offset = 0;
+
+  return status;
+}
+
+
+enum nss_status
+_nss_nis_setpwent (int stayopen)
+{
+  enum nss_status result = NSS_STATUS_SUCCESS;
+
+  __libc_lock_lock (lock);
+
+  internal_nis_endpwent ();
+
+  if (_nsl_default_nss () & NSS_FLAG_SETENT_BATCH_READ)
+    result = internal_nis_setpwent ();
+
+  __libc_lock_unlock (lock);
+
+  return result;
+}
+
+
+static enum nss_status
+internal_nis_getpwent_r (struct passwd *pwd, char *buffer, size_t buflen,
+			 int *errnop)
+{
+  /* If we read the entire database at setpwent time we just iterate
+     over the data we have in memory.  */
+  bool batch_read = intern.start != NULL;
+
+  char *domain = NULL;
+  if (!batch_read && __builtin_expect (yp_get_default_domain (&domain), 0))
+    return NSS_STATUS_UNAVAIL;
+
+  /* Get the next entry until we found a correct one. */
+  int parse_res;
+  do
+    {
+      char *result;
+      char *outkey;
+      int len;
+      int keylen;
+
+      if (batch_read)
+	{
+	  struct response_t *bucket;
+
+	handle_batch_read:
+	  bucket = intern.next;
+
+	  if (__glibc_unlikely (intern.offset >= bucket->size))
+	    {
+	      if (bucket->next == NULL)
+		return NSS_STATUS_NOTFOUND;
+
+	      /* We look at all the content in the current bucket.  Go on
+		 to the next.  */
+	      bucket = intern.next = bucket->next;
+	      intern.offset = 0;
+	    }
+
+	  for (result = &bucket->mem[intern.offset]; isspace (*result);
+	       ++result)
+	    ++intern.offset;
+
+	  len = strlen (result);
+	}
+      else
+	{
+	  int yperr;
+
+	  if (new_start)
+	    {
+	      /* Maybe we should read the database in one piece.  */
+	      if ((_nsl_default_nss () & NSS_FLAG_SETENT_BATCH_READ)
+		  && internal_nis_setpwent () == NSS_STATUS_SUCCESS
+		  && intern.start != NULL)
+		{
+		  batch_read = true;
+		  goto handle_batch_read;
+		}
+
+	      yperr = yp_first (domain, "passwd.byname", &outkey, &keylen,
+				&result, &len);
+	    }
+	  else
+	    yperr = yp_next (domain, "passwd.byname", oldkey, oldkeylen,
+			     &outkey, &keylen, &result, &len);
+
+	  if (__glibc_unlikely (yperr != YPERR_SUCCESS))
+	    {
+	      enum nss_status retval = yperr2nss (yperr);
+
+	      if (retval == NSS_STATUS_TRYAGAIN)
+		*errnop = errno;
+	      return retval;
+	    }
+	}
+
+      /* Check for adjunct style secret passwords.  They can be
+	 recognized by a password starting with "##".  We do not use
+	 it if the passwd.adjunct.byname table is supposed to be used
+	 as a shadow.byname replacement.  */
+      char *p = strchr (result, ':');
+      size_t namelen;
+      char *result2;
+      int len2;
+      if ((_nsl_default_nss () & NSS_FLAG_ADJUNCT_AS_SHADOW) == 0
+	  && p != NULL	/* This better should be true in all cases.  */
+	  && p[1] == '#' && p[2] == '#'
+	  && (namelen = p - result,
+	      yp_match (domain, "passwd.adjunct.byname", result, namelen,
+			&result2, &len2)) == YPERR_SUCCESS)
+	{
+	  /* We found a passwd.adjunct.byname entry.  Merge encrypted
+	     password therein into original result.  */
+	  char *encrypted = strchr (result2, ':');
+	  char *endp;
+	  size_t restlen;
+
+	  if (encrypted == NULL
+	      || (endp = strchr (++encrypted, ':')) == NULL
+	      || (p = strchr (p + 1, ':')) == NULL)
+	    {
+	      /* Invalid format of the entry.  This never should happen
+		 unless the data from which the NIS table is generated is
+		 wrong.  We simply ignore it.  */
+	      free (result2);
+	      goto non_adjunct;
+	    }
+
+	  restlen = len - (p - result);
+	  if (__builtin_expect ((size_t) (namelen + (endp - encrypted)
+					  + restlen + 2) > buflen, 0))
+	    {
+	      free (result2);
+	      free (result);
+	      *errnop = ERANGE;
+	      return NSS_STATUS_TRYAGAIN;
+	    }
+
+	  mempcpy (mempcpy (mempcpy (mempcpy (buffer, result, namelen),
+				     ":", 1),
+			    encrypted, endp - encrypted),
+		   p, restlen + 1);
+	  p = buffer;
+
+	  free (result2);
+	}
+      else
+	{
+	non_adjunct:
+	  if (__glibc_unlikely ((size_t) (len + 1) > buflen))
+	    {
+	      free (result);
+	      *errnop = ERANGE;
+	      return NSS_STATUS_TRYAGAIN;
+	    }
+
+	  p = buffer;
+	  *((char *) mempcpy (buffer, result, len)) = '\0';
+	}
+
+      while (isspace (*p))
+	++p;
+      if (!batch_read)
+	free (result);
+
+      parse_res = _nss_files_parse_pwent (p, pwd, (void *) buffer, buflen,
+					  errnop);
+      if (__glibc_unlikely (parse_res == -1))
+	{
+	  if (!batch_read)
+	    free (outkey);
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+
+      if (batch_read)
+	intern.offset += len + 1;
+      else
+	{
+	  free (oldkey);
+	  oldkey = outkey;
+	  oldkeylen = keylen;
+	  new_start = false;
+	}
+    }
+  while (parse_res < 1);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nis_getpwent_r (struct passwd *result, char *buffer, size_t buflen,
+		     int *errnop)
+{
+  int status;
+
+  __libc_lock_lock (lock);
+
+  status = internal_nis_getpwent_r (result, buffer, buflen, errnop);
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+enum nss_status
+_nss_nis_getpwnam_r (const char *name, struct passwd *pwd,
+		     char *buffer, size_t buflen, int *errnop)
+{
+  if (name == NULL)
+    {
+      *errnop = EINVAL;
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  char *domain;
+  if (__glibc_unlikely (yp_get_default_domain (&domain)))
+    return NSS_STATUS_UNAVAIL;
+
+  size_t namelen = strlen (name);
+
+  char *result;
+  int len;
+  int yperr = yp_match (domain, "passwd.byname", name, namelen, &result, &len);
+
+  if (__glibc_unlikely (yperr != YPERR_SUCCESS))
+    {
+      enum nss_status retval = yperr2nss (yperr);
+
+      if (retval == NSS_STATUS_TRYAGAIN)
+	*errnop = errno;
+      return retval;
+    }
+
+  /* Check for adjunct style secret passwords.  They can be recognized
+     by a password starting with "##". We do not use it if the
+     passwd.adjunct.byname table is supposed to be used as a shadow.byname
+     replacement.  */
+  char *result2;
+  int len2;
+  char *p = strchr (result, ':');
+  if ((_nsl_default_nss () & NSS_FLAG_ADJUNCT_AS_SHADOW) == 0
+      && p != NULL	/* This better should be true in all cases.  */
+      && p[1] == '#' && p[2] == '#'
+      && yp_match (domain, "passwd.adjunct.byname", name, namelen,
+		   &result2, &len2) == YPERR_SUCCESS)
+    {
+      /* We found a passwd.adjunct.byname entry.  Merge encrypted password
+	 therein into original result.  */
+      char *encrypted = strchr (result2, ':');
+      char *endp;
+
+      if (encrypted == NULL
+	  || (endp = strchr (++encrypted, ':')) == NULL
+	  || (p = strchr (p + 1, ':')) == NULL)
+	{
+	  /* Invalid format of the entry.  This never should happen
+	     unless the data from which the NIS table is generated is
+	     wrong.  We simply ignore it.  */
+	  free (result2);
+	  goto non_adjunct;
+	}
+
+      size_t restlen = len - (p - result);
+      if (__builtin_expect ((size_t) (namelen + (endp - encrypted)
+				      + restlen + 2) > buflen, 0))
+	{
+	  free (result2);
+	  free (result);
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+
+      __mempcpy (__mempcpy (__mempcpy (__mempcpy (buffer, name, namelen),
+				       ":", 1),
+			    encrypted, endp - encrypted),
+		 p, restlen + 1);
+      p = buffer;
+
+      free (result2);
+    }
+  else
+    {
+    non_adjunct:
+      if (__glibc_unlikely ((size_t) (len + 1) > buflen))
+	{
+	  free (result);
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+
+      p = strncpy (buffer, result, len);
+      buffer[len] = '\0';
+    }
+
+  while (isspace (*p))
+    ++p;
+  free (result);
+
+  int parse_res = _nss_files_parse_pwent (p, pwd, (void *) buffer, buflen,
+					  errnop);
+  if (__glibc_unlikely (parse_res < 1))
+    {
+      if (parse_res == -1)
+	return NSS_STATUS_TRYAGAIN;
+      else
+	return NSS_STATUS_NOTFOUND;
+    }
+  else
+    return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nis_getpwuid_r (uid_t uid, struct passwd *pwd,
+		     char *buffer, size_t buflen, int *errnop)
+{
+  char *domain;
+  if (__glibc_unlikely (yp_get_default_domain (&domain)))
+    return NSS_STATUS_UNAVAIL;
+
+  char buf[32];
+  int nlen = snprintf (buf, sizeof (buf), "%lu", (unsigned long int) uid);
+
+  char *result;
+  int len;
+  int yperr = yp_match (domain, "passwd.byuid", buf, nlen, &result, &len);
+
+  if (__glibc_unlikely (yperr != YPERR_SUCCESS))
+    {
+      enum nss_status retval = yperr2nss (yperr);
+
+      if (retval == NSS_STATUS_TRYAGAIN)
+	*errnop = errno;
+      return retval;
+    }
+
+  /* Check for adjunct style secret passwords.  They can be recognized
+     by a password starting with "##".  We do not use it if the
+     passwd.adjunct.byname table is supposed to be used as a shadow.byname
+     replacement.  */
+  char *result2;
+  int len2;
+  size_t namelen;
+  char *p = strchr (result, ':');
+  if ((_nsl_default_nss () & NSS_FLAG_ADJUNCT_AS_SHADOW) == 0
+      && p != NULL	/* This better should be true in all cases.  */
+      && p[1] == '#' && p[2] == '#'
+      && (namelen = p - result,
+	  yp_match (domain, "passwd.adjunct.byname", result, namelen,
+		    &result2, &len2)) == YPERR_SUCCESS)
+    {
+      /* We found a passwd.adjunct.byname entry.  Merge encrypted password
+	 therein into original result.  */
+      char *encrypted = strchr (result2, ':');
+      char *endp;
+      size_t restlen;
+
+      if (encrypted == NULL
+	  || (endp = strchr (++encrypted, ':')) == NULL
+	  || (p = strchr (p + 1, ':')) == NULL)
+	{
+	  /* Invalid format of the entry.  This never should happen
+	     unless the data from which the NIS table is generated is
+	     wrong.  We simply ignore it.  */
+	  free (result2);
+	  goto non_adjunct;
+	}
+
+      restlen = len - (p - result);
+      if (__builtin_expect ((size_t) (namelen + (endp - encrypted)
+				      + restlen + 2) > buflen, 0))
+	{
+	  free (result2);
+	  free (result);
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+
+      __mempcpy (__mempcpy (__mempcpy (__mempcpy (buffer, result, namelen),
+				       ":", 1),
+			    encrypted, endp - encrypted),
+		 p, restlen + 1);
+      p = buffer;
+
+      free (result2);
+    }
+  else
+    {
+    non_adjunct:
+      if (__glibc_unlikely ((size_t) (len + 1) > buflen))
+	{
+	  free (result);
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+
+      p = strncpy (buffer, result, len);
+      buffer[len] = '\0';
+    }
+
+  while (isspace (*p))
+    ++p;
+  free (result);
+
+  int parse_res = _nss_files_parse_pwent (p, pwd, (void *) buffer, buflen,
+					  errnop);
+  if (__glibc_unlikely (parse_res < 1))
+    {
+      if (parse_res == -1)
+	return NSS_STATUS_TRYAGAIN;
+     else
+       return NSS_STATUS_NOTFOUND;
+    }
+  else
+    return NSS_STATUS_SUCCESS;
+}
diff --git a/REORG.TODO/nis/nss_nis/nis-rpc.c b/REORG.TODO/nis/nss_nis/nis-rpc.c
new file mode 100644
index 0000000000..24e47e9884
--- /dev/null
+++ b/REORG.TODO/nis/nss_nis/nis-rpc.c
@@ -0,0 +1,279 @@
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <nss.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <libc-lock.h>
+#include <rpcsvc/yp.h>
+#include <rpcsvc/ypclnt.h>
+
+#include "nss-nis.h"
+
+/* Get the declaration of the parser function.  */
+#define ENTNAME rpcent
+#define EXTERN_PARSER
+#include <nss/nss_files/files-parse.c>
+
+__libc_lock_define_initialized (static, lock)
+
+static intern_t intern;
+
+
+static void
+internal_nis_endrpcent (intern_t *intern)
+{
+  struct response_t *curr = intern->next;
+
+  while (curr != NULL)
+    {
+      struct response_t *last = curr;
+      curr = curr->next;
+      free (last);
+    }
+
+  intern->next = intern->start = NULL;
+}
+
+static enum nss_status
+internal_nis_setrpcent (intern_t *intern)
+{
+  char *domainname;
+  struct ypall_callback ypcb;
+  enum nss_status status;
+
+  if (yp_get_default_domain (&domainname))
+    return NSS_STATUS_UNAVAIL;
+
+  internal_nis_endrpcent (intern);
+
+  ypcb.foreach = _nis_saveit;
+  ypcb.data = (char *) intern;
+  status = yperr2nss (yp_all (domainname, "rpc.bynumber", &ypcb));
+
+  /* Mark the last buffer as full.  */
+  if (intern->next != NULL)
+    intern->next->size = intern->offset;
+
+  intern->next = intern->start;
+  intern->offset = 0;
+
+  return status;
+}
+
+enum nss_status
+_nss_nis_setrpcent (int stayopen)
+{
+  enum nss_status status;
+
+  __libc_lock_lock (lock);
+
+  status = internal_nis_setrpcent (&intern);
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+enum nss_status
+_nss_nis_endrpcent (void)
+{
+  __libc_lock_lock (lock);
+
+  internal_nis_endrpcent (&intern);
+
+  __libc_lock_unlock (lock);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+static enum nss_status
+internal_nis_getrpcent_r (struct rpcent *rpc, char *buffer, size_t buflen,
+			  int *errnop, intern_t *intern)
+{
+  struct parser_data *pdata = (void *) buffer;
+  int parse_res;
+  char *p;
+
+  if (intern->start == NULL)
+    internal_nis_setrpcent (intern);
+
+  if (intern->next == NULL)
+    /* Not one entry in the map.  */
+    return NSS_STATUS_NOTFOUND;
+
+  /* Get the next entry until we found a correct one. */
+  do
+    {
+      struct response_t *bucket = intern->next;
+
+      if (__glibc_unlikely (intern->offset >= bucket->size))
+	{
+	  if (bucket->next == NULL)
+	    return NSS_STATUS_NOTFOUND;
+
+	  /* We look at all the content in the current bucket.  Go on
+	     to the next.  */
+	  bucket = intern->next = bucket->next;
+	  intern->offset = 0;
+	}
+
+      for (p = &bucket->mem[intern->offset]; isspace (*p); ++p)
+        ++intern->offset;
+
+      size_t len = strlen (p) + 1;
+      if (__glibc_unlikely (len > buflen))
+	{
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+
+      /* We unfortunately have to copy the data in the user-provided
+	 buffer because that buffer might be around for a very long
+	 time and the servent structure must remain valid.  If we would
+	 rely on the BUCKET memory the next 'setservent' or 'endservent'
+	 call would destroy it.
+
+	 The important thing is that it is a single NUL-terminated
+	 string.  This is what the parsing routine expects.  */
+      p = memcpy (buffer, &bucket->mem[intern->offset], len);
+
+      parse_res = _nss_files_parse_rpcent (p, rpc, pdata, buflen, errnop);
+      if (__glibc_unlikely (parse_res == -1))
+	return NSS_STATUS_TRYAGAIN;
+
+      intern->offset += len;
+    }
+  while (!parse_res);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nis_getrpcent_r (struct rpcent *rpc, char *buffer, size_t buflen,
+		      int *errnop)
+{
+  enum nss_status status;
+
+  __libc_lock_lock (lock);
+
+  status = internal_nis_getrpcent_r (rpc, buffer, buflen, errnop, &intern);
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+enum nss_status
+_nss_nis_getrpcbyname_r (const char *name, struct rpcent *rpc,
+			 char *buffer, size_t buflen, int *errnop)
+{
+  if (name == NULL)
+    {
+      *errnop = EINVAL;
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  intern_t data = { NULL, NULL, 0 };
+  enum nss_status status = internal_nis_setrpcent (&data);
+  if (__glibc_unlikely (status != NSS_STATUS_SUCCESS))
+    return status;
+
+  int found = 0;
+  while (!found &&
+         ((status = internal_nis_getrpcent_r (rpc, buffer, buflen, errnop,
+					      &data)) == NSS_STATUS_SUCCESS))
+    {
+      if (strcmp (rpc->r_name, name) == 0)
+	found = 1;
+      else
+	{
+	  int i = 0;
+
+	  while (rpc->r_aliases[i] != NULL)
+	    {
+	      if (strcmp (rpc->r_aliases[i], name) == 0)
+		{
+		  found = 1;
+		  break;
+		}
+	      else
+		++i;
+	    }
+	}
+    }
+
+  internal_nis_endrpcent (&data);
+
+  if (__glibc_unlikely (!found && status == NSS_STATUS_SUCCESS))
+    return NSS_STATUS_NOTFOUND;
+
+  return status;
+}
+
+enum nss_status
+_nss_nis_getrpcbynumber_r (int number, struct rpcent *rpc,
+			   char *buffer, size_t buflen, int *errnop)
+{
+  char *domain;
+  if (__glibc_unlikely (yp_get_default_domain (&domain)))
+    return NSS_STATUS_UNAVAIL;
+
+  char buf[32];
+  int nlen = snprintf (buf, sizeof (buf), "%d", number);
+
+  char *result;
+  int len;
+  int yperr = yp_match (domain, "rpc.bynumber", buf, nlen, &result, &len);
+
+  if (__glibc_unlikely (yperr != YPERR_SUCCESS))
+    {
+      enum nss_status retval = yperr2nss (yperr);
+
+      if (retval == NSS_STATUS_TRYAGAIN)
+	*errnop = errno;
+      return retval;
+    }
+
+  if (__glibc_unlikely ((size_t) (len + 1) > buflen))
+    {
+      free (result);
+      *errnop = ERANGE;
+      return NSS_STATUS_TRYAGAIN;
+    }
+
+  char *p = strncpy (buffer, result, len);
+  buffer[len] = '\0';
+  while (isspace (*p))
+    ++p;
+  free (result);
+
+  int parse_res = _nss_files_parse_rpcent (p, rpc, (void  *) buffer, buflen,
+					   errnop);
+  if (__glibc_unlikely (parse_res < 1))
+    {
+      if (parse_res == -1)
+	return NSS_STATUS_TRYAGAIN;
+      else
+	return NSS_STATUS_NOTFOUND;
+    }
+  else
+    return NSS_STATUS_SUCCESS;
+}
diff --git a/REORG.TODO/nis/nss_nis/nis-service.c b/REORG.TODO/nis/nss_nis/nis-service.c
new file mode 100644
index 0000000000..fe628aa139
--- /dev/null
+++ b/REORG.TODO/nis/nss_nis/nis-service.c
@@ -0,0 +1,438 @@
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <nss.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <libc-lock.h>
+#include <rpcsvc/yp.h>
+#include <rpcsvc/ypclnt.h>
+
+#include "nss-nis.h"
+#include <libnsl.h>
+
+
+/* Get the declaration of the parser function.  */
+#define ENTNAME servent
+#define EXTERN_PARSER
+#include <nss/nss_files/files-parse.c>
+
+__libc_lock_define_initialized (static, lock)
+
+static intern_t intern;
+
+struct search_t
+{
+  const char *name;
+  const char *proto;
+  int port;
+  enum nss_status status;
+  struct servent *serv;
+  char *buffer;
+  size_t buflen;
+  int *errnop;
+};
+
+static int
+dosearch (int instatus, char *inkey, int inkeylen, char *inval,
+	  int invallen, char *indata)
+{
+  struct search_t *req = (struct search_t *) indata;
+
+  if (__glibc_unlikely (instatus != YP_TRUE))
+    return 1;
+
+  if (inkey && inkeylen > 0 && inval && invallen > 0)
+    {
+      if (__glibc_unlikely ((size_t) (invallen + 1) > req->buflen))
+	{
+	  *req->errnop = ERANGE;
+	  req->status = NSS_STATUS_TRYAGAIN;
+	  return 1;
+	}
+
+      char *p = strncpy (req->buffer, inval, invallen);
+      req->buffer[invallen] = '\0';
+      while (isspace (*p))
+        ++p;
+
+      int parse_res = _nss_files_parse_servent (p, req->serv,
+						(void *) req->buffer,
+						req->buflen, req->errnop);
+      if (parse_res == -1)
+	{
+	  req->status = NSS_STATUS_TRYAGAIN;
+	  return 1;
+	}
+
+      if (!parse_res)
+        return 0;
+
+      if (req->proto != NULL && strcmp (req->serv->s_proto, req->proto) != 0)
+	return 0;
+
+      if (req->port != -1 && req->serv->s_port != req->port)
+	return 0;
+
+      if (req->name != NULL && strcmp (req->serv->s_name, req->name) != 0)
+	{
+	  char **cp;
+	  for (cp = req->serv->s_aliases; *cp; cp++)
+	    if (strcmp (req->name, *cp) == 0)
+	      break;
+
+	  if (*cp == NULL)
+	    return 0;
+	}
+
+      req->status = NSS_STATUS_SUCCESS;
+      return 1;
+    }
+
+  return 0;
+}
+
+static void
+internal_nis_endservent (void)
+{
+  struct response_t *curr = intern.next;
+
+  while (curr != NULL)
+    {
+      struct response_t *last = curr;
+      curr = curr->next;
+      free (last);
+    }
+
+  intern.next = intern.start = NULL;
+}
+
+enum nss_status
+_nss_nis_endservent (void)
+{
+  __libc_lock_lock (lock);
+
+  internal_nis_endservent ();
+
+  __libc_lock_unlock (lock);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+static enum nss_status
+internal_nis_setservent (void)
+{
+  char *domainname;
+  struct ypall_callback ypcb;
+  enum nss_status status;
+
+  if (yp_get_default_domain (&domainname))
+    return NSS_STATUS_UNAVAIL;
+
+  internal_nis_endservent ();
+
+  ypcb.foreach = _nis_saveit;
+  ypcb.data = (char *) &intern;
+  status = yperr2nss (yp_all (domainname, "services.byname", &ypcb));
+
+  /* Mark the last buffer as full.  */
+  if (intern.next != NULL)
+    intern.next->size = intern.offset;
+
+  intern.next = intern.start;
+  intern.offset = 0;
+
+  return status;
+}
+
+enum nss_status
+_nss_nis_setservent (int stayopen)
+{
+  enum nss_status status;
+
+  __libc_lock_lock (lock);
+
+  status = internal_nis_setservent ();
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+static enum nss_status
+internal_nis_getservent_r (struct servent *serv, char *buffer,
+			   size_t buflen, int *errnop)
+{
+  struct parser_data *pdata = (void *) buffer;
+  int parse_res;
+  char *p;
+
+  if (intern.start == NULL)
+    internal_nis_setservent ();
+
+  if (intern.next == NULL)
+    /* Not one entry in the map.  */
+    return NSS_STATUS_NOTFOUND;
+
+  /* Get the next entry until we found a correct one.  */
+  do
+    {
+      struct response_t *bucket = intern.next;
+
+      if (__glibc_unlikely (intern.offset >= bucket->size))
+	{
+	  if (bucket->next == NULL)
+	    return NSS_STATUS_NOTFOUND;
+
+	  /* We look at all the content in the current bucket.  Go on
+	     to the next.  */
+	  bucket = intern.next = bucket->next;
+	  intern.offset = 0;
+	}
+
+      for (p = &bucket->mem[intern.offset]; isspace (*p); ++p)
+        ++intern.offset;
+
+      size_t len = strlen (p) + 1;
+      if (__glibc_unlikely (len > buflen))
+	{
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+
+      /* We unfortunately have to copy the data in the user-provided
+	 buffer because that buffer might be around for a very long
+	 time and the servent structure must remain valid.  If we would
+	 rely on the BUCKET memory the next 'setservent' or 'endservent'
+	 call would destroy it.
+
+	 The important thing is that it is a single NUL-terminated
+	 string.  This is what the parsing routine expects.  */
+      p = memcpy (buffer, &bucket->mem[intern.offset], len);
+
+      parse_res = _nss_files_parse_servent (p, serv, pdata, buflen, errnop);
+      if (__glibc_unlikely (parse_res == -1))
+        return NSS_STATUS_TRYAGAIN;
+
+      intern.offset += len;
+    }
+  while (!parse_res);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nis_getservent_r (struct servent *serv, char *buffer, size_t buflen,
+		       int *errnop)
+{
+  enum nss_status status;
+
+  __libc_lock_lock (lock);
+
+  status = internal_nis_getservent_r (serv, buffer, buflen, errnop);
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+enum nss_status
+_nss_nis_getservbyname_r (const char *name, const char *protocol,
+			  struct servent *serv, char *buffer, size_t buflen,
+			  int *errnop)
+{
+  if (name == NULL)
+    {
+      *errnop = EINVAL;
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  char *domain;
+  if (__glibc_unlikely (yp_get_default_domain (&domain)))
+    return NSS_STATUS_UNAVAIL;
+
+  /* If the protocol is given, we could try if our NIS server knows
+     about services.byservicename map. If yes, we only need one query.  */
+  size_t keylen = strlen (name) + (protocol ? 1 + strlen (protocol) : 0);
+  /* Limit key length to the maximum size of an RPC packet.  */
+  if (keylen > UDPMSGSIZE)
+    {
+      *errnop = ERANGE;
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  char key[keylen + 1];
+
+  /* key is: "name/proto" */
+  char *cp = stpcpy (key, name);
+  if (protocol != NULL)
+    {
+      *cp++ = '/';
+      strcpy (cp, protocol);
+    }
+
+  char *result;
+  int int_len;
+  int status = yp_match (domain, "services.byservicename", key,
+			 keylen, &result, &int_len);
+  size_t len = int_len;
+
+  /* If we found the key, it's ok and parse the result. If not,
+     fall through and parse the complete table. */
+  if (__glibc_likely (status == YPERR_SUCCESS))
+    {
+      if (__glibc_unlikely ((size_t) (len + 1) > buflen))
+	{
+	  free (result);
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+
+      char *p = strncpy (buffer, result, len);
+      buffer[len] = '\0';
+      while (isspace (*p))
+	++p;
+      free (result);
+
+      int parse_res = _nss_files_parse_servent (p, serv, (void *) buffer,
+						buflen, errnop);
+      if (__glibc_unlikely (parse_res < 0))
+	{
+	  if (parse_res == -1)
+	    return NSS_STATUS_TRYAGAIN;
+	  else
+	    return NSS_STATUS_NOTFOUND;
+	}
+      else
+	return NSS_STATUS_SUCCESS;
+    }
+
+  /* Check if it is safe to rely on services.byservicename.  */
+  if (_nsl_default_nss () & NSS_FLAG_SERVICES_AUTHORITATIVE)
+    return yperr2nss (status);
+
+  struct ypall_callback ypcb;
+  struct search_t req;
+
+  ypcb.foreach = dosearch;
+  ypcb.data = (char *) &req;
+  req.name = name;
+  req.proto = protocol;
+  req.port = -1;
+  req.serv = serv;
+  req.buffer = buffer;
+  req.buflen = buflen;
+  req.errnop = errnop;
+  req.status = NSS_STATUS_NOTFOUND;
+  status = yp_all (domain, "services.byname", &ypcb);
+
+  if (__glibc_unlikely (status != YPERR_SUCCESS))
+    return yperr2nss (status);
+
+  return req.status;
+}
+
+enum nss_status
+_nss_nis_getservbyport_r (int port, const char *protocol,
+			  struct servent *serv, char *buffer,
+			  size_t buflen, int *errnop)
+{
+  char *domain;
+  if (__glibc_unlikely (yp_get_default_domain (&domain)))
+    return NSS_STATUS_UNAVAIL;
+
+  /* If the protocol is given, we only need one query.
+     Otherwise try first port/tcp, then port/udp and then fallback
+     to sequential scanning of services.byname.  */
+  const char *proto = protocol != NULL ? protocol : "tcp";
+  /* Limit protocol name length to the maximum size of an RPC packet.  */
+  if (strlen (proto) > UDPMSGSIZE)
+    {
+      *errnop = ERANGE;
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  do
+    {
+      /* key is: "port/proto" */
+      char key[sizeof (int) * 3 + strlen (proto) + 2];
+      size_t keylen = snprintf (key, sizeof (key), "%d/%s", ntohs (port),
+				proto);
+
+      char *result;
+      int int_len;
+      int status = yp_match (domain, "services.byname", key, keylen, &result,
+			     &int_len);
+      size_t len = int_len;
+
+      /* If we found the key, it's ok and parse the result. If not,
+	 fall through and parse the complete table. */
+      if (__glibc_likely (status == YPERR_SUCCESS))
+	{
+	  if (__glibc_unlikely ((size_t) (len + 1) > buflen))
+	    {
+	      free (result);
+	      *errnop = ERANGE;
+	      return NSS_STATUS_TRYAGAIN;
+	    }
+
+	  char  *p = strncpy (buffer, result, len);
+	  buffer[len] = '\0';
+	  while (isspace (*p))
+	    ++p;
+	  free (result);
+	  int parse_res = _nss_files_parse_servent (p, serv, (void *) buffer,
+						    buflen, errnop);
+	  if (__glibc_unlikely (parse_res < 0))
+	    {
+	      if (parse_res == -1)
+		return NSS_STATUS_TRYAGAIN;
+	      else
+		return NSS_STATUS_NOTFOUND;
+	    }
+
+	  return NSS_STATUS_SUCCESS;
+	}
+    }
+  while (protocol == NULL && (proto[0] == 't' ? (proto = "udp") : NULL));
+
+  if (port == -1)
+    return NSS_STATUS_NOTFOUND;
+
+  struct ypall_callback ypcb;
+  struct search_t req;
+
+  ypcb.foreach = dosearch;
+  ypcb.data = (char *) &req;
+  req.name = NULL;
+  req.proto = protocol;
+  req.port = port;
+  req.serv = serv;
+  req.buffer = buffer;
+  req.buflen = buflen;
+  req.errnop = errnop;
+  req.status = NSS_STATUS_NOTFOUND;
+  int status = yp_all (domain, "services.byname", &ypcb);
+
+  if (__glibc_unlikely (status != YPERR_SUCCESS))
+    return yperr2nss (status);
+
+  return req.status;
+}
diff --git a/REORG.TODO/nis/nss_nis/nis-spwd.c b/REORG.TODO/nis/nss_nis/nis-spwd.c
new file mode 100644
index 0000000000..45e9d964d2
--- /dev/null
+++ b/REORG.TODO/nis/nss_nis/nis-spwd.c
@@ -0,0 +1,235 @@
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <nss.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+/* The following is an ugly trick to avoid a prototype declaration for
+   _nss_nis_endspent.  */
+#define _nss_nis_endspent _nss_nis_endspent_XXX
+#include <shadow.h>
+#undef _nss_nis_endspent
+#include <libc-lock.h>
+#include <rpcsvc/yp.h>
+#include <rpcsvc/ypclnt.h>
+
+#include "nss-nis.h"
+#include <libnsl.h>
+
+/* Get the declaration of the parser function.  */
+#define ENTNAME spent
+#define STRUCTURE spwd
+#define EXTERN_PARSER
+#include <nss/nss_files/files-parse.c>
+
+/* Protect global state against multiple changers */
+__libc_lock_define_initialized (static, lock)
+
+static bool new_start = true;
+static bool ent_adjunct_used;
+static char *oldkey;
+static int oldkeylen;
+
+enum nss_status
+_nss_nis_setspent (int stayopen)
+{
+  __libc_lock_lock (lock);
+
+  new_start = true;
+  ent_adjunct_used = false;
+  free (oldkey);
+  oldkey = NULL;
+  oldkeylen = 0;
+
+  __libc_lock_unlock (lock);
+
+  return NSS_STATUS_SUCCESS;
+}
+/* Make _nss_nis_endspent an alias of _nss_nis_setspent.  We do this
+   even though the prototypes don't match.  The argument of setspent
+   is not used so this makes no difference.  */
+strong_alias (_nss_nis_setspent, _nss_nis_endspent)
+
+static enum nss_status
+internal_nis_getspent_r (struct spwd *sp, char *buffer, size_t buflen,
+			 int *errnop)
+{
+  char *domain;
+  if (__glibc_unlikely (yp_get_default_domain (&domain)))
+    return NSS_STATUS_UNAVAIL;
+
+  /* Get the next entry until we found a correct one. */
+  int parse_res;
+  do
+    {
+      char *result;
+      char *outkey;
+      int len;
+      int keylen;
+      int yperr;
+
+      if (new_start)
+	{
+	  yperr = yp_first (domain, "shadow.byname", &outkey, &keylen, &result,
+			    &len);
+	  if (__builtin_expect (yperr == YPERR_MAP, 0)
+	      && (_nsl_default_nss () & NSS_FLAG_ADJUNCT_AS_SHADOW))
+	    {
+	      free (result);
+	      yperr = yp_first (domain, "passwd.adjunct.byname", &outkey,
+				&keylen, &result, &len);
+	      ent_adjunct_used = true;
+	    }
+	}
+      else
+	yperr = yp_next (domain, (ent_adjunct_used
+				  ? "passwd.adjunct.byname" : "shadow.byname"),
+			 oldkey, oldkeylen, &outkey, &keylen, &result, &len);
+
+      if (__glibc_unlikely (yperr != YPERR_SUCCESS))
+	{
+	  enum nss_status retval = yperr2nss (yperr);
+
+	  if (retval == NSS_STATUS_TRYAGAIN)
+	    *errnop = errno;
+	  return retval;
+	}
+
+      if (__builtin_expect ((size_t) (len + (ent_adjunct_used ? 3 : 1))
+			    > buflen, 0))
+	{
+	  free (result);
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+
+      char *p = strncpy (buffer, result, len);
+      if (ent_adjunct_used)
+	/* This is an ugly trick.  The format of passwd.adjunct.byname almost
+	   matches the shadow.byname format except that the last two fields
+	   are missing.  Synthesize them by marking them empty.  */
+	strcpy (&buffer[len], "::");
+      else
+	buffer[len] = '\0';
+      while (isspace (*p))
+	++p;
+      free (result);
+
+      parse_res = _nss_files_parse_spent (p, sp, (void *) buffer, buflen,
+					  errnop);
+      if (__builtin_expect  (parse_res == -1, 0))
+	{
+	  free (outkey);
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+
+      free (oldkey);
+      oldkey = outkey;
+      oldkeylen = keylen;
+      new_start = false;
+    }
+  while (!parse_res);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nis_getspent_r (struct spwd *result, char *buffer, size_t buflen,
+		     int *errnop)
+{
+  int status;
+
+  __libc_lock_lock (lock);
+
+  status = internal_nis_getspent_r (result, buffer, buflen, errnop);
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+enum nss_status
+_nss_nis_getspnam_r (const char *name, struct spwd *sp,
+		     char *buffer, size_t buflen, int *errnop)
+{
+  if (name == NULL)
+    {
+      *errnop = EINVAL;
+      return NSS_STATUS_UNAVAIL;
+    }
+  const size_t name_len = strlen (name);
+
+  char *domain;
+  if (__glibc_unlikely (yp_get_default_domain (&domain)))
+    return NSS_STATUS_UNAVAIL;
+
+  bool adjunct_used = false;
+  char *result;
+  int len;
+  int yperr = yp_match (domain, "shadow.byname", name, name_len, &result,
+			&len);
+  if (__builtin_expect (yperr == YPERR_MAP, 0)
+      && (_nsl_default_nss () & NSS_FLAG_ADJUNCT_AS_SHADOW))
+    {
+      free (result);
+      yperr = yp_match (domain, "passwd.adjunct.byname", name, name_len,
+			&result, &len);
+      adjunct_used = true;
+    }
+
+  if (__glibc_unlikely (yperr != YPERR_SUCCESS))
+    {
+      enum nss_status retval = yperr2nss (yperr);
+
+      if (retval == NSS_STATUS_TRYAGAIN)
+	*errnop = errno;
+      return retval;
+    }
+
+  if (__glibc_unlikely ((size_t) (len + (adjunct_used ? 3 : 1)) > buflen))
+    {
+      free (result);
+      *errnop = ERANGE;
+      return NSS_STATUS_TRYAGAIN;
+    }
+
+  char *p = strncpy (buffer, result, len);
+  if (__builtin_expect (adjunct_used, false))
+    /* This is an ugly trick.  The format of passwd.adjunct.byname almost
+       matches the shadow.byname format except that the last two fields
+       are missing.  Synthesize them by marking them empty.  */
+    strcpy (&buffer[len], "::");
+  else
+    buffer[len] = '\0';
+  while (isspace (*p))
+    ++p;
+  free (result);
+
+  int parse_res = _nss_files_parse_spent (p, sp, (void *) buffer, buflen,
+					  errnop);
+  if (__glibc_unlikely (parse_res < 1))
+    {
+      if (parse_res == -1)
+	return NSS_STATUS_TRYAGAIN;
+      else
+	return NSS_STATUS_NOTFOUND;
+    }
+  return NSS_STATUS_SUCCESS;
+}
diff --git a/REORG.TODO/nis/nss_nisplus/nisplus-alias.c b/REORG.TODO/nis/nss_nisplus/nisplus-alias.c
new file mode 100644
index 0000000000..8301e5a836
--- /dev/null
+++ b/REORG.TODO/nis/nss_nisplus/nisplus-alias.c
@@ -0,0 +1,337 @@
+/* Copyright (C) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <atomic.h>
+#include <nss.h>
+#include <errno.h>
+#include <ctype.h>
+#include <string.h>
+#include <aliases.h>
+#include <libc-lock.h>
+#include <rpcsvc/nis.h>
+
+#include "nss-nisplus.h"
+
+__libc_lock_define_initialized (static, lock)
+
+static nis_result *result;
+static u_long next_entry;
+static nis_name tablename_val;
+static size_t tablename_len;
+
+#define NISENTRYVAL(idx, col, res) \
+        (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val)
+
+#define NISENTRYLEN(idx, col, res) \
+        (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_len)
+
+static enum nss_status
+_nss_create_tablename (int *errnop)
+{
+  if (tablename_val == NULL)
+    {
+      const char *local_dir = nis_local_directory ();
+      size_t local_dir_len = strlen (local_dir);
+      static const char prefix[] = "mail_aliases.org_dir.";
+
+      char *p = malloc (sizeof (prefix) + local_dir_len);
+      if (p == NULL)
+	{
+	  *errnop = errno;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+
+      memcpy (__stpcpy (p, prefix), local_dir, local_dir_len + 1);
+
+      tablename_len = sizeof (prefix) - 1 + local_dir_len;
+
+      atomic_write_barrier ();
+
+      tablename_val = p;
+    }
+
+  return NSS_STATUS_SUCCESS;
+}
+
+static int
+_nss_nisplus_parse_aliasent (nis_result *result, unsigned long entry,
+			     struct aliasent *alias, char *buffer,
+			     size_t buflen, int *errnop)
+{
+  if (result == NULL)
+    return 0;
+
+  if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS)
+      || __type_of (&NIS_RES_OBJECT (result)[entry]) != NIS_ENTRY_OBJ
+      || strcmp (NIS_RES_OBJECT (result)[entry].EN_data.en_type,
+		 "mail_aliases") != 0
+      || NIS_RES_OBJECT (result)[entry].EN_data.en_cols.en_cols_len < 2)
+    return 0;
+
+  if (NISENTRYLEN (entry, 1, result) >= buflen)
+    {
+      /* The line is too long for our buffer.  */
+    no_more_room:
+      *errnop = ERANGE;
+      return -1;
+    }
+
+  char *cp = __stpncpy (buffer, NISENTRYVAL (entry, 1, result),
+			NISENTRYLEN (entry, 1, result));
+  *cp = '\0';
+
+  char *first_unused = cp + 1;
+  size_t room_left = buflen - (first_unused - buffer);
+
+  alias->alias_local = 0;
+  alias->alias_members_len = 0;
+
+  if (NISENTRYLEN (entry, 0, result) >= room_left)
+    goto no_more_room;
+
+  cp = __stpncpy (first_unused, NISENTRYVAL (entry, 0, result),
+		  NISENTRYLEN (entry, 0, result));
+  *cp = '\0';
+  alias->alias_name = first_unused;
+
+  /* Terminate the line for any case.  */
+  cp = strpbrk (alias->alias_name, "#\n");
+  if (cp != NULL)
+    *cp = '\0';
+
+  size_t len = strlen (alias->alias_name) + 1;
+  first_unused += len;
+  room_left -= len;
+
+  /* Adjust the pointer so it is aligned for
+     storing pointers.  */
+  size_t adjust = ((__alignof__ (char *)
+		    - (first_unused - (char *) 0) % __alignof__ (char *))
+		   % __alignof__ (char *));
+  if (room_left < adjust)
+    goto no_more_room;
+  first_unused += adjust;
+  room_left -= adjust;
+
+  alias->alias_members = (char **) first_unused;
+
+  char *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';
+	  ++alias->alias_members_len;
+	}
+      else if (*line == ',')
+	++line;
+    }
+
+  return alias->alias_members_len == 0 ? 0 : 1;
+}
+
+static enum nss_status
+internal_setaliasent (void)
+{
+  enum nss_status status;
+  int err;
+
+  if (result !=  NULL)
+    {
+      nis_freeresult (result);
+      result = NULL;
+    }
+
+  if (_nss_create_tablename (&err) != NSS_STATUS_SUCCESS)
+    return NSS_STATUS_UNAVAIL;
+
+  next_entry = 0;
+  result = nis_list (tablename_val, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
+  if (result == NULL)
+    {
+      status = NSS_STATUS_TRYAGAIN;
+      __set_errno (ENOMEM);
+    }
+  else
+    {
+      status = niserr2nss (result->status);
+      if (status != NSS_STATUS_SUCCESS)
+	{
+	  nis_freeresult (result);
+	  result = NULL;
+	}
+    }
+  return status;
+}
+
+enum nss_status
+_nss_nisplus_setaliasent (void)
+{
+  enum nss_status status;
+
+  __libc_lock_lock (lock);
+
+  status = internal_setaliasent ();
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+enum nss_status
+_nss_nisplus_endaliasent (void)
+{
+  __libc_lock_lock (lock);
+
+  if (result != NULL)
+    {
+      nis_freeresult (result);
+      result = NULL;
+    }
+  next_entry = 0;
+
+  __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 *errnop)
+{
+  int parse_res;
+
+  if (result == NULL)
+    {
+      enum nss_status status;
+
+      status = internal_setaliasent ();
+      if (result == NULL || status != NSS_STATUS_SUCCESS)
+	return status;
+    }
+
+  /* Get the next entry until we found a correct one. */
+  do
+    {
+      if (next_entry >= result->objects.objects_len)
+	return NSS_STATUS_NOTFOUND;
+
+      parse_res = _nss_nisplus_parse_aliasent (result, next_entry, alias,
+					       buffer, buflen, errnop);
+      if (parse_res == -1)
+	return NSS_STATUS_TRYAGAIN;
+
+      ++next_entry;
+    }
+  while (!parse_res);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_getaliasent_r (struct aliasent *result, char *buffer,
+			    size_t buflen, int *errnop)
+{
+  int status;
+
+  __libc_lock_lock (lock);
+
+  status = internal_nisplus_getaliasent_r (result, buffer, buflen, errnop);
+
+  __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 *errnop)
+{
+  int parse_res;
+
+  if (tablename_val == NULL)
+    {
+      __libc_lock_lock (lock);
+
+      enum nss_status status = _nss_create_tablename (errnop);
+
+      __libc_lock_unlock (lock);
+
+      if (status != NSS_STATUS_SUCCESS)
+	return status;
+    }
+
+  if (name == NULL)
+    {
+      *errnop = EINVAL;
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  char buf[strlen (name) + 9 + tablename_len];
+  int olderr = errno;
+
+  snprintf (buf, sizeof (buf), "[name=%s],%s", name, tablename_val);
+
+  nis_result *result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
+
+  if (result == NULL)
+    {
+      *errnop = ENOMEM;
+      return NSS_STATUS_TRYAGAIN;
+    }
+
+  if (__glibc_unlikely (niserr2nss (result->status) != NSS_STATUS_SUCCESS))
+    {
+      enum nss_status status = niserr2nss (result->status);
+      nis_freeresult (result);
+      return status;
+    }
+
+  parse_res = _nss_nisplus_parse_aliasent (result, 0, alias,
+					   buffer, buflen, errnop);
+
+  /* We do not need the lookup result anymore.  */
+  nis_freeresult (result);
+
+  if (__glibc_unlikely (parse_res < 1))
+    {
+      __set_errno (olderr);
+
+      if (parse_res == -1)
+	return NSS_STATUS_TRYAGAIN;
+      else
+	return NSS_STATUS_NOTFOUND;
+    }
+
+  return NSS_STATUS_SUCCESS;
+}
diff --git a/REORG.TODO/nis/nss_nisplus/nisplus-ethers.c b/REORG.TODO/nis/nss_nisplus/nisplus-ethers.c
new file mode 100644
index 0000000000..bb20696a49
--- /dev/null
+++ b/REORG.TODO/nis/nss_nisplus/nisplus-ethers.c
@@ -0,0 +1,356 @@
+/* Copyright (C) 1997-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <atomic.h>
+#include <ctype.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <netdb.h>
+#include <nss.h>
+#include <string.h>
+#include <netinet/ether.h>
+#include <netinet/if_ether.h>
+#include <rpcsvc/nis.h>
+#include <libc-lock.h>
+
+#include "nss-nisplus.h"
+
+__libc_lock_define_initialized (static, lock)
+
+static nis_result *result;
+static nis_name tablename_val;
+static u_long tablename_len;
+
+
+#define NISENTRYVAL(idx, col, res) \
+	(NIS_RES_OBJECT (res)[idx].zo_data.objdata_u.en_data.en_cols.en_cols_val[col].ec_value.ec_value_val)
+
+#define NISENTRYLEN(idx, col, res) \
+	(NIS_RES_OBJECT (res)[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, int *errnop)
+{
+  char *p = buffer;
+  size_t room_left = buflen;
+
+  if (result == NULL)
+    return 0;
+
+  if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS)
+      || NIS_RES_NUMOBJ (result) != 1
+      || __type_of (NIS_RES_OBJECT (result)) != NIS_ENTRY_OBJ
+      || strcmp (NIS_RES_OBJECT (result)->EN_data.en_type,
+		 "ethers_tbl") != 0
+      || NIS_RES_OBJECT (result)->EN_data.en_cols.en_cols_len < 2)
+    return 0;
+
+  /* Generate the ether entry format and use the normal parser */
+  if (NISENTRYLEN (0, 0, result) + 1 > room_left)
+    {
+      *errnop = ERANGE;
+      return -1;
+    }
+  char *cp = __stpncpy (p, NISENTRYVAL (0, 0, result),
+			NISENTRYLEN (0, 0, result));
+  *cp = '\0';
+  room_left -= NISENTRYLEN (0, 0, result) + 1;
+  ether->e_name = p;
+
+  struct ether_addr *ea = ether_aton (NISENTRYVAL (0, 1, result));
+  if (ea == NULL)
+    {
+      *errnop = EINVAL;
+      return -2;
+    }
+
+  ether->e_addr = *ea;
+
+  return 1;
+}
+
+static enum nss_status
+_nss_create_tablename (int *errnop)
+{
+  if (tablename_val == NULL)
+    {
+      const char *local_dir = nis_local_directory ();
+      size_t local_dir_len = strlen (local_dir);
+      static const char prefix[] = "ethers.org_dir.";
+
+      char *p = malloc (sizeof (prefix) + local_dir_len);
+      if (p == NULL)
+	{
+	  *errnop = errno;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+
+      memcpy (__stpcpy (p, prefix), local_dir, local_dir_len + 1);
+
+      tablename_len = sizeof (prefix) - 1 + local_dir_len;
+
+      atomic_write_barrier ();
+
+      tablename_val = p;
+    }
+  return NSS_STATUS_SUCCESS;
+}
+
+
+enum nss_status
+_nss_nisplus_setetherent (int stayopen)
+{
+  enum nss_status status;
+  int err;
+
+  status = NSS_STATUS_SUCCESS;
+
+  __libc_lock_lock (lock);
+
+  if (result != NULL)
+    {
+      nis_freeresult (result);
+      result = NULL;
+    }
+
+  if (_nss_create_tablename (&err) != NSS_STATUS_SUCCESS)
+    status = NSS_STATUS_UNAVAIL;
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+enum nss_status
+_nss_nisplus_endetherent (void)
+{
+  __libc_lock_lock (lock);
+
+  if (result != NULL)
+    {
+      nis_freeresult (result);
+      result = 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 *errnop)
+{
+  if (tablename_val == NULL)
+    {
+      enum nss_status status = _nss_create_tablename (errnop);
+
+      if (status != NSS_STATUS_SUCCESS)
+	return status;
+    }
+
+  /* Get the next entry until we found a correct one. */
+  int parse_res;
+  do
+    {
+      nis_result *saved_result;
+
+      if (result == NULL)
+	{
+	  saved_result = NULL;
+	  result = nis_first_entry (tablename_val);
+	  if (result == NULL)
+	    {
+	      *errnop = errno;
+	      return NSS_STATUS_TRYAGAIN;
+	    }
+	  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	    return niserr2nss (result->status);
+	}
+      else
+	{
+	  saved_result = result;
+	  result = nis_next_entry (tablename_val, &result->cookie);
+	  if (result == NULL)
+	    {
+	      *errnop = errno;
+	      return NSS_STATUS_TRYAGAIN;
+	    }
+	  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	    {
+	      nis_freeresult (saved_result);
+	      return niserr2nss (result->status);
+	    }
+	}
+
+      parse_res = _nss_nisplus_parse_etherent (result, ether, buffer,
+					       buflen, errnop);
+      if (parse_res == -1)
+	{
+	  nis_freeresult (result);
+	  result = saved_result;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+
+      if (saved_result != NULL)
+	nis_freeresult (saved_result);
+
+    }
+  while (!parse_res);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_getetherent_r (struct etherent *result, char *buffer,
+			    size_t buflen, int *errnop)
+{
+  int status;
+
+  __libc_lock_lock (lock);
+
+  status = internal_nisplus_getetherent_r (result, buffer, buflen, errnop);
+
+  __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 *errnop)
+{
+  if (tablename_val == NULL)
+    {
+      enum nss_status status = _nss_create_tablename (errnop);
+
+      if (status != NSS_STATUS_SUCCESS)
+	return status;
+    }
+
+  if (name == NULL)
+    {
+      *errnop = EINVAL;
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  char buf[strlen (name) + 9 + tablename_len];
+  int olderr = errno;
+
+  snprintf (buf, sizeof (buf), "[name=%s],%s", name, tablename_val);
+
+  nis_result *result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS | USE_DGRAM,
+				 NULL, NULL);
+
+  if (result == NULL)
+    {
+      *errnop = ENOMEM;
+      return NSS_STATUS_TRYAGAIN;
+    }
+
+  if (__glibc_unlikely (niserr2nss (result->status) != NSS_STATUS_SUCCESS))
+    {
+      enum nss_status status = niserr2nss (result->status);
+      nis_freeresult (result);
+      return status;
+    }
+
+  int parse_res = _nss_nisplus_parse_etherent (result, eth, buffer,
+					       buflen, errnop);
+
+  /* We do not need the lookup result anymore.  */
+  nis_freeresult (result);
+
+  if (__glibc_unlikely (parse_res < 1))
+    {
+      __set_errno (olderr);
+
+      if (parse_res == -1)
+	return NSS_STATUS_TRYAGAIN;
+
+      return NSS_STATUS_NOTFOUND;
+    }
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_getntohost_r (const struct ether_addr *addr, struct etherent *eth,
+			   char *buffer, size_t buflen, int *errnop)
+{
+  if (tablename_val == NULL)
+    {
+      __libc_lock_lock (lock);
+
+      enum nss_status status = _nss_create_tablename (errnop);
+
+      __libc_lock_unlock (lock);
+
+      if (status != NSS_STATUS_SUCCESS)
+	return status;
+    }
+
+  if (addr == NULL)
+    {
+      *errnop = EINVAL;
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  char buf[26 + tablename_len];
+
+  snprintf (buf, sizeof (buf),
+	    "[addr=%" PRIx8 ":%" PRIx8 ":%" PRIx8 ":%" PRIx8 ":%" PRIx8
+	    ":%" PRIx8 "],%s",
+	    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],
+	    tablename_val);
+
+  nis_result *result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS | USE_DGRAM,
+				 NULL, NULL);
+
+  if (result == NULL)
+    {
+      *errnop = ENOMEM;
+      return NSS_STATUS_TRYAGAIN;
+    }
+
+  if (__glibc_unlikely (niserr2nss (result->status) != NSS_STATUS_SUCCESS))
+    {
+      enum nss_status status = niserr2nss (result->status);
+      nis_freeresult (result);
+      return status;
+    }
+
+  int parse_res = _nss_nisplus_parse_etherent (result, eth, buffer,
+					       buflen, errnop);
+
+  /* We do not need the lookup result anymore.  */
+  nis_freeresult (result);
+
+  if (__glibc_unlikely (parse_res < 1))
+    {
+      if (parse_res == -1)
+	return NSS_STATUS_TRYAGAIN;
+
+      return NSS_STATUS_NOTFOUND;
+    }
+
+  return NSS_STATUS_SUCCESS;
+}
diff --git a/REORG.TODO/nis/nss_nisplus/nisplus-grp.c b/REORG.TODO/nis/nss_nisplus/nisplus-grp.c
new file mode 100644
index 0000000000..124b8b85b5
--- /dev/null
+++ b/REORG.TODO/nis/nss_nisplus/nisplus-grp.c
@@ -0,0 +1,401 @@
+/* Copyright (C) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <atomic.h>
+#include <nss.h>
+#include <grp.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <libc-lock.h>
+#include <rpcsvc/nis.h>
+
+#include "nss-nisplus.h"
+#include "nisplus-parser.h"
+#include <libnsl.h>
+#include <nis_intern.h>
+#include <nis_xdr.h>
+
+
+__libc_lock_define_initialized (static, lock);
+
+/* Connection information.  */
+static ib_request *ibreq;
+static directory_obj *dir;
+static dir_binding bptr;
+static char *tablepath;
+static char *tableptr;
+/* Cursor.  */
+static netobj cursor;
+
+
+nis_name grp_tablename_val attribute_hidden;
+size_t grp_tablename_len attribute_hidden;
+
+enum nss_status
+_nss_grp_create_tablename (int *errnop)
+{
+  if (grp_tablename_val == NULL)
+    {
+      const char *local_dir = nis_local_directory ();
+      size_t local_dir_len = strlen (local_dir);
+      static const char prefix[] = "group.org_dir.";
+
+      char *p = malloc (sizeof (prefix) + local_dir_len);
+      if (p == NULL)
+	{
+	  *errnop = errno;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+
+      memcpy (__stpcpy (p, prefix), local_dir, local_dir_len + 1);
+
+      grp_tablename_len = sizeof (prefix) - 1 + local_dir_len;
+
+      atomic_write_barrier ();
+
+      if (atomic_compare_and_exchange_bool_acq (&grp_tablename_val, p, NULL))
+	{
+	  /* Another thread already installed the value.  */
+	  free (p);
+	  grp_tablename_len = strlen (grp_tablename_val);
+	}
+    }
+
+  return NSS_STATUS_SUCCESS;
+}
+
+
+static void
+internal_endgrent (void)
+{
+  __nisbind_destroy (&bptr);
+  memset (&bptr, '\0', sizeof (bptr));
+
+  nis_free_directory (dir);
+  dir = NULL;
+
+  nis_free_request (ibreq);
+  ibreq = NULL;
+
+  xdr_free ((xdrproc_t) xdr_netobj, (char *) &cursor);
+  memset (&cursor, '\0', sizeof (cursor));
+
+  free (tablepath);
+  tableptr = tablepath = NULL;
+}
+
+
+static enum nss_status
+internal_setgrent (int *errnop)
+{
+  enum nss_status status = NSS_STATUS_SUCCESS;
+
+  if (grp_tablename_val == NULL)
+    status = _nss_grp_create_tablename (errnop);
+
+  if (status == NSS_STATUS_SUCCESS)
+    {
+      ibreq = __create_ib_request (grp_tablename_val, 0);
+      if (ibreq == NULL)
+	{
+	  *errnop = errno;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+
+      nis_error retcode = __prepare_niscall (grp_tablename_val, &dir, &bptr, 0);
+      if (retcode != NIS_SUCCESS)
+	{
+	  nis_free_request (ibreq);
+	  ibreq = NULL;
+	  status = niserr2nss (retcode);
+	}
+    }
+
+  return status;
+}
+
+
+enum nss_status
+_nss_nisplus_setgrent (int stayopen)
+{
+  enum nss_status status;
+
+  __libc_lock_lock (lock);
+
+  internal_endgrent ();
+
+  // XXX We need to be able to set errno.  Pass in new parameter.
+  int err;
+  status = internal_setgrent (&err);
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+
+enum nss_status
+_nss_nisplus_endgrent (void)
+{
+  __libc_lock_lock (lock);
+
+  internal_endgrent ();
+
+  __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 *errnop)
+{
+  int parse_res = -1;
+  enum nss_status retval = NSS_STATUS_SUCCESS;
+
+  /* Get the next entry until we found a correct one. */
+  do
+    {
+      nis_error status;
+      nis_result result;
+      memset (&result, '\0', sizeof (result));
+
+      if (cursor.n_bytes == NULL)
+	{
+	  if (ibreq == NULL)
+	    {
+	      retval = internal_setgrent (errnop);
+	      if (retval != NSS_STATUS_SUCCESS)
+		return retval;
+	    }
+
+	  status = __do_niscall3 (&bptr, NIS_IBFIRST,
+				  (xdrproc_t) _xdr_ib_request,
+				  (caddr_t) ibreq,
+				  (xdrproc_t) _xdr_nis_result,
+				  (caddr_t) &result,
+				  0, NULL);
+	}
+      else
+	{
+	  ibreq->ibr_cookie.n_bytes = cursor.n_bytes;
+	  ibreq->ibr_cookie.n_len = cursor.n_len;
+
+	  status = __do_niscall3 (&bptr, NIS_IBNEXT,
+				  (xdrproc_t) _xdr_ib_request,
+				  (caddr_t) ibreq,
+				  (xdrproc_t) _xdr_nis_result,
+				  (caddr_t) &result,
+				  0, NULL);
+
+	  ibreq->ibr_cookie.n_bytes = NULL;
+	  ibreq->ibr_cookie.n_len = 0;
+	}
+
+      if (status != NIS_SUCCESS)
+	return niserr2nss (status);
+
+      if (NIS_RES_STATUS (&result) == NIS_NOTFOUND)
+	{
+	  /* No more entries on this server.  This means we have to go
+	     to the next server on the path.  */
+	  status = __follow_path (&tablepath, &tableptr, ibreq, &bptr);
+	  if (status != NIS_SUCCESS)
+	    return niserr2nss (status);
+
+	  directory_obj *newdir = NULL;
+	  dir_binding newbptr;
+	  status = __prepare_niscall (ibreq->ibr_name, &newdir, &newbptr, 0);
+	  if (status != NIS_SUCCESS)
+	    return niserr2nss (status);
+
+	  nis_free_directory (dir);
+	  dir = newdir;
+	  __nisbind_destroy (&bptr);
+	  bptr = newbptr;
+
+	  xdr_free ((xdrproc_t) xdr_netobj, (char *) &result.cookie);
+	  result.cookie.n_bytes = NULL;
+	  result.cookie.n_len = 0;
+	  parse_res = 0;
+	  goto next;
+	}
+      else if (NIS_RES_STATUS (&result) != NIS_SUCCESS)
+	return niserr2nss (NIS_RES_STATUS (&result));
+
+      parse_res = _nss_nisplus_parse_grent (&result, gr,
+					    buffer, buflen, errnop);
+      if (__glibc_unlikely (parse_res == -1))
+	{
+	  *errnop = ERANGE;
+	  retval = NSS_STATUS_TRYAGAIN;
+	  goto freeres;
+	}
+
+    next:
+      /* Free the old cursor.  */
+      xdr_free ((xdrproc_t) xdr_netobj, (char *) &cursor);
+      /* Remember the new one.  */
+      cursor.n_bytes = result.cookie.n_bytes;
+      cursor.n_len = result.cookie.n_len;
+      /* Free the result structure.  NB: we do not remove the cookie.  */
+      result.cookie.n_bytes = NULL;
+      result.cookie.n_len = 0;
+    freeres:
+      xdr_free ((xdrproc_t) _xdr_nis_result, (char *) &result);
+      memset (&result, '\0', sizeof (result));
+    }
+  while (!parse_res);
+
+  return retval;
+}
+
+enum nss_status
+_nss_nisplus_getgrent_r (struct group *result, char *buffer, size_t buflen,
+			 int *errnop)
+{
+  int status;
+
+  __libc_lock_lock (lock);
+
+  status = internal_nisplus_getgrent_r (result, buffer, buflen, errnop);
+
+  __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 *errnop)
+{
+  int parse_res;
+
+  if (grp_tablename_val == NULL)
+    {
+      enum nss_status status = _nss_grp_create_tablename (errnop);
+
+      if (status != NSS_STATUS_SUCCESS)
+	return status;
+    }
+
+  if (name == NULL)
+    {
+      *errnop = EINVAL;
+      return NSS_STATUS_NOTFOUND;
+    }
+
+  nis_result *result;
+  char buf[strlen (name) + 9 + grp_tablename_len];
+  int olderr = errno;
+
+  snprintf (buf, sizeof (buf), "[name=%s],%s", name, grp_tablename_val);
+
+  result = nis_list (buf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL);
+
+  if (result == NULL)
+    {
+      *errnop = ENOMEM;
+      return NSS_STATUS_TRYAGAIN;
+    }
+
+  if (__glibc_unlikely (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, errnop);
+  nis_freeresult (result);
+  if (__glibc_unlikely (parse_res < 1))
+    {
+      if (parse_res == -1)
+	{
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+      else
+	{
+	  __set_errno (olderr);
+	  return NSS_STATUS_NOTFOUND;
+	}
+    }
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_getgrgid_r (const gid_t gid, struct group *gr,
+			 char *buffer, size_t buflen, int *errnop)
+{
+  if (grp_tablename_val == NULL)
+    {
+      enum nss_status status = _nss_grp_create_tablename (errnop);
+
+      if (status != NSS_STATUS_SUCCESS)
+	return status;
+    }
+
+  int parse_res;
+  nis_result *result;
+  char buf[8 + 3 * sizeof (unsigned long int) + grp_tablename_len];
+  int olderr = errno;
+
+  snprintf (buf, sizeof (buf), "[gid=%lu],%s",
+	    (unsigned long int) gid, grp_tablename_val);
+
+  result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
+
+  if (result == NULL)
+    {
+      *errnop = ENOMEM;
+      return NSS_STATUS_TRYAGAIN;
+    }
+
+  if (__glibc_unlikely (niserr2nss (result->status) != NSS_STATUS_SUCCESS))
+    {
+      enum nss_status status = niserr2nss (result->status);
+
+      __set_errno (olderr);
+
+      nis_freeresult (result);
+      return status;
+    }
+
+  parse_res = _nss_nisplus_parse_grent (result, gr, buffer, buflen, errnop);
+
+  nis_freeresult (result);
+  if (__glibc_unlikely (parse_res < 1))
+    {
+      __set_errno (olderr);
+
+      if (parse_res == -1)
+	{
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+      else
+	return NSS_STATUS_NOTFOUND;
+    }
+
+  return NSS_STATUS_SUCCESS;
+}
diff --git a/REORG.TODO/nis/nss_nisplus/nisplus-hosts.c b/REORG.TODO/nis/nss_nisplus/nisplus-hosts.c
new file mode 100644
index 0000000000..31dfd31fbd
--- /dev/null
+++ b/REORG.TODO/nis/nss_nisplus/nisplus-hosts.c
@@ -0,0 +1,619 @@
+/* Copyright (C) 1997-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <assert.h>
+#include <atomic.h>
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <nss.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <rpcsvc/nis.h>
+#include <libc-lock.h>
+
+#include "nss-nisplus.h"
+
+__libc_lock_define_initialized (static, lock)
+
+static nis_result *result;
+static nis_name tablename_val;
+static u_long tablename_len;
+
+#define NISENTRYVAL(idx, col, res) \
+	(NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val)
+
+#define NISENTRYLEN(idx, col, res) \
+	(NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_len)
+
+/* Get implementation for some internal functions. */
+#include <resolv/resolv-internal.h>
+#include <resolv/mapv4v6addr.h>
+
+
+static int
+_nss_nisplus_parse_hostent (nis_result *result, int af, struct hostent *host,
+			    char *buffer, size_t buflen, int *errnop,
+			    int flags)
+{
+  unsigned int i;
+  char *first_unused = buffer;
+  size_t room_left = buflen;
+
+  if (result == NULL)
+    return 0;
+
+  if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS)
+      || __type_of (NIS_RES_OBJECT (result)) != NIS_ENTRY_OBJ
+      || strcmp (NIS_RES_OBJECT (result)[0].EN_data.en_type, "hosts_tbl") != 0
+      || NIS_RES_OBJECT (result)[0].EN_data.en_cols.en_cols_len < 4)
+    return 0;
+
+  char *data = first_unused;
+
+  if (room_left < (af != AF_INET || (flags & AI_V4MAPPED) != 0
+		   ? IN6ADDRSZ : INADDRSZ))
+    {
+    no_more_room:
+      *errnop = ERANGE;
+      return -1;
+    }
+
+  /* Parse address.  */
+  if (af != AF_INET6
+      && inet_pton (AF_INET, NISENTRYVAL (0, 2, result), data) > 0)
+    {
+      assert ((flags & AI_V4MAPPED) == 0 || af != AF_UNSPEC);
+      if (flags & AI_V4MAPPED)
+	{
+	  map_v4v6_address (data, data);
+	  host->h_addrtype = AF_INET6;
+	  host->h_length = IN6ADDRSZ;
+	}
+      else
+	{
+	  host->h_addrtype = AF_INET;
+	  host->h_length = INADDRSZ;
+	}
+    }
+  else if (af != AF_INET
+	   && inet_pton (AF_INET6, NISENTRYVAL (0, 2, result), data) > 0)
+    {
+      host->h_addrtype = AF_INET6;
+      host->h_length = IN6ADDRSZ;
+    }
+  else
+    /* Illegal address: ignore line.  */
+    return 0;
+
+  first_unused += host->h_length;
+  room_left -= host->h_length;
+
+  if (NISENTRYLEN (0, 0, result) + 1 > room_left)
+    goto no_more_room;
+
+  host->h_name = first_unused;
+  first_unused = __stpncpy (first_unused, NISENTRYVAL (0, 0, result),
+			    NISENTRYLEN (0, 0, result));
+  *first_unused++ = '\0';
+
+  room_left -= NISENTRYLEN (0, 0, result) + 1;
+  char *line = first_unused;
+
+  /* When this is a call to gethostbyname4_r we do not need the aliases.  */
+  if (af != AF_UNSPEC)
+    {
+      /* XXX Rewrite at some point to allocate the array first and then
+	 copy the strings.  It is wasteful to first concatenate the strings
+	 to just split them again later.  */
+      for (i = 0; i < NIS_RES_NUMOBJ (result); ++i)
+	{
+	  if (strcmp (NISENTRYVAL (i, 1, result), host->h_name) != 0)
+	    {
+	      if (NISENTRYLEN (i, 1, result) + 2 > room_left)
+		goto no_more_room;
+
+	      *first_unused++ = ' ';
+	      first_unused = __stpncpy (first_unused,
+					NISENTRYVAL (i, 1, result),
+					NISENTRYLEN (i, 1, result));
+	      *first_unused = '\0';
+	      room_left -= NISENTRYLEN (i, 1, result) + 1;
+	    }
+	}
+      *first_unused++ = '\0';
+    }
+
+  /* Adjust the pointer so it is aligned for
+     storing pointers.  */
+  size_t adjust = ((__alignof__ (char *)
+		    - (first_unused - (char *) 0) % __alignof__ (char *))
+		   % __alignof__ (char *));
+  if (room_left < adjust + 3 * sizeof (char *))
+    goto no_more_room;
+  first_unused += adjust;
+  room_left -= adjust;
+  host->h_addr_list = (char **) first_unused;
+
+  room_left -= 3 * sizeof (char *);
+  host->h_addr_list[0] = data;
+  host->h_addr_list[1] = NULL;
+  host->h_aliases = &host->h_addr_list[2];
+
+  /* When this is a call to gethostbyname4_r we do not need the aliases.  */
+  if (af != AF_UNSPEC)
+    {
+      i = 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 *);
+	  host->h_aliases[i++] = line;
+
+	  while (*line != '\0' && *line != ' ')
+	    ++line;
+
+	  if (*line == ' ')
+	    *line++ = '\0';
+	}
+
+      host->h_aliases[i] = NULL;
+    }
+
+  return 1;
+}
+
+
+static enum nss_status
+_nss_create_tablename (int *errnop)
+{
+  if (tablename_val == NULL)
+    {
+      const char *local_dir = nis_local_directory ();
+      size_t local_dir_len = strlen (local_dir);
+      static const char prefix[] = "hosts.org_dir.";
+
+      char *p = malloc (sizeof (prefix) + local_dir_len);
+      if (p == NULL)
+	{
+	  *errnop = errno;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+
+      memcpy (__stpcpy (p, prefix), local_dir, local_dir_len + 1);
+
+      tablename_len = sizeof (prefix) - 1 + local_dir_len;
+
+      atomic_write_barrier ();
+
+      tablename_val = p;
+    }
+
+  return NSS_STATUS_SUCCESS;
+}
+
+
+enum nss_status
+_nss_nisplus_sethostent (int stayopen)
+{
+  enum nss_status status = NSS_STATUS_SUCCESS;
+  int err;
+
+  __libc_lock_lock (lock);
+
+  if (result != NULL)
+    {
+      nis_freeresult (result);
+      result = NULL;
+    }
+
+  if (tablename_val == NULL)
+    status = _nss_create_tablename (&err);
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+
+enum nss_status
+_nss_nisplus_endhostent (void)
+{
+  __libc_lock_lock (lock);
+
+  if (result != NULL)
+    {
+      nis_freeresult (result);
+      result = 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 *errnop, int *herrnop)
+{
+  int parse_res;
+
+  /* Get the next entry until we found a correct one. */
+  do
+    {
+      nis_result *saved_res;
+
+      if (result == NULL)
+	{
+	  saved_res = NULL;
+	  if (tablename_val == NULL)
+	    {
+	      enum nss_status status = _nss_create_tablename (errnop);
+
+	      if (status != NSS_STATUS_SUCCESS)
+		return status;
+	    }
+
+	  result = nis_first_entry (tablename_val);
+	  if (result == NULL)
+	    {
+	      *errnop = errno;
+	      return NSS_STATUS_TRYAGAIN;
+	    }
+	  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	    {
+	      enum nss_status retval = niserr2nss (result->status);
+	      if (retval == NSS_STATUS_TRYAGAIN)
+		{
+		  *herrnop = NETDB_INTERNAL;
+		  *errnop = errno;
+		}
+	      return retval;
+	    }
+
+	}
+      else
+	{
+	  saved_res = result;
+	  result = nis_next_entry (tablename_val, &result->cookie);
+	  if (result == NULL)
+	    {
+	      *errnop = errno;
+	      return NSS_STATUS_TRYAGAIN;
+	    }
+	  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	    {
+	      enum nss_status retval= niserr2nss (result->status);
+
+	      nis_freeresult (result);
+	      result = saved_res;
+	      if (retval == NSS_STATUS_TRYAGAIN)
+		{
+		  *herrnop = NETDB_INTERNAL;
+		  *errnop = errno;
+		}
+	      return retval;
+	    }
+	}
+
+      if (res_use_inet6 ())
+	parse_res = _nss_nisplus_parse_hostent (result, AF_INET6, host, buffer,
+						buflen, errnop, AI_V4MAPPED);
+      else
+	parse_res = _nss_nisplus_parse_hostent (result, AF_INET, host, buffer,
+						buflen, errnop, 0);
+
+      if (parse_res == -1)
+	{
+	  nis_freeresult (result);
+	  result = saved_res;
+	  *herrnop = NETDB_INTERNAL;
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+      if (saved_res != NULL)
+	nis_freeresult (saved_res);
+
+    } while (!parse_res);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+
+enum nss_status
+_nss_nisplus_gethostent_r (struct hostent *result, char *buffer,
+			   size_t buflen, int *errnop, int *herrnop)
+{
+  int status;
+
+  __libc_lock_lock (lock);
+
+  status = internal_nisplus_gethostent_r (result, buffer, buflen, errnop,
+					  herrnop);
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+
+static enum nss_status
+get_tablename (int *herrnop)
+{
+  __libc_lock_lock (lock);
+
+  enum nss_status status = _nss_create_tablename (herrnop);
+
+  __libc_lock_unlock (lock);
+
+  if (status != NSS_STATUS_SUCCESS)
+    *herrnop = NETDB_INTERNAL;
+
+  return status;
+}
+
+
+static enum nss_status
+internal_gethostbyname2_r (const char *name, int af, struct hostent *host,
+			   char *buffer, size_t buflen, int *errnop,
+			   int *herrnop, int flags)
+{
+  if (tablename_val == NULL)
+    {
+      enum nss_status status = get_tablename (herrnop);
+      if (status != NSS_STATUS_SUCCESS)
+	return status;
+    }
+
+  if (name == NULL)
+    {
+      *errnop = EINVAL;
+      *herrnop = NETDB_INTERNAL;
+      return NSS_STATUS_NOTFOUND;
+    }
+
+  char buf[strlen (name) + 10 + tablename_len];
+  int olderr = errno;
+
+  /* Search at first in the alias list, and use the correct name
+     for the next search.  */
+  snprintf (buf, sizeof (buf), "[name=%s],%s", name, tablename_val);
+  nis_result *result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
+
+  if (result != NULL)
+    {
+      /* If we did not find it, try it as original name. But if the
+	 database is correct, we should find it in the first case, too.  */
+      char *bufptr = buf;
+      size_t buflen = sizeof (buf);
+
+      if ((result->status == NIS_SUCCESS || result->status == NIS_S_SUCCESS)
+	  && __type_of (result->objects.objects_val) == NIS_ENTRY_OBJ
+	  && strcmp (result->objects.objects_val->EN_data.en_type,
+		     "hosts_tbl") == 0
+	  && result->objects.objects_val->EN_data.en_cols.en_cols_len >= 3)
+	{
+	  /* We need to allocate a new buffer since there is no
+	     guarantee the returned alias name has a length limit.  */
+	  name = NISENTRYVAL(0, 0, result);
+	  size_t buflen = strlen (name) + 10 + tablename_len;
+	  bufptr = alloca (buflen);
+	}
+
+      snprintf (bufptr, buflen, "[cname=%s],%s", name, tablename_val);
+
+      nis_freeresult (result);
+      result = nis_list (bufptr, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
+    }
+
+  if (result == NULL)
+    {
+      *errnop = ENOMEM;
+      *herrnop = NETDB_INTERNAL;
+      return NSS_STATUS_TRYAGAIN;
+    }
+
+  int retval = niserr2nss (result->status);
+  if (__glibc_unlikely (retval != NSS_STATUS_SUCCESS))
+    {
+      if (retval == NSS_STATUS_TRYAGAIN)
+	{
+	  *errnop = errno;
+	  *herrnop = TRY_AGAIN;
+	}
+      else
+	{
+	  __set_errno (olderr);
+	  *herrnop = NETDB_INTERNAL;
+	}
+      nis_freeresult (result);
+      return retval;
+    }
+
+  int parse_res = _nss_nisplus_parse_hostent (result, af, host, buffer,
+					      buflen, errnop, flags);
+
+  nis_freeresult (result);
+
+  if (parse_res > 0)
+    return NSS_STATUS_SUCCESS;
+
+  *herrnop = NETDB_INTERNAL;
+  if (parse_res == -1)
+    {
+      *errnop = ERANGE;
+      return NSS_STATUS_TRYAGAIN;
+    }
+
+  __set_errno (olderr);
+  return NSS_STATUS_NOTFOUND;
+}
+
+
+enum nss_status
+_nss_nisplus_gethostbyname2_r (const char *name, int af, struct hostent *host,
+			       char *buffer, size_t buflen, int *errnop,
+			       int *herrnop)
+{
+  if (af != AF_INET && af != AF_INET6)
+    {
+      *herrnop = HOST_NOT_FOUND;
+      return NSS_STATUS_NOTFOUND;
+    }
+
+  return internal_gethostbyname2_r (name, af, host, buffer, buflen, errnop,
+				    herrnop,
+				    (res_use_inet6 () ? AI_V4MAPPED : 0));
+}
+
+
+enum nss_status
+_nss_nisplus_gethostbyname_r (const char *name, struct hostent *host,
+			      char *buffer, size_t buflen, int *errnop,
+			      int *h_errnop)
+{
+  if (res_use_inet6 ())
+    {
+      enum nss_status status;
+
+      status = internal_gethostbyname2_r (name, AF_INET6, host, buffer,
+					  buflen, errnop, h_errnop,
+					  AI_V4MAPPED);
+      if (status == NSS_STATUS_SUCCESS)
+	return status;
+    }
+
+  return internal_gethostbyname2_r (name, AF_INET, host, buffer,
+				   buflen, errnop, h_errnop, 0);
+}
+
+
+enum nss_status
+_nss_nisplus_gethostbyaddr_r (const void *addr, socklen_t addrlen, int af,
+			      struct hostent *host, char *buffer,
+			      size_t buflen, int *errnop, int *herrnop)
+{
+  if (tablename_val == NULL)
+    {
+      enum nss_status status = get_tablename (herrnop);
+      if (status != NSS_STATUS_SUCCESS)
+	return status;
+    }
+
+  if (addr == NULL)
+    return NSS_STATUS_NOTFOUND;
+
+  char buf[24 + tablename_len];
+  int retval, parse_res;
+  int olderr = errno;
+
+  snprintf (buf, sizeof (buf), "[addr=%s],%s",
+	   inet_ntoa (*(const struct in_addr *) addr), tablename_val);
+  nis_result *result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
+
+  if (result == NULL)
+    {
+      __set_errno (ENOMEM);
+      return NSS_STATUS_TRYAGAIN;
+    }
+
+  retval = niserr2nss (result->status);
+  if (__glibc_unlikely (retval != NSS_STATUS_SUCCESS))
+    {
+      if (retval == NSS_STATUS_TRYAGAIN)
+	{
+	  *errnop = errno;
+	  *herrnop = NETDB_INTERNAL;
+	}
+      else
+	__set_errno (olderr);
+      nis_freeresult (result);
+      return retval;
+    }
+
+  parse_res = _nss_nisplus_parse_hostent (result, af, host,
+					  buffer, buflen, errnop,
+					  (res_use_inet6 ()
+					   ? AI_V4MAPPED : 0));
+  nis_freeresult (result);
+
+  if (parse_res > 0)
+    return NSS_STATUS_SUCCESS;
+
+  *herrnop = NETDB_INTERNAL;
+  if (parse_res == -1)
+    {
+      *errnop = ERANGE;
+      return NSS_STATUS_TRYAGAIN;
+    }
+
+  __set_errno (olderr);
+  return NSS_STATUS_NOTFOUND;
+}
+
+
+enum nss_status
+_nss_nisplus_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
+			       char *buffer, size_t buflen, int *errnop,
+			       int *herrnop, int32_t *ttlp)
+{
+  struct hostent host;
+
+  enum nss_status status = internal_gethostbyname2_r (name, AF_UNSPEC, &host,
+						      buffer, buflen,
+						      errnop, herrnop, 0);
+  if (__glibc_likely (status == NSS_STATUS_SUCCESS))
+    {
+      if (*pat == NULL)
+	{
+	  uintptr_t pad = (-(uintptr_t) buffer
+			   % __alignof__ (struct gaih_addrtuple));
+	  buffer += pad;
+	  buflen = buflen > pad ? buflen - pad : 0;
+
+	  if (__glibc_unlikely (buflen < sizeof (struct gaih_addrtuple)))
+	    {
+	      free (result);
+	      *errnop = ERANGE;
+	      *herrnop = NETDB_INTERNAL;
+	      return NSS_STATUS_TRYAGAIN;
+	    }
+	}
+
+      (*pat)->next = NULL;
+      (*pat)->name = host.h_name;
+      (*pat)->family = host.h_addrtype;
+
+      memcpy ((*pat)->addr, host.h_addr_list[0], host.h_length);
+      (*pat)->scopeid = 0;
+      assert (host.h_addr_list[1] == NULL);
+    }
+
+  return status;
+}
diff --git a/REORG.TODO/nis/nss_nisplus/nisplus-initgroups.c b/REORG.TODO/nis/nss_nisplus/nisplus-initgroups.c
new file mode 100644
index 0000000000..95ee623b1c
--- /dev/null
+++ b/REORG.TODO/nis/nss_nisplus/nisplus-initgroups.c
@@ -0,0 +1,148 @@
+/* Copyright (C) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <atomic.h>
+#include <nss.h>
+#include <grp.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <libc-lock.h>
+#include <rpcsvc/nis.h>
+
+#include "nss-nisplus.h"
+#include "nisplus-parser.h"
+#include <libnsl.h>
+#include <nis_intern.h>
+#include <nis_xdr.h>
+
+#define NISOBJVAL(col, obj) \
+  ((obj)->EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val)
+
+#define NISOBJLEN(col, obj) \
+  ((obj)->EN_data.en_cols.en_cols_val[col].ec_value.ec_value_len)
+
+extern nis_name grp_tablename_val attribute_hidden;
+extern size_t grp_tablename_len attribute_hidden;
+extern enum nss_status _nss_grp_create_tablename (int *errnop);
+
+
+enum nss_status
+_nss_nisplus_initgroups_dyn (const char *user, gid_t group, long int *start,
+			     long int *size, gid_t **groupsp, long int limit,
+			     int *errnop)
+{
+  if (grp_tablename_val == NULL)
+    {
+      enum nss_status status = _nss_grp_create_tablename (errnop);
+
+      if (status != NSS_STATUS_SUCCESS)
+	return status;
+    }
+
+  nis_result *result;
+  char buf[strlen (user) + 12 + grp_tablename_len];
+
+  snprintf (buf, sizeof (buf), "[members=%s],%s", user, grp_tablename_val);
+
+  result = nis_list (buf, FOLLOW_LINKS | FOLLOW_PATH | ALL_RESULTS, NULL, NULL);
+
+  if (result == NULL)
+    {
+      *errnop = ENOMEM;
+      return NSS_STATUS_TRYAGAIN;
+    }
+
+  if (__glibc_unlikely (niserr2nss (result->status) != NSS_STATUS_SUCCESS))
+    {
+      enum nss_status status = niserr2nss (result->status);
+
+      nis_freeresult (result);
+      return status;
+    }
+
+  if (NIS_RES_NUMOBJ (result) == 0)
+    {
+    errout:
+      nis_freeresult (result);
+      return NSS_STATUS_NOTFOUND;
+    }
+
+  gid_t *groups = *groupsp;
+  nis_object *obj = NIS_RES_OBJECT (result);
+  for (unsigned int cnt = 0; cnt < NIS_RES_NUMOBJ (result); ++cnt, ++obj)
+    {
+      if (__type_of (obj) != NIS_ENTRY_OBJ
+	  || strcmp (obj->EN_data.en_type, "group_tbl") != 0
+	  || obj->EN_data.en_cols.en_cols_len < 4)
+	continue;
+
+      char *numstr = NISOBJVAL (2, obj);
+      size_t len = NISOBJLEN (2, obj);
+      if (len == 0 || numstr[0] == '\0')
+	continue;
+
+      gid_t gid;
+      char *endp;
+      if (__glibc_unlikely (numstr[len - 1] != '\0'))
+	{
+	  char numstrbuf[len + 1];
+	  memcpy (numstrbuf, numstr, len);
+	  numstrbuf[len] = '\0';
+	  gid = strtoul (numstrbuf, &endp, 10);
+	  if (*endp)
+	    continue;
+	}
+      else
+	{
+	  gid = strtoul (numstr, &endp, 10);
+	  if (*endp)
+	    continue;
+	}
+
+      if (gid == group)
+	continue;
+
+      /* Insert this group.  */
+      if (*start == *size)
+	{
+	  /* Need a bigger buffer.  */
+	  long int newsize;
+
+	  if (limit > 0 && *size == limit)
+	    /* We reached the maximum.  */
+	    break;
+
+	  if (limit <= 0)
+	    newsize = 2 * *size;
+	  else
+	    newsize = MIN (limit, 2 * *size);
+
+	  gid_t *newgroups = realloc (groups, newsize * sizeof (*groups));
+	  if (newgroups == NULL)
+	    goto errout;
+	  *groupsp = groups = newgroups;
+	  *size = newsize;
+	}
+
+      groups[*start] = gid;
+      *start += 1;
+    }
+
+  nis_freeresult (result);
+  return NSS_STATUS_SUCCESS;
+}
diff --git a/REORG.TODO/nis/nss_nisplus/nisplus-netgrp.c b/REORG.TODO/nis/nss_nisplus/nisplus-netgrp.c
new file mode 100644
index 0000000000..f10a85f0e3
--- /dev/null
+++ b/REORG.TODO/nis/nss_nisplus/nisplus-netgrp.c
@@ -0,0 +1,191 @@
+/* Copyright (C) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <nss.h>
+#include <errno.h>
+#include <ctype.h>
+#include <netdb.h>
+#include <string.h>
+#include <netgroup.h>
+#include <rpcsvc/nis.h>
+
+#include "nss-nisplus.h"
+
+#define NISENTRYVAL(idx, col, res) \
+        (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val)
+
+#define NISENTRYLEN(idx, col, res) \
+        (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_len)
+
+enum nss_status
+_nss_nisplus_getnetgrent_r (struct __netgrent *result, char *buffer,
+			    size_t buflen, int *errnop)
+{
+  enum nss_status status;
+
+  /* Some sanity checks.  */
+  if (result->data == NULL || result->data_size == 0)
+    return NSS_STATUS_NOTFOUND;
+
+  if (result->position == result->data_size)
+    return result->first ? NSS_STATUS_NOTFOUND : NSS_STATUS_RETURN;
+
+  unsigned int entrylen
+    = NISENTRYLEN (result->position, 1, (nis_result *) result->data);
+  if (entrylen > 0)
+    {
+      /* We have a list of other netgroups.  */
+
+      result->type = group_val;
+      if (entrylen >= buflen)
+	{
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+      strncpy (buffer, NISENTRYVAL (result->position, 1,
+				    (nis_result *) result->data),
+	       entrylen);
+      buffer[entrylen] = '\0';
+      result->val.group = buffer;
+      ++result->position;
+      result->first = 0;
+
+      return NSS_STATUS_SUCCESS;
+    }
+
+  /* Before we can copy the entry to the private buffer we have to make
+     sure it is big enough.  */
+  unsigned int hostlen
+    = NISENTRYLEN (result->position, 2, (nis_result *) result->data);
+  unsigned int userlen
+    = NISENTRYLEN (result->position, 3, (nis_result *) result->data);
+  unsigned int domainlen
+    = NISENTRYLEN (result->position, 4, (nis_result *) result->data);
+  if (hostlen + userlen + domainlen + 6 > buflen)
+    {
+      *errnop = ERANGE;
+      status = NSS_STATUS_TRYAGAIN;
+    }
+  else
+    {
+      char *cp = buffer;
+
+      result->type = triple_val;
+
+      if (hostlen == 0 ||
+	  NISENTRYVAL (result->position, 2,
+		       (nis_result *) result->data)[0] == '\0')
+	result->val.triple.host = NULL;
+      else
+	{
+	  result->val.triple.host = cp;
+	  cp = __stpncpy (cp, NISENTRYVAL (result->position, 2,
+					   (nis_result *) result->data),
+			  hostlen);
+	  *cp++ = '\0';
+	}
+
+      if (userlen == 0 ||
+	  NISENTRYVAL (result->position, 3,
+		       (nis_result *) result->data)[0] == '\0')
+	result->val.triple.user = NULL;
+      else
+	{
+	  result->val.triple.user = cp;
+	  cp = __stpncpy (cp, NISENTRYVAL (result->position, 3,
+					   (nis_result *) result->data),
+			  userlen);
+	  *cp++ = '\0';
+	}
+
+      if (domainlen == 0 ||
+	  NISENTRYVAL (result->position, 4,
+		       (nis_result *) result->data)[0] == '\0')
+	result->val.triple.domain = NULL;
+      else
+	{
+	  result->val.triple.domain = cp;
+	  cp = __stpncpy (cp, NISENTRYVAL (result->position, 4,
+					   (nis_result *) result->data),
+			  domainlen);
+	  *cp = '\0';
+	}
+
+      status = NSS_STATUS_SUCCESS;
+
+      /* Remember where we stopped reading.  */
+      ++result->position;
+
+      result->first = 0;
+    }
+
+  return status;
+}
+
+static void
+internal_endnetgrent (struct __netgrent *netgrp)
+{
+  nis_freeresult ((nis_result *) netgrp->data);
+  netgrp->data = NULL;
+  netgrp->data_size = 0;
+  netgrp->position = 0;
+}
+
+enum nss_status
+_nss_nisplus_setnetgrent (const char *group, struct __netgrent *netgrp)
+{
+  char buf[strlen (group) + 25];
+
+  if (group == NULL || group[0] == '\0')
+    return NSS_STATUS_UNAVAIL;
+
+  enum nss_status status = NSS_STATUS_SUCCESS;
+
+  snprintf (buf, sizeof (buf), "[name=%s],netgroup.org_dir", group);
+
+  netgrp->data = (char *) nis_list (buf, EXPAND_NAME, NULL, NULL);
+
+  if (netgrp->data == NULL)
+    {
+      __set_errno (ENOMEM);
+      status = NSS_STATUS_TRYAGAIN;
+    }
+  else if (niserr2nss (((nis_result *) netgrp->data)->status)
+	   != NSS_STATUS_SUCCESS)
+    {
+      status = niserr2nss (((nis_result *) netgrp->data)->status);
+
+      internal_endnetgrent (netgrp);
+    }
+  else
+    {
+      netgrp->data_size = ((nis_result *) netgrp->data)->objects.objects_len;
+      netgrp->position = 0;
+      netgrp->first = 1;
+    }
+
+  return status;
+}
+
+enum nss_status
+_nss_nisplus_endnetgrent (struct __netgrent *netgrp)
+{
+  internal_endnetgrent (netgrp);
+
+  return NSS_STATUS_SUCCESS;
+}
diff --git a/REORG.TODO/nis/nss_nisplus/nisplus-network.c b/REORG.TODO/nis/nss_nisplus/nisplus-network.c
new file mode 100644
index 0000000000..ad266b9f6d
--- /dev/null
+++ b/REORG.TODO/nis/nss_nisplus/nisplus-network.c
@@ -0,0 +1,494 @@
+/* Copyright (C) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <atomic.h>
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <nss.h>
+#include <stdint.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include <rpcsvc/nis.h>
+#include <libc-lock.h>
+
+#include "nss-nisplus.h"
+
+__libc_lock_define_initialized (static, lock)
+
+static nis_result *result;
+static nis_name tablename_val;
+static u_long tablename_len;
+
+#define NISENTRYVAL(idx, col, res) \
+        (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val)
+
+#define NISENTRYLEN(idx, col, res) \
+        (NIS_RES_OBJECT (res)[idx].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, int *errnop)
+{
+  char *first_unused = buffer;
+  size_t room_left = buflen;
+
+  if (result == NULL)
+    return 0;
+
+  if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS)
+      || __type_of (NIS_RES_OBJECT (result)) != NIS_ENTRY_OBJ
+      || strcmp (NIS_RES_OBJECT (result)[0].EN_data.en_type,
+		 "networks_tbl") != 0
+      || NIS_RES_OBJECT (result)[0].EN_data.en_cols.en_cols_len < 3)
+    return 0;
+
+  if (NISENTRYLEN (0, 0, result) >= room_left)
+    {
+      /* The line is too long for our buffer.  */
+    no_more_room:
+      *errnop = ERANGE;
+      return -1;
+    }
+
+  strncpy (first_unused, NISENTRYVAL (0, 0, result),
+           NISENTRYLEN (0, 0, result));
+  first_unused[NISENTRYLEN (0, 0, result)] = '\0';
+  network->n_name = first_unused;
+  size_t len = strlen (first_unused) + 1;
+  room_left -= len;
+  first_unused += len;
+
+  network->n_addrtype = 0;
+  network->n_net = inet_network (NISENTRYVAL (0, 2, result));
+
+  /* XXX Rewrite at some point to allocate the array first and then
+     copy the strings.  It wasteful to first concatenate the strings
+     to just split them again later.  */
+  char *line = first_unused;
+  for (unsigned int i = 0; i < NIS_RES_NUMOBJ (result); ++i)
+    {
+      if (strcmp (NISENTRYVAL (i, 1, result), network->n_name) != 0)
+        {
+          if (NISENTRYLEN (i, 1, result) + 2 > room_left)
+	    goto no_more_room;
+
+	  *first_unused++ = ' ';
+          first_unused = __stpncpy (first_unused, NISENTRYVAL (i, 1, result),
+				    NISENTRYLEN (i, 1, result));
+          room_left -= (NISENTRYLEN (i, 1, result) + 1);
+        }
+    }
+  *first_unused++ = '\0';
+
+  /* Adjust the pointer so it is aligned for
+     storing pointers.  */
+  size_t adjust = ((__alignof__ (char *)
+		    - (first_unused - (char *) 0) % __alignof__ (char *))
+		   % __alignof__ (char *));
+  if (room_left < adjust + sizeof (char *))
+    goto no_more_room;
+  first_unused += adjust;
+  room_left -= adjust;
+  network->n_aliases = (char **) first_unused;
+
+  /* For the terminating NULL pointer.  */
+  room_left -= sizeof (char *);
+
+  unsigned int i = 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 *);
+      network->n_aliases[i++] = line;
+
+      while (*line != '\0' && *line != ' ')
+        ++line;
+
+      if (*line == ' ')
+	*line++ = '\0';
+    }
+  network->n_aliases[i] = NULL;
+
+  return 1;
+}
+
+
+static enum nss_status
+_nss_create_tablename (int *errnop)
+{
+  if (tablename_val == NULL)
+    {
+      const char *local_dir = nis_local_directory ();
+      size_t local_dir_len = strlen (local_dir);
+      static const char prefix[] = "networks.org_dir.";
+
+      char *p = malloc (sizeof (prefix) + local_dir_len);
+      if (p == NULL)
+	{
+	  *errnop = errno;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+
+      memcpy (__stpcpy (p, prefix), local_dir, local_dir_len + 1);
+
+      tablename_len = sizeof (prefix) - 1 + local_dir_len;
+
+      atomic_write_barrier ();
+
+      tablename_val = p;
+    }
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_setnetent (int stayopen)
+{
+  enum nss_status status = NSS_STATUS_SUCCESS;
+
+  __libc_lock_lock (lock);
+
+  if (result != NULL)
+    {
+      nis_freeresult (result);
+      result = NULL;
+    }
+
+  if (tablename_val == NULL)
+    {
+      int err;
+      status = _nss_create_tablename (&err);
+    }
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+enum nss_status
+_nss_nisplus_endnetent (void)
+{
+  __libc_lock_lock (lock);
+
+  if (result != NULL)
+    {
+      nis_freeresult (result);
+      result = 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 *errnop, int *herrnop)
+{
+  int parse_res;
+
+  /* Get the next entry until we found a correct one. */
+  do
+    {
+      nis_result *saved_res;
+
+      if (result == NULL)
+	{
+	  saved_res = NULL;
+
+	  if (tablename_val == NULL)
+	    {
+	      enum nss_status status = _nss_create_tablename (errnop);
+
+	      if (status != NSS_STATUS_SUCCESS)
+		return status;
+	    }
+
+	  result = nis_first_entry (tablename_val);
+	  if (result == NULL)
+	    {
+	      *errnop = errno;
+	      return NSS_STATUS_TRYAGAIN;
+	    }
+	  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	    {
+	      int retval = niserr2nss (result->status);
+	      nis_freeresult (result);
+	      result = NULL;
+	      if (retval == NSS_STATUS_TRYAGAIN)
+		{
+		  *herrnop = NETDB_INTERNAL;
+		  *errnop = errno;
+		  return retval;
+		}
+	      else
+		return retval;
+	    }
+	}
+      else
+	{
+	  saved_res = result;
+	  result = nis_next_entry (tablename_val, &result->cookie);
+	  if (result == NULL)
+	    {
+	      *errnop = errno;
+	      return NSS_STATUS_TRYAGAIN;
+	    }
+	  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	    {
+	      int retval = niserr2nss (result->status);
+	      nis_freeresult (result);
+	      result = saved_res;
+	      if (retval == NSS_STATUS_TRYAGAIN)
+		{
+		  *herrnop = NETDB_INTERNAL;
+		  *errnop = errno;
+		}
+	      return retval;
+	    }
+	}
+
+      parse_res = _nss_nisplus_parse_netent (result, network, buffer,
+					     buflen, errnop);
+      if (parse_res == -1)
+        {
+          *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 *errnop, int *herrnop)
+{
+  int status;
+
+  __libc_lock_lock (lock);
+
+  status = internal_nisplus_getnetent_r (result, buffer, buflen, errnop,
+					 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 *errnop,
+			     int *herrnop)
+{
+  int parse_res, retval;
+
+  if (tablename_val == NULL)
+    {
+      __libc_lock_lock (lock);
+
+      enum nss_status status = _nss_create_tablename (errnop);
+
+      __libc_lock_unlock (lock);
+
+      if (status != NSS_STATUS_SUCCESS)
+	return status;
+    }
+
+  if (name == NULL)
+    {
+      *errnop = EINVAL;
+      *herrnop = NETDB_INTERNAL;
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  nis_result *result;
+  char buf[strlen (name) + 10 + tablename_len];
+  int olderr = errno;
+
+  /* Search at first in the alias list, and use the correct name
+     for the next search */
+  snprintf (buf, sizeof (buf), "[name=%s],%s", name, tablename_val);
+  result = nis_list (buf, FOLLOW_LINKS | FOLLOW_PATH | USE_DGRAM, NULL, NULL);
+
+  if (result != NULL)
+    {
+      char *bufptr = buf;
+
+      /* 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)
+	  || __type_of (result->objects.objects_val) != NIS_ENTRY_OBJ
+	  || strcmp (result->objects.objects_val[0].EN_data.en_type,
+		     "networks_tbl") != 0
+	  || (result->objects.objects_val[0].EN_data.en_cols.en_cols_len
+	      < 3))
+	snprintf (buf, sizeof (buf), "[cname=%s],%s", name, tablename_val);
+      else
+	{
+	  /* We need to allocate a new buffer since there is no
+	     guarantee the returned name has a length limit.  */
+	  const char *entryval = NISENTRYVAL (0, 0, result);
+	  size_t buflen = strlen (entryval) + 10 + tablename_len;
+	  bufptr = alloca (buflen);
+	  snprintf (bufptr, buflen, "[cname=%s],%s",
+		    entryval, tablename_val);
+	}
+
+      nis_freeresult (result);
+      result = nis_list (bufptr, FOLLOW_LINKS | FOLLOW_PATH | USE_DGRAM,
+			 NULL, NULL);
+    }
+
+  if (result == NULL)
+    {
+      __set_errno (ENOMEM);
+      return NSS_STATUS_TRYAGAIN;
+    }
+
+  retval = niserr2nss (result->status);
+  if (__glibc_unlikely (retval != NSS_STATUS_SUCCESS))
+    {
+      if (retval == NSS_STATUS_TRYAGAIN)
+	{
+	  *errnop = errno;
+	  *herrnop = NETDB_INTERNAL;
+	}
+      else
+	__set_errno (olderr);
+      nis_freeresult (result);
+      return retval;
+    }
+
+  parse_res = _nss_nisplus_parse_netent (result, network, buffer, buflen,
+					 errnop);
+
+  nis_freeresult (result);
+
+  if (parse_res > 0)
+    return NSS_STATUS_SUCCESS;
+
+  *herrnop = NETDB_INTERNAL;
+  if (parse_res == -1)
+    {
+      *errnop = ERANGE;
+      return NSS_STATUS_TRYAGAIN;
+    }
+
+  __set_errno (olderr);
+  return NSS_STATUS_NOTFOUND;
+}
+
+/* XXX type is ignored, SUN's NIS+ table doesn't support it */
+enum nss_status
+_nss_nisplus_getnetbyaddr_r (uint32_t addr, const int type,
+			     struct netent *network, char *buffer,
+			     size_t buflen, int *errnop, int *herrnop)
+{
+  if (tablename_val == NULL)
+    {
+      __libc_lock_lock (lock);
+
+      enum nss_status status = _nss_create_tablename (errnop);
+
+      __libc_lock_unlock (lock);
+
+      if (status != NSS_STATUS_SUCCESS)
+	return status;
+    }
+
+  {
+    char buf[27 + tablename_len];
+    char buf2[18];
+    int olderr = errno;
+
+    struct in_addr in = { .s_addr = htonl (addr) };
+    strcpy (buf2, inet_ntoa (in));
+    size_t b2len = strlen (buf2);
+
+    while (1)
+      {
+	snprintf (buf, sizeof (buf), "[addr=%s],%s", buf2, tablename_val);
+	nis_result *result = nis_list (buf, EXPAND_NAME | USE_DGRAM,
+				       NULL, NULL);
+
+	if (result == NULL)
+	  {
+	    __set_errno (ENOMEM);
+	    return NSS_STATUS_TRYAGAIN;
+	  }
+	enum nss_status retval = niserr2nss (result->status);
+	if (__glibc_unlikely (retval != NSS_STATUS_SUCCESS))
+	  {
+	    if (b2len > 2 && buf2[b2len - 2] == '.' && buf2[b2len - 1] == '0')
+	      {
+		/* Try again, but with trailing dot(s)
+		   removed (one by one) */
+		buf2[b2len - 2] = '\0';
+		b2len -= 2;
+		nis_freeresult (result);
+		continue;
+	      }
+
+	    if (retval == NSS_STATUS_TRYAGAIN)
+	      {
+		*errnop = errno;
+		*herrnop = NETDB_INTERNAL;
+	      }
+	    else
+	      __set_errno (olderr);
+	    nis_freeresult (result);
+	    return retval;
+	  }
+
+	int parse_res = _nss_nisplus_parse_netent (result, network, buffer,
+						   buflen, errnop);
+
+	nis_freeresult (result);
+
+	if (parse_res > 0)
+	  return NSS_STATUS_SUCCESS;
+
+	*herrnop = NETDB_INTERNAL;
+	if (parse_res == -1)
+	  {
+	    *errnop = ERANGE;
+	    return NSS_STATUS_TRYAGAIN;
+	  }
+	else
+	  {
+	    __set_errno (olderr);
+	    return NSS_STATUS_NOTFOUND;
+	  }
+      }
+  }
+}
diff --git a/REORG.TODO/nis/nss_nisplus/nisplus-parser.c b/REORG.TODO/nis/nss_nisplus/nisplus-parser.c
new file mode 100644
index 0000000000..64170ddc1a
--- /dev/null
+++ b/REORG.TODO/nis/nss_nisplus/nisplus-parser.c
@@ -0,0 +1,375 @@
+/* Copyright (C) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <pwd.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <rpcsvc/nis.h>
+
+#include "nisplus-parser.h"
+
+#define NISENTRYVAL(idx, col, res) \
+        (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val)
+
+#define NISENTRYLEN(idx, col, res) \
+        (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_len)
+
+#define NISOBJVAL(col, obj) \
+  ((obj)->EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val)
+
+#define NISOBJLEN(col, obj) \
+  ((obj)->EN_data.en_cols.en_cols_val[col].ec_value.ec_value_len)
+
+
+int
+_nss_nisplus_parse_pwent (nis_result *result, struct passwd *pw,
+			  char *buffer, size_t buflen, int *errnop)
+{
+  if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS)
+      || NIS_RES_NUMOBJ (result) != 1
+      || __type_of (NIS_RES_OBJECT (result)) != NIS_ENTRY_OBJ
+      || strcmp (NIS_RES_OBJECT (result)->EN_data.en_type, "passwd_tbl") != 0
+      || NIS_RES_OBJECT (result)->EN_data.en_cols.en_cols_len < 7)
+    return 0;
+
+  nis_object *obj = NIS_RES_OBJECT (result);
+  char *first_unused = buffer;
+  size_t room_left = buflen;
+  size_t len;
+
+  if (NISOBJLEN (0, obj) >= room_left)
+    {
+      /* The line is too long for our buffer.  */
+    no_more_room:
+      *errnop = ERANGE;
+      return -1;
+    }
+
+  strncpy (first_unused, NISOBJVAL (0, obj), NISOBJLEN (0, obj));
+  first_unused[NISOBJLEN (0, obj)] = '\0';
+  len = strlen (first_unused);
+  if (len == 0) /* No name ? Should never happen, database is corrupt */
+    return 0;
+  pw->pw_name = first_unused;
+  room_left -= len + 1;
+  first_unused += len + 1;
+
+  if (NISOBJLEN (1, obj) >= room_left)
+    goto no_more_room;
+
+  strncpy (first_unused, NISOBJVAL (1, obj), NISOBJLEN (1, obj));
+  first_unused[NISOBJLEN (1, obj)] = '\0';
+  pw->pw_passwd = first_unused;
+  len = strlen (first_unused);
+  room_left -= len + 1;
+  first_unused += len + 1;
+
+  char *numstr = NISOBJVAL (2, obj);
+  len = NISOBJLEN (2, obj);
+  if (len == 0 && numstr[len - 1] != '\0')
+    {
+      if (len >= room_left)
+	goto no_more_room;
+
+      strncpy (first_unused, numstr, len);
+      first_unused[len] = '\0';
+      numstr = first_unused;
+    }
+  if (numstr[0] == '\0')
+    /* If we don't have a uid, it's an invalid shadow entry.  */
+    return 0;
+  pw->pw_uid = strtoul (numstr, NULL, 10);
+
+  numstr = NISOBJVAL (3, obj);
+  len = NISOBJLEN (3, obj);
+  if (len == 0 && numstr[len - 1] != '\0')
+    {
+      if (len >= room_left)
+	goto no_more_room;
+
+      strncpy (first_unused, numstr, len);
+      first_unused[len] = '\0';
+      numstr = first_unused;
+    }
+  if (numstr[0] == '\0')
+    /* If we don't have a gid, it's an invalid shadow entry.  */
+    return 0;
+  pw->pw_gid = strtoul (numstr, NULL, 10);
+
+  if (NISOBJLEN(4, obj) >= room_left)
+    goto no_more_room;
+
+  strncpy (first_unused, NISOBJVAL (4, obj), NISOBJLEN (4, obj));
+  first_unused[NISOBJLEN (4, obj)] = '\0';
+  pw->pw_gecos = first_unused;
+  len = strlen (first_unused);
+  room_left -= len + 1;
+  first_unused += len + 1;
+
+  if (NISOBJLEN (5, obj) >= room_left)
+    goto no_more_room;
+
+  strncpy (first_unused, NISOBJVAL (5, obj), NISOBJLEN (5, obj));
+  first_unused[NISOBJLEN (5, obj)] = '\0';
+  pw->pw_dir = first_unused;
+  len = strlen (first_unused);
+  room_left -= len + 1;
+  first_unused += len + 1;
+
+  if (NISOBJLEN (6, obj) >= room_left)
+    goto no_more_room;
+
+  strncpy (first_unused, NISOBJVAL (6, obj), NISOBJLEN (6, obj));
+  first_unused[NISOBJLEN (6, obj)] = '\0';
+  pw->pw_shell = first_unused;
+  len = strlen (first_unused);
+  room_left -= len + 1;
+  first_unused += len + 1;
+
+  return 1;
+}
+
+
+int
+_nss_nisplus_parse_grent (nis_result *result, struct group *gr,
+			  char *buffer, size_t buflen, int *errnop)
+{
+  if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS)
+      || __type_of(NIS_RES_OBJECT (result)) != NIS_ENTRY_OBJ
+      || strcmp (NIS_RES_OBJECT (result)[0].EN_data.en_type, "group_tbl") != 0
+      || NIS_RES_OBJECT (result)[0].EN_data.en_cols.en_cols_len < 4)
+    return 0;
+
+  nis_object *obj = NIS_RES_OBJECT (result);
+  char *first_unused = buffer;
+  size_t room_left = buflen;
+  char *line;
+  int count;
+  size_t len;
+
+  if (NISOBJLEN (0, obj) >= room_left)
+    {
+      /* The line is too long for our buffer.  */
+    no_more_room:
+      *errnop = ERANGE;
+      return -1;
+    }
+
+  strncpy (first_unused, NISOBJVAL (0, obj), NISOBJLEN (0, obj));
+  first_unused[NISOBJLEN (0, obj)] = '\0';
+  len = strlen (first_unused);
+  if (len == 0) /* group table is corrupt */
+    return 0;
+  gr->gr_name = first_unused;
+  room_left -= len + 1;
+  first_unused += len + 1;
+
+  if (NISOBJLEN (1, obj) >= room_left)
+    goto no_more_room;
+
+  strncpy (first_unused, NISOBJVAL (1, obj), NISOBJLEN (1, obj));
+  first_unused[NISOBJLEN (1, obj)] = '\0';
+  gr->gr_passwd = first_unused;
+  len = strlen (first_unused);
+  room_left -= len + 1;
+  first_unused += len + 1;
+
+  char *numstr = NISOBJVAL (2, obj);
+  len = NISOBJLEN (2, obj);
+  if (len == 0 || numstr[len - 1] != '\0')
+    {
+      if (len >= room_left)
+	goto no_more_room;
+
+      strncpy (first_unused, numstr, len);
+      first_unused[len] = '\0';
+      numstr = first_unused;
+    }
+  if (numstr[0] == '\0')
+    /* We should always have a gid.  */
+    return 0;
+  gr->gr_gid = strtoul (numstr, NULL, 10);
+
+  if (NISOBJLEN (3, obj) >= room_left)
+    goto no_more_room;
+
+  strncpy (first_unused, NISOBJVAL (3, obj), NISOBJLEN (3, obj));
+  first_unused[NISOBJLEN (3, obj)] = '\0';
+  line = first_unused;
+  len = strlen (line);
+  room_left -= len + 1;
+  first_unused += len + 1;
+  /* Adjust the pointer so it is aligned for
+     storing pointers.  */
+  size_t adjust = ((__alignof__ (char *)
+		    - (first_unused - (char *) 0) % __alignof__ (char *))
+		   % __alignof__ (char *));
+  if (room_left < adjust)
+    goto no_more_room;
+  first_unused += adjust;
+  room_left -= adjust;
+  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 == ',' || isspace (*line))
+	{
+	  int is = isspace (*line);
+
+	  *line++ = '\0';
+	  if (is)
+	    while (*line != '\0' && (*line == ',' || isspace (*line)))
+	      ++line;
+	}
+    }
+  if (room_left < sizeof (char *))
+    goto no_more_room;
+  room_left -= sizeof (char *);
+  gr->gr_mem[count] = NULL;
+
+  return 1;
+}
+
+
+int
+_nss_nisplus_parse_spent (nis_result *result, struct spwd *sp,
+			  char *buffer, size_t buflen, int *errnop)
+{
+  char *first_unused = buffer;
+  size_t room_left = buflen;
+  size_t len;
+
+  if (result == NULL)
+    return 0;
+
+  if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS)
+      || NIS_RES_NUMOBJ (result) != 1
+      || __type_of(NIS_RES_OBJECT (result)) != NIS_ENTRY_OBJ
+      || strcmp (NIS_RES_OBJECT (result)->EN_data.en_type, "passwd_tbl") != 0
+      || NIS_RES_OBJECT (result)->EN_data.en_cols.en_cols_len < 8)
+    return 0;
+
+  if (NISENTRYLEN (0, 0, result) >= room_left)
+    {
+      /* The line is too long for our buffer.  */
+    no_more_room:
+      *errnop = ERANGE;
+      return -1;
+    }
+
+  strncpy (first_unused, NISENTRYVAL (0, 0, result),
+	   NISENTRYLEN (0, 0, result));
+  first_unused[NISENTRYLEN (0, 0, result)] = '\0';
+  len = strlen (first_unused);
+  if (len == 0)
+    return 0;
+  sp->sp_namp = first_unused;
+  room_left -= len + 1;
+  first_unused += len + 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;
+  len = strlen (first_unused);
+  room_left -= len + 1;
+  first_unused += len + 1;
+
+  sp->sp_lstchg = sp->sp_min = sp->sp_max = sp->sp_warn = sp->sp_inact =
+    sp->sp_expire = -1;
+  sp->sp_flag = ~0ul;
+
+  if (NISENTRYLEN (0, 7, result) > 0)
+    {
+      char *line = NISENTRYVAL (0, 7, result);
+      char *cp = strchr (line, ':');
+      if (cp == NULL)
+	return 1;
+      *cp++ = '\0';
+      if (*line)
+	sp->sp_lstchg = atol (line);
+
+      line = cp;
+      cp = strchr (line, ':');
+      if (cp == NULL)
+	return 1;
+      *cp++ = '\0';
+      if (*line)
+	sp->sp_min = atol (line);
+
+      line = cp;
+      cp = strchr (line, ':');
+      if (cp == NULL)
+	return 1;
+      *cp++ = '\0';
+      if (*line)
+	sp->sp_max = atol (line);
+
+      line = cp;
+      cp = strchr (line, ':');
+      if (cp == NULL)
+	return 1;
+      *cp++ = '\0';
+      if (*line)
+	sp->sp_warn = atol (line);
+
+      line = cp;
+      cp = strchr (line, ':');
+      if (cp == NULL)
+	return 1;
+      *cp++ = '\0';
+      if (*line)
+	sp->sp_inact = atol (line);
+
+      line = cp;
+      cp = strchr (line, ':');
+      if (cp == NULL)
+	return 1;
+      *cp++ = '\0';
+      if (*line)
+	sp->sp_expire = atol (line);
+
+      line = cp;
+      if (line == NULL)
+	return 1;
+      if (*line)
+	sp->sp_flag = atol (line);
+    }
+
+  return 1;
+}
diff --git a/REORG.TODO/nis/nss_nisplus/nisplus-proto.c b/REORG.TODO/nis/nss_nisplus/nisplus-proto.c
new file mode 100644
index 0000000000..1f4a24fab2
--- /dev/null
+++ b/REORG.TODO/nis/nss_nisplus/nisplus-proto.c
@@ -0,0 +1,441 @@
+/* Copyright (C) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <atomic.h>
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <nss.h>
+#include <string.h>
+#include <rpcsvc/nis.h>
+#include <libc-lock.h>
+
+#include "nss-nisplus.h"
+
+__libc_lock_define_initialized (static, lock)
+
+static nis_result *result;
+static nis_name tablename_val;
+static u_long tablename_len;
+
+#define NISENTRYVAL(idx, col, res) \
+        (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val)
+
+#define NISENTRYLEN(idx, col, res) \
+        (NIS_RES_OBJECT (res)[idx].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, int *errnop)
+{
+  char *first_unused = buffer;
+  size_t room_left = buflen;
+  unsigned int i;
+
+  if (result == NULL)
+    return 0;
+
+  if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS)
+      || __type_of (NIS_RES_OBJECT (result)) != NIS_ENTRY_OBJ
+      || strcmp (NIS_RES_OBJECT (result)->EN_data.en_type,
+		 "protocols_tbl") != 0
+      || NIS_RES_OBJECT (result)->EN_data.en_cols.en_cols_len < 3)
+    return 0;
+
+  /* Generate the protocols entry format and use the normal parser */
+  if (NISENTRYLEN (0, 0, result) + 1 > room_left)
+    {
+    no_more_room:
+      *errnop = ERANGE;
+      return -1;
+    }
+  strncpy (first_unused, NISENTRYVAL (0, 0, result),
+           NISENTRYLEN (0, 0, result));
+  first_unused[NISENTRYLEN (0, 0, result)] = '\0';
+  proto->p_name = first_unused;
+  size_t len = strlen (first_unused) + 1;
+  room_left -= len;
+  first_unused += len;
+
+
+  proto->p_proto = atoi (NISENTRYVAL (0, 2, result));
+
+  /* XXX Rewrite at some point to allocate the array first and then
+     copy the strings.  It wasteful to first concatenate the strings
+     to just split them again later.  */
+  char *line = first_unused;
+  for (i = 0; i < NIS_RES_NUMOBJ (result); ++i)
+    {
+      if (strcmp (NISENTRYVAL (i, 1, result), proto->p_name) != 0)
+        {
+          if (NISENTRYLEN (i, 1, result) + 2 > room_left)
+            goto no_more_room;
+	  *first_unused++ = ' ';
+          first_unused = __stpncpy (first_unused, NISENTRYVAL (i, 1, result),
+				    NISENTRYLEN (i, 1, result));
+          room_left -= NISENTRYLEN (i, 1, result) + 1;
+        }
+    }
+  *first_unused++ = '\0';
+
+  /* Adjust the pointer so it is aligned for
+     storing pointers.  */
+  size_t adjust = ((__alignof__ (char *)
+		    - (first_unused - (char *) 0) % __alignof__ (char *))
+		   % __alignof__ (char *));
+  if (room_left < adjust + sizeof (char *))
+    goto no_more_room;
+  first_unused += adjust;
+  room_left -= adjust;
+  proto->p_aliases = (char **) first_unused;
+
+  /* For the terminating NULL pointer.  */
+  room_left -= sizeof (char *);
+
+  i = 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 *);
+      proto->p_aliases[i++] = line;
+
+      while (*line != '\0' && *line != ' ')
+        ++line;
+
+      if (*line == ' ')
+	*line++ = '\0';
+    }
+  proto->p_aliases[i] = NULL;
+
+  return 1;
+}
+
+static enum nss_status
+_nss_create_tablename (int *errnop)
+{
+  if (tablename_val == NULL)
+    {
+      const char *local_dir = nis_local_directory ();
+      size_t local_dir_len = strlen (local_dir);
+      static const char prefix[] = "protocols.org_dir.";
+
+      char *p = malloc (sizeof (prefix) + local_dir_len);
+      if (p == NULL)
+	{
+	  *errnop = errno;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+
+      memcpy (__stpcpy (p, prefix), local_dir, local_dir_len + 1);
+
+      tablename_len = sizeof (prefix) - 1 + local_dir_len;
+
+      atomic_write_barrier ();
+
+      tablename_val = p;
+    }
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_setprotoent (int stayopen)
+{
+  enum nss_status status = NSS_STATUS_SUCCESS;
+
+  __libc_lock_lock (lock);
+
+  if (result != NULL)
+    {
+      nis_freeresult (result);
+      result = NULL;
+    }
+
+  if (tablename_val == NULL)
+    {
+      int err;
+      status = _nss_create_tablename (&err);
+    }
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+enum nss_status
+_nss_nisplus_endprotoent (void)
+{
+  __libc_lock_lock (lock);
+
+  if (result != NULL)
+    {
+      nis_freeresult (result);
+      result = 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 *errnop)
+{
+  int parse_res;
+
+  /* Get the next entry until we found a correct one. */
+  do
+    {
+      nis_result *saved_res;
+
+      if (result == NULL)
+	{
+	  saved_res = NULL;
+	  if (tablename_val == NULL)
+	    {
+	      enum nss_status status = _nss_create_tablename (errnop);
+
+	      if (status != NSS_STATUS_SUCCESS)
+		return status;
+	    }
+
+	  result = nis_first_entry (tablename_val);
+	  if (result == NULL)
+	    {
+	      *errnop = errno;
+	      return NSS_STATUS_TRYAGAIN;
+	    }
+	  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	    return niserr2nss (result->status);
+	}
+      else
+	{
+	  saved_res = result;
+	  result = nis_next_entry (tablename_val, &result->cookie);
+	  if (result == NULL)
+	    {
+	      *errnop = errno;
+	      return NSS_STATUS_TRYAGAIN;
+	    }
+	  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	    {
+	      nis_freeresult (saved_res);
+	      return niserr2nss (result->status);
+	    }
+	}
+
+      parse_res = _nss_nisplus_parse_protoent (result, proto, buffer,
+					       buflen, errnop);
+      if (parse_res == -1)
+	{
+	  nis_freeresult (result);
+	  result = saved_res;
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+      else
+	{
+	  if (saved_res)
+	    nis_freeresult (saved_res);
+	}
+    }
+  while (!parse_res);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_getprotoent_r (struct protoent *result, char *buffer,
+			    size_t buflen, int *errnop)
+{
+  int status;
+
+  __libc_lock_lock (lock);
+
+  status = internal_nisplus_getprotoent_r (result, buffer, buflen, errnop);
+
+  __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 *errnop)
+{
+  int parse_res;
+
+  if (tablename_val == NULL)
+    {
+      __libc_lock_lock (lock);
+
+      enum nss_status status = _nss_create_tablename (errnop);
+
+      __libc_lock_unlock (lock);
+
+      if (status != NSS_STATUS_SUCCESS)
+	return status;
+    }
+
+  if (name == NULL)
+    return NSS_STATUS_NOTFOUND;
+
+  char buf[strlen (name) + 10 + tablename_len];
+  int olderr = errno;
+
+  /* Search at first in the alias list, and use the correct name
+     for the next search */
+  snprintf (buf, sizeof (buf), "[name=%s],%s", name, tablename_val);
+  nis_result *result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
+
+  if (result != NULL)
+    {
+      char *bufptr = buf;
+
+      /* If we did 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)
+	  || __type_of (result->objects.objects_val) != NIS_ENTRY_OBJ
+	  || strcmp (result->objects.objects_val->EN_data.en_type,
+			 "protocols_tbl") != 0
+	  || result->objects.objects_val->EN_data.en_cols.en_cols_len < 3)
+	snprintf (buf, sizeof (buf), "[cname=%s],%s", name, tablename_val);
+      else
+	{
+	  /* We need to allocate a new buffer since there is no
+	     guarantee the returned name has a length limit.  */
+	  const char *entryval = NISENTRYVAL (0, 0, result);
+	  size_t buflen = strlen (entryval) + 10 + tablename_len;
+	  bufptr = alloca (buflen);
+	  snprintf (bufptr, buflen, "[cname=%s],%s",
+		    entryval, tablename_val);
+	}
+
+      nis_freeresult (result);
+      result = nis_list (bufptr, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
+    }
+
+  if (result == NULL)
+    {
+      __set_errno (ENOMEM);
+      return NSS_STATUS_TRYAGAIN;
+    }
+
+  if (__glibc_unlikely (niserr2nss (result->status) != NSS_STATUS_SUCCESS))
+    {
+      enum nss_status status = niserr2nss (result->status);
+
+      __set_errno (olderr);
+
+      nis_freeresult (result);
+      return status;
+    }
+
+  parse_res = _nss_nisplus_parse_protoent (result, proto, buffer, buflen,
+					   errnop);
+
+  nis_freeresult (result);
+
+  if (parse_res < 1)
+    {
+      if (parse_res == -1)
+	{
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+      else
+	{
+	  __set_errno (olderr);
+	  return NSS_STATUS_NOTFOUND;
+	}
+    }
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_getprotobynumber_r (const int number, struct protoent *proto,
+				 char *buffer, size_t buflen, int *errnop)
+{
+  if (tablename_val == NULL)
+    {
+      __libc_lock_lock (lock);
+
+      enum nss_status status = _nss_create_tablename (errnop);
+
+      __libc_lock_unlock (lock);
+
+      if (status != NSS_STATUS_SUCCESS)
+	return status;
+    }
+
+  char buf[12 + 3 * sizeof (number) + tablename_len];
+  int olderr = errno;
+
+  snprintf (buf, sizeof (buf), "[number=%d],%s", number, tablename_val);
+
+  nis_result *result = nis_list (buf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL);
+
+  if (result == NULL)
+    {
+      __set_errno (ENOMEM);
+      return NSS_STATUS_TRYAGAIN;
+    }
+
+  if (__glibc_unlikely (niserr2nss (result->status) != NSS_STATUS_SUCCESS))
+    {
+      enum nss_status status = niserr2nss (result->status);
+
+      __set_errno (olderr);
+
+      nis_freeresult (result);
+      return status;
+    }
+
+  int parse_res = _nss_nisplus_parse_protoent (result, proto, buffer, buflen,
+					       errnop);
+
+  nis_freeresult (result);
+
+  if (parse_res < 1)
+    {
+      if (parse_res == -1)
+	{
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+      else
+	{
+	  __set_errno (olderr);
+	  return NSS_STATUS_NOTFOUND;
+	}
+    }
+
+  return NSS_STATUS_SUCCESS;
+}
diff --git a/REORG.TODO/nis/nss_nisplus/nisplus-publickey.c b/REORG.TODO/nis/nss_nisplus/nisplus-publickey.c
new file mode 100644
index 0000000000..d327936941
--- /dev/null
+++ b/REORG.TODO/nis/nss_nisplus/nisplus-publickey.c
@@ -0,0 +1,411 @@
+/* Copyright (c) 1997-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <nss.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <libintl.h>
+#include <syslog.h>
+#include <rpc/rpc.h>
+#include <rpcsvc/nis.h>
+#include <rpc/key_prot.h>
+extern int xdecrypt (char *, char *);
+
+#include <nss-nisplus.h>
+
+/* If we haven't found the entry, we give a SUCCESS and an empty key back. */
+enum nss_status
+_nss_nisplus_getpublickey (const char *netname, char *pkey, int *errnop)
+{
+  nis_result *res;
+  enum nss_status retval;
+  char buf[NIS_MAXNAMELEN + 2];
+  size_t slen;
+  char *domain, *cptr;
+  int len;
+
+  pkey[0] = 0;
+
+  if (netname == NULL)
+    {
+      *errnop = EINVAL;
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  domain = strchr (netname, '@');
+  if (!domain)
+    return NSS_STATUS_UNAVAIL;
+  domain++;
+
+  slen = snprintf (buf, NIS_MAXNAMELEN,
+		   "[auth_name=%s,auth_type=DES],cred.org_dir.%s",
+		   netname, domain);
+
+  if (slen >= NIS_MAXNAMELEN)
+    {
+      *errnop = EINVAL;
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  if (buf[slen - 1] != '.')
+    {
+      buf[slen++] = '.';
+      buf[slen] = '\0';
+    }
+
+  res = nis_list (buf, USE_DGRAM+NO_AUTHINFO+FOLLOW_LINKS+FOLLOW_PATH,
+		  NULL, NULL);
+
+  if (res == NULL)
+    {
+      *errnop = ENOMEM;
+      return NSS_STATUS_TRYAGAIN;
+    }
+  retval = niserr2nss (res->status);
+
+  if (retval != NSS_STATUS_SUCCESS)
+    {
+      if (retval == NSS_STATUS_TRYAGAIN)
+	*errnop = errno;
+      if (res->status == NIS_NOTFOUND)
+	retval = NSS_STATUS_SUCCESS;
+      nis_freeresult (res);
+      return retval;
+    }
+
+  if (NIS_RES_NUMOBJ (res) > 1)
+    {
+      /*
+       * More than one principal with same uid?
+       * something wrong with cred table. Should be unique
+       * Warn user and continue.
+       */
+      syslog (LOG_ERR, _("DES entry for netname %s not unique\n"), netname);
+      nis_freeresult (res);
+      return NSS_STATUS_SUCCESS;
+    }
+
+  len = ENTRY_LEN (NIS_RES_OBJECT (res), 3);
+  memcpy (pkey, ENTRY_VAL (NIS_RES_OBJECT (res),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,
+			   int *errnop)
+{
+  nis_result *res;
+  enum nss_status retval;
+  char buf[NIS_MAXNAMELEN + 2];
+  size_t slen;
+  char *domain, *cptr;
+  int len;
+
+  skey[0] = 0;
+
+  if (netname == NULL)
+    {
+      *errnop = EINVAL;
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  domain = strchr (netname, '@');
+  if (!domain)
+    return NSS_STATUS_UNAVAIL;
+  domain++;
+
+  slen = snprintf (buf, NIS_MAXNAMELEN,
+		   "[auth_name=%s,auth_type=DES],cred.org_dir.%s",
+		   netname, domain);
+
+  if (slen >= NIS_MAXNAMELEN)
+    {
+      *errnop = EINVAL;
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  if (buf[slen - 1] != '.')
+    {
+      buf[slen++] = '.';
+      buf[slen] = '\0';
+    }
+
+  res = nis_list (buf, USE_DGRAM | NO_AUTHINFO | FOLLOW_LINKS | FOLLOW_PATH,
+		  NULL, NULL);
+
+  if (res == NULL)
+    {
+      *errnop = ENOMEM;
+      return NSS_STATUS_TRYAGAIN;
+    }
+  retval = niserr2nss (res->status);
+
+  if (retval != NSS_STATUS_SUCCESS)
+    {
+      if (retval == NSS_STATUS_TRYAGAIN)
+	*errnop = errno;
+      nis_freeresult (res);
+      return retval;
+    }
+
+  if (NIS_RES_NUMOBJ (res) > 1)
+    {
+      /*
+       * More than one principal with same uid?
+       * something wrong with cred table. Should be unique
+       * Warn user and continue.
+       */
+      syslog (LOG_ERR, _("DES entry for netname %s not unique\n"), netname);
+      nis_freeresult (res);
+      return NSS_STATUS_SUCCESS;
+    }
+
+  len = ENTRY_LEN (NIS_RES_OBJECT (res), 4);
+  memcpy (buf, ENTRY_VAL (NIS_RES_OBJECT (res), 4), len);
+  buf[len] = '\0';
+  cptr = strchr (buf, ':');
+  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 *errnop)
+{
+  char *ep;
+  int gidlen;
+
+  if (!s || (!isdigit (*s)))
+    {
+      syslog (LOG_ERR, _("netname2user: missing group id list in `%s'"), s);
+      return NSS_STATUS_NOTFOUND;
+    }
+
+  *gidp = strtoul (s, &ep, 10);
+
+  gidlen = 0;
+
+  /* After strtoul() ep should point to the marker ',', which means
+     here starts a new value.
+
+     The Sun man pages show that GIDLIST should contain at least NGRPS
+     elements.  Limiting the number written by this value is the best
+     we can do.  */
+  while (ep != NULL && *ep == ',' && gidlen < NGRPS)
+    {
+      ep++;
+      s = ep;
+      gidlist[gidlen++] = strtoul (s, &ep, 10);
+    }
+  *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, int *errnop)
+{
+  char *domain;
+  nis_result *res;
+  char sname[NIS_MAXNAMELEN + 2]; /*  search criteria + table name */
+  size_t slen;
+  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.  */
+  slen = snprintf (sname, NIS_MAXNAMELEN,
+		   "[auth_name=%s,auth_type=DES],cred.org_dir.%s",
+		   netname, domain);
+
+  if (slen >= NIS_MAXNAMELEN)
+    {
+      *errnop = EINVAL;
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  if (sname[slen - 1] != '.')
+    {
+      sname[slen++] = '.';
+      sname[slen] = '\0';
+    }
+
+  /* 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);
+  if (res == NULL)
+    {
+      *errnop = ENOMEM;
+      return NSS_STATUS_TRYAGAIN;
+    }
+  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);
+      *errnop = errno;
+      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 (NIS_RES_NUMOBJ (res) > 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 (NIS_RES_OBJECT (res), 0);
+  strncpy (principal, ENTRY_VAL (NIS_RES_OBJECT (res), 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;
+    }
+
+  slen = snprintf (sname, sizeof  (sname),
+		   "[cname=%s,auth_type=LOCAL],cred.org_dir.%s",
+		   principal, domain);
+
+  if (sname[slen - 1] != '.')
+    {
+      sname[slen++] = '.';
+      sname[slen] = '\0';
+    }
+
+  /* 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);
+  if (res == NULL)
+    {
+      *errnop = ENOMEM;
+      return NSS_STATUS_TRYAGAIN;
+    }
+  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);
+      *errnop = errno;
+      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 (NIS_RES_NUMOBJ (res) > 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 = strtoul (ENTRY_VAL (NIS_RES_OBJECT (res), 2), NULL, 10);
+
+  if (*uidp == 0)
+    {
+      syslog (LOG_ERR, _("netname2user: should not have uid 0"));
+      nis_freeresult (res);
+      return NSS_STATUS_NOTFOUND;
+    }
+
+  parse_grp_str (ENTRY_VAL (NIS_RES_OBJECT (res), 3),
+		 gidp, gidlenp, gidlist, errnop);
+
+  nis_freeresult (res);
+  return NSS_STATUS_SUCCESS;
+}
diff --git a/REORG.TODO/nis/nss_nisplus/nisplus-pwd.c b/REORG.TODO/nis/nss_nisplus/nisplus-pwd.c
new file mode 100644
index 0000000000..3b5e25ea43
--- /dev/null
+++ b/REORG.TODO/nis/nss_nisplus/nisplus-pwd.c
@@ -0,0 +1,408 @@
+/* Copyright (C) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <atomic.h>
+#include <nss.h>
+#include <errno.h>
+#include <pwd.h>
+#include <string.h>
+#include <libc-lock.h>
+#include <rpcsvc/nis.h>
+
+#include "nss-nisplus.h"
+#include "nisplus-parser.h"
+#include <libnsl.h>
+#include <nis_intern.h>
+#include <nis_xdr.h>
+
+
+__libc_lock_define_initialized (static, lock)
+
+/* Connection information.  */
+static ib_request *ibreq;
+static directory_obj *dir;
+static dir_binding bptr;
+static char *tablepath;
+static char *tableptr;
+/* Cursor.  */
+static netobj cursor;
+
+
+nis_name pwd_tablename_val attribute_hidden;
+size_t pwd_tablename_len attribute_hidden;
+
+enum nss_status
+_nss_pwd_create_tablename (int *errnop)
+{
+  if (pwd_tablename_val == NULL)
+    {
+      const char *local_dir = nis_local_directory ();
+      size_t local_dir_len = strlen (local_dir);
+      static const char prefix[] = "passwd.org_dir.";
+
+      char *p = malloc (sizeof (prefix) + local_dir_len);
+      if (p == NULL)
+	{
+	  *errnop = errno;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+
+      memcpy (__stpcpy (p, prefix), local_dir, local_dir_len + 1);
+
+      pwd_tablename_len = sizeof (prefix) - 1 + local_dir_len;
+
+      atomic_write_barrier ();
+
+      if (atomic_compare_and_exchange_bool_acq (&pwd_tablename_val, p, NULL))
+	{
+	  /* Another thread already installed the value.  */
+	  free (p);
+	  pwd_tablename_len = strlen (pwd_tablename_val);
+	}
+    }
+
+  return NSS_STATUS_SUCCESS;
+}
+
+
+static void
+internal_nisplus_endpwent (void)
+{
+  __nisbind_destroy (&bptr);
+  memset (&bptr, '\0', sizeof (bptr));
+
+  nis_free_directory (dir);
+  dir = NULL;
+
+  nis_free_request (ibreq);
+  ibreq = NULL;
+
+  xdr_free ((xdrproc_t) xdr_netobj, (char *) &cursor);
+  memset (&cursor, '\0', sizeof (cursor));
+
+  free (tablepath);
+  tableptr = tablepath = NULL;
+}
+
+
+static enum nss_status
+internal_nisplus_setpwent (int *errnop)
+{
+  enum nss_status status = NSS_STATUS_SUCCESS;
+
+  if (pwd_tablename_val == NULL)
+    status = _nss_pwd_create_tablename (errnop);
+
+  if (status == NSS_STATUS_SUCCESS)
+    {
+      ibreq = __create_ib_request (pwd_tablename_val, 0);
+      if (ibreq == NULL)
+	{
+	  *errnop = errno;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+
+      nis_error retcode = __prepare_niscall (pwd_tablename_val, &dir,
+					     &bptr, 0);
+      if (retcode != NIS_SUCCESS)
+	{
+	  nis_free_request (ibreq);
+	  ibreq = NULL;
+	  status = niserr2nss (retcode);
+	}
+    }
+
+  return status;
+}
+
+
+enum nss_status
+_nss_nisplus_setpwent (int stayopen)
+{
+  enum nss_status status;
+
+  __libc_lock_lock (lock);
+
+  internal_nisplus_endpwent ();
+
+  // XXX We need to be able to set errno.  Pass in new parameter.
+  int err;
+  status = internal_nisplus_setpwent (&err);
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+
+enum nss_status
+_nss_nisplus_endpwent (void)
+{
+  __libc_lock_lock (lock);
+
+  internal_nisplus_endpwent ();
+
+  __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 *errnop)
+{
+  int parse_res = -1;
+  enum nss_status retval = NSS_STATUS_SUCCESS;
+
+  /* Get the next entry until we found a correct one. */
+  do
+    {
+      nis_error status;
+      nis_result result;
+      memset (&result, '\0', sizeof (result));
+
+      if (cursor.n_bytes == NULL)
+	{
+	  if (ibreq == NULL)
+	    {
+	      retval = internal_nisplus_setpwent (errnop);
+	      if (retval != NSS_STATUS_SUCCESS)
+		return retval;
+	    }
+
+	  status = __do_niscall3 (&bptr, NIS_IBFIRST,
+				  (xdrproc_t) _xdr_ib_request,
+				  (caddr_t) ibreq,
+				  (xdrproc_t) _xdr_nis_result,
+				  (caddr_t) &result,
+				  0, NULL);
+	}
+      else
+	{
+	  ibreq->ibr_cookie.n_bytes = cursor.n_bytes;
+	  ibreq->ibr_cookie.n_len = cursor.n_len;
+
+	  status = __do_niscall3 (&bptr, NIS_IBNEXT,
+				  (xdrproc_t) _xdr_ib_request,
+				  (caddr_t) ibreq,
+				  (xdrproc_t) _xdr_nis_result,
+				  (caddr_t) &result,
+				  0, NULL);
+
+	  ibreq->ibr_cookie.n_bytes = NULL;
+	  ibreq->ibr_cookie.n_len = 0;
+	}
+
+      if (status != NIS_SUCCESS)
+	return niserr2nss (status);
+
+      if (NIS_RES_STATUS (&result) == NIS_NOTFOUND)
+	{
+	  /* No more entries on this server.  This means we have to go
+	     to the next server on the path.  */
+	  status = __follow_path (&tablepath, &tableptr, ibreq, &bptr);
+	  if (status != NIS_SUCCESS)
+	    return niserr2nss (status);
+
+	  directory_obj *newdir = NULL;
+	  dir_binding newbptr;
+	  status = __prepare_niscall (ibreq->ibr_name, &newdir, &newbptr, 0);
+	  if (status != NIS_SUCCESS)
+	    return niserr2nss (status);
+
+	  nis_free_directory (dir);
+	  dir = newdir;
+	  __nisbind_destroy (&bptr);
+	  bptr = newbptr;
+
+	  xdr_free ((xdrproc_t) xdr_netobj, (char *) &result.cookie);
+	  result.cookie.n_bytes = NULL;
+	  result.cookie.n_len = 0;
+	  parse_res = 0;
+	  goto next;
+	}
+      else if (NIS_RES_STATUS (&result) != NIS_SUCCESS)
+	return niserr2nss (NIS_RES_STATUS (&result));
+
+      parse_res = _nss_nisplus_parse_pwent (&result, pw, buffer,
+					    buflen, errnop);
+
+      if (__glibc_unlikely (parse_res == -1))
+	{
+	  *errnop = ERANGE;
+	  retval = NSS_STATUS_TRYAGAIN;
+	  goto freeres;
+	}
+
+    next:
+      /* Free the old cursor.  */
+      xdr_free ((xdrproc_t) xdr_netobj, (char *) &cursor);
+      /* Remember the new one.  */
+      cursor.n_bytes = result.cookie.n_bytes;
+      cursor.n_len = result.cookie.n_len;
+      /* Free the result structure.  NB: we do not remove the cookie.  */
+      result.cookie.n_bytes = NULL;
+      result.cookie.n_len = 0;
+    freeres:
+      xdr_free ((xdrproc_t) _xdr_nis_result, (char *) &result);
+      memset (&result, '\0', sizeof (result));
+    }
+  while (!parse_res);
+
+  return retval;
+}
+
+enum nss_status
+_nss_nisplus_getpwent_r (struct passwd *result, char *buffer, size_t buflen,
+			 int *errnop)
+{
+  int status;
+
+  __libc_lock_lock (lock);
+
+  status = internal_nisplus_getpwent_r (result, buffer, buflen, errnop);
+
+  __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 *errnop)
+{
+  int parse_res;
+
+  if (pwd_tablename_val == NULL)
+    {
+      enum nss_status status = _nss_pwd_create_tablename (errnop);
+
+      if (status != NSS_STATUS_SUCCESS)
+	return status;
+    }
+
+  if (name == NULL)
+    {
+      *errnop = EINVAL;
+      return NSS_STATUS_UNAVAIL;
+    }
+
+  nis_result *result;
+  char buf[strlen (name) + 9 + pwd_tablename_len];
+  int olderr = errno;
+
+  snprintf (buf, sizeof (buf), "[name=%s],%s", name, pwd_tablename_val);
+
+  result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS | USE_DGRAM, NULL, NULL);
+
+  if (result == NULL)
+    {
+      *errnop = ENOMEM;
+      return NSS_STATUS_TRYAGAIN;
+    }
+
+  if (__glibc_unlikely (niserr2nss (result->status) != NSS_STATUS_SUCCESS))
+    {
+      enum nss_status status =  niserr2nss (result->status);
+
+      __set_errno (olderr);
+
+      nis_freeresult (result);
+      return status;
+    }
+
+  parse_res = _nss_nisplus_parse_pwent (result, pw, buffer, buflen, errnop);
+
+  nis_freeresult (result);
+
+  if (__glibc_unlikely (parse_res < 1))
+    {
+      if (parse_res == -1)
+	{
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+      else
+	{
+	  __set_errno (olderr);
+	  return NSS_STATUS_NOTFOUND;
+	}
+    }
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_getpwuid_r (const uid_t uid, struct passwd *pw,
+			 char *buffer, size_t buflen, int *errnop)
+{
+  if (pwd_tablename_val == NULL)
+    {
+      enum nss_status status = _nss_pwd_create_tablename (errnop);
+
+      if (status != NSS_STATUS_SUCCESS)
+	return status;
+    }
+
+  int parse_res;
+  nis_result *result;
+  char buf[8 + 3 * sizeof (unsigned long int) + pwd_tablename_len];
+  int olderr = errno;
+
+  snprintf (buf, sizeof (buf), "[uid=%lu],%s",
+	    (unsigned long int) uid, pwd_tablename_val);
+
+  result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS | USE_DGRAM, NULL, NULL);
+
+  if (result == NULL)
+    {
+      *errnop = ENOMEM;
+      return NSS_STATUS_TRYAGAIN;
+    }
+
+  if (__glibc_unlikely (niserr2nss (result->status) != NSS_STATUS_SUCCESS))
+    {
+      enum nss_status status = niserr2nss (result->status);
+
+      __set_errno (olderr);
+
+      nis_freeresult (result);
+      return status;
+    }
+
+  parse_res = _nss_nisplus_parse_pwent (result, pw, buffer, buflen, errnop);
+
+  nis_freeresult (result);
+
+  if (__glibc_unlikely (parse_res < 1))
+    {
+      if (parse_res == -1)
+	{
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+      else
+	{
+	  __set_errno (olderr);
+	  return NSS_STATUS_NOTFOUND;
+	}
+    }
+
+  return NSS_STATUS_SUCCESS;
+}
diff --git a/REORG.TODO/nis/nss_nisplus/nisplus-rpc.c b/REORG.TODO/nis/nss_nisplus/nisplus-rpc.c
new file mode 100644
index 0000000000..977d85a574
--- /dev/null
+++ b/REORG.TODO/nis/nss_nisplus/nisplus-rpc.c
@@ -0,0 +1,444 @@
+/* Copyright (C) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <atomic.h>
+#include <ctype.h>
+#include <errno.h>
+#include <nss.h>
+#include <string.h>
+#include <rpc/netdb.h>
+#include <rpcsvc/nis.h>
+#include <libc-lock.h>
+
+#include "nss-nisplus.h"
+
+__libc_lock_define_initialized (static, lock)
+
+static nis_result *result;
+static nis_name tablename_val;
+static u_long tablename_len;
+
+#define NISENTRYVAL(idx, col, res) \
+        (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val)
+
+#define NISENTRYLEN(idx, col, res) \
+        (NIS_RES_OBJECT (res)[idx].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, int *errnop)
+{
+  char *first_unused = buffer;
+  size_t room_left = buflen;
+  unsigned int i;
+  char *line;
+
+
+  if (result == NULL)
+    return 0;
+
+  if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS)
+      || __type_of (NIS_RES_OBJECT (result)) != NIS_ENTRY_OBJ
+      || strcmp (NIS_RES_OBJECT (result)[0].EN_data.en_type, "rpc_tbl") != 0
+      || NIS_RES_OBJECT (result)[0].EN_data.en_cols.en_cols_len < 3)
+    return 0;
+
+  if (NISENTRYLEN (0, 0, result) >= room_left)
+    {
+    no_more_room:
+      *errnop = ERANGE;
+      return -1;
+    }
+  strncpy (first_unused, NISENTRYVAL (0, 0, result),
+           NISENTRYLEN (0, 0, result));
+  first_unused[NISENTRYLEN (0, 0, result)] = '\0';
+  rpc->r_name = first_unused;
+  size_t len = strlen (first_unused) + 1;
+  room_left -= len;
+  first_unused += len;
+
+  rpc->r_number = atoi (NISENTRYVAL (0, 2, result));
+
+  /* XXX Rewrite at some point to allocate the array first and then
+     copy the strings.  It wasteful to first concatenate the strings
+     to just split them again later.  */
+  line = first_unused;
+  for (i = 0; i < NIS_RES_NUMOBJ (result); ++i)
+    {
+      if (strcmp (NISENTRYVAL (i, 1, result), rpc->r_name) != 0)
+        {
+          if (NISENTRYLEN (i, 1, result) + 2 > room_left)
+	    goto no_more_room;
+	  *first_unused++ = ' ';
+          first_unused = __stpncpy (first_unused, NISENTRYVAL (i, 1, result),
+				    NISENTRYLEN (i, 1, result));
+          room_left -= NISENTRYLEN (i, 1, result) + 1;
+        }
+    }
+  *first_unused++ = '\0';
+
+  /* Adjust the pointer so it is aligned for
+     storing pointers.  */
+  size_t adjust = ((__alignof__ (char *)
+		    - (first_unused - (char *) 0) % __alignof__ (char *))
+		   % __alignof__ (char *));
+  if (room_left < adjust + sizeof (char *))
+    goto no_more_room;
+  first_unused += adjust;
+  room_left -= adjust;
+  rpc->r_aliases = (char **) first_unused;
+
+  /* For the terminating NULL pointer.  */
+  room_left -= sizeof (char *);
+
+  i = 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 *);
+      rpc->r_aliases[i++] = line;
+
+      while (*line != '\0' && *line != ' ')
+        ++line;
+
+      if (*line == ' ')
+	*line++ = '\0';
+    }
+  rpc->r_aliases[i] = NULL;
+
+  return 1;
+}
+
+
+static enum nss_status
+_nss_create_tablename (int *errnop)
+{
+  if (tablename_val == NULL)
+    {
+      const char *local_dir = nis_local_directory ();
+      size_t local_dir_len = strlen (local_dir);
+      static const char prefix[] = "rpc.org_dir.";
+
+      char *p = malloc (sizeof (prefix) + local_dir_len);
+      if (p == NULL)
+	{
+	  *errnop = errno;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+
+      memcpy (__stpcpy (p, prefix), local_dir, local_dir_len + 1);
+
+      tablename_len = sizeof (prefix) - 1 + local_dir_len;
+
+      atomic_write_barrier ();
+
+      tablename_val = p;
+    }
+
+  return NSS_STATUS_SUCCESS;
+}
+
+
+enum nss_status
+_nss_nisplus_setrpcent (int stayopen)
+{
+  enum nss_status status = NSS_STATUS_SUCCESS;
+
+  __libc_lock_lock (lock);
+
+  if (result != NULL)
+    {
+      nis_freeresult (result);
+      result = NULL;
+    }
+
+  if (tablename_val == NULL)
+    {
+      int err;
+      status = _nss_create_tablename (&err);
+    }
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+enum nss_status
+_nss_nisplus_endrpcent (void)
+{
+  __libc_lock_lock (lock);
+
+  if (result != NULL)
+    {
+      nis_freeresult (result);
+      result = 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 *errnop)
+{
+  int parse_res;
+
+  /* Get the next entry until we found a correct one. */
+  do
+    {
+      nis_result *saved_res;
+
+      if (result == NULL)
+	{
+	  saved_res = NULL;
+          if (tablename_val == NULL)
+	    {
+	      enum nss_status status =  _nss_create_tablename (errnop);
+
+	      if (status != NSS_STATUS_SUCCESS)
+		return status;
+	    }
+
+	  result = nis_first_entry (tablename_val);
+	  if (result == NULL)
+	    {
+	      *errnop = errno;
+	      return NSS_STATUS_TRYAGAIN;
+	    }
+	  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	    return niserr2nss (result->status);
+	}
+      else
+	{
+	  saved_res = result;
+	  result = nis_next_entry (tablename_val, &result->cookie);
+	  if (result == NULL)
+	    {
+	      *errnop = errno;
+	      return NSS_STATUS_TRYAGAIN;
+	    }
+	  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	    {
+	      nis_freeresult (saved_res);
+	      return niserr2nss (result->status);
+	    }
+	}
+
+      parse_res = _nss_nisplus_parse_rpcent (result, rpc, buffer,
+					     buflen, errnop);
+      if (parse_res == -1)
+	{
+	  nis_freeresult (result);
+	  result = saved_res;
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+      else
+	{
+	  if (saved_res)
+	    nis_freeresult (saved_res);
+	}
+    }
+  while (!parse_res);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_getrpcent_r (struct rpcent *result, char *buffer,
+			  size_t buflen, int *errnop)
+{
+  int status;
+
+  __libc_lock_lock (lock);
+
+  status = internal_nisplus_getrpcent_r (result, buffer, buflen, errnop);
+
+  __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 *errnop)
+{
+  int parse_res;
+
+  if (tablename_val == NULL)
+    {
+      __libc_lock_lock (lock);
+
+      enum nss_status status = _nss_create_tablename (errnop);
+
+      __libc_lock_unlock (lock);
+
+      if (status != NSS_STATUS_SUCCESS)
+	return status;
+    }
+
+  if (name == NULL)
+    return NSS_STATUS_NOTFOUND;
+
+  char buf[strlen (name) + 10 + tablename_len];
+  int olderr = errno;
+
+  /* Search at first in the alias list, and use the correct name
+     for the next search */
+  snprintf (buf, sizeof (buf), "[name=%s],%s", name, tablename_val);
+  nis_result *result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS | USE_DGRAM,
+				 NULL, NULL);
+
+  if (result != NULL)
+    {
+      char *bufptr = buf;
+
+      /* If we did 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)
+	  || __type_of (result->objects.objects_val) != NIS_ENTRY_OBJ
+	  || strcmp (result->objects.objects_val->EN_data.en_type,
+		     "rpc_tbl") != 0
+	  || result->objects.objects_val->EN_data.en_cols.en_cols_len < 3)
+	snprintf (buf, sizeof (buf), "[cname=%s],%s", name, tablename_val);
+      else
+	{
+	  /* We need to allocate a new buffer since there is no
+	     guarantee the returned name has a length limit.  */
+	  const char *entryval = NISENTRYVAL (0, 0, result);
+	  size_t buflen = strlen (entryval) + 10 + tablename_len;
+	  bufptr = alloca (buflen);
+	  snprintf (bufptr, buflen, "[cname=%s],%s",
+		    entryval, tablename_val);
+	}
+
+      nis_freeresult (result);
+      result = nis_list (bufptr, FOLLOW_PATH | FOLLOW_LINKS | USE_DGRAM,
+			 NULL, NULL);
+    }
+
+  if (result == NULL)
+    {
+      *errnop = ENOMEM;
+      return NSS_STATUS_TRYAGAIN;
+    }
+
+  if (__glibc_unlikely (niserr2nss (result->status) != NSS_STATUS_SUCCESS))
+    {
+      enum nss_status status = niserr2nss (result->status);
+
+      __set_errno (olderr);
+
+      nis_freeresult (result);
+      return status;
+    }
+
+  parse_res = _nss_nisplus_parse_rpcent (result, rpc, buffer, buflen,
+					     errnop);
+
+  nis_freeresult (result);
+
+  if (parse_res < 1)
+    {
+      if (parse_res == -1)
+	{
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+
+      __set_errno (olderr);
+      return NSS_STATUS_NOTFOUND;
+    }
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_getrpcbynumber_r (const int number, struct rpcent *rpc,
+			       char *buffer, size_t buflen, int *errnop)
+{
+  if (tablename_val == NULL)
+    {
+      __libc_lock_lock (lock);
+
+      enum nss_status status = _nss_create_tablename (errnop);
+
+      __libc_lock_unlock (lock);
+
+      if (status != NSS_STATUS_SUCCESS)
+	return status;
+    }
+
+  char buf[12 + 3 * sizeof (number) + tablename_len];
+  int olderr = errno;
+
+  snprintf (buf, sizeof (buf), "[number=%d],%s", number, tablename_val);
+
+  nis_result *result = nis_list (buf, FOLLOW_LINKS | FOLLOW_PATH | USE_DGRAM,
+				 NULL, NULL);
+
+  if (result == NULL)
+    {
+      *errnop = ENOMEM;
+      return NSS_STATUS_TRYAGAIN;
+    }
+
+  if (__builtin_expect (niserr2nss (result->status) != NSS_STATUS_SUCCESS,  0))
+    {
+      enum nss_status status = niserr2nss (result->status);
+
+      __set_errno (olderr);
+
+      nis_freeresult (result);
+      return status;
+    }
+
+  int parse_res = _nss_nisplus_parse_rpcent (result, rpc, buffer, buflen,
+					     errnop);
+
+  nis_freeresult (result);
+
+  if (parse_res < 1)
+    {
+      if (parse_res == -1)
+	{
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+      else
+	{
+	  __set_errno (olderr);
+	  return NSS_STATUS_NOTFOUND;
+	}
+    }
+
+  return NSS_STATUS_SUCCESS;
+}
diff --git a/REORG.TODO/nis/nss_nisplus/nisplus-service.c b/REORG.TODO/nis/nss_nisplus/nisplus-service.c
new file mode 100644
index 0000000000..302087153f
--- /dev/null
+++ b/REORG.TODO/nis/nss_nisplus/nisplus-service.c
@@ -0,0 +1,461 @@
+/* Copyright (C) 1997-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <atomic.h>
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <nss.h>
+#include <string.h>
+#include <rpcsvc/nis.h>
+#include <libc-lock.h>
+
+#include "nss-nisplus.h"
+
+__libc_lock_define_initialized (static, lock);
+
+static nis_result *result;
+static nis_name tablename_val;
+static u_long tablename_len;
+
+#define NISENTRYVAL(idx, col, res) \
+  (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val)
+
+#define NISENTRYLEN(idx, col, res) \
+    (NIS_RES_OBJECT (res)[idx].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, int *errnop)
+{
+  char *first_unused = buffer;
+  size_t room_left = buflen;
+
+  if (result == NULL)
+    return 0;
+
+  if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS)
+      || __type_of (NIS_RES_OBJECT (result)) != NIS_ENTRY_OBJ
+      || strcmp (NIS_RES_OBJECT (result)->EN_data.en_type, "services_tbl") != 0
+      || NIS_RES_OBJECT (result)->EN_data.en_cols.en_cols_len < 4)
+    return 0;
+
+  if (NISENTRYLEN (0, 0, result) >= room_left)
+    {
+    no_more_room:
+      *errnop = ERANGE;
+      return -1;
+    }
+  strncpy (first_unused, NISENTRYVAL (0, 0, result),
+           NISENTRYLEN (0, 0, result));
+  first_unused[NISENTRYLEN (0, 0, result)] = '\0';
+  serv->s_name = first_unused;
+  size_t len = strlen (first_unused) + 1;
+  room_left -= len;
+  first_unused += len;
+
+  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';
+  serv->s_proto = first_unused;
+  len = strlen (first_unused) + 1;
+  room_left -= len;
+  first_unused += len;
+
+  serv->s_port = htons (atoi (NISENTRYVAL (0, 3, result)));
+
+  /* XXX Rewrite at some point to allocate the array first and then
+     copy the strings.  It wasteful to first concatenate the strings
+     to just split them again later.  */
+  char *line = first_unused;
+  for (unsigned int i = 0; i < NIS_RES_NUMOBJ (result); ++i)
+    {
+      if (strcmp (NISENTRYVAL (i, 1, result), serv->s_name) != 0)
+        {
+          if (NISENTRYLEN (i, 1, result) + 2 > room_left)
+            goto no_more_room;
+	  *first_unused++ = ' ';
+          first_unused = __stpncpy (first_unused, NISENTRYVAL (i, 1, result),
+				    NISENTRYLEN (i, 1, result));
+          room_left -= NISENTRYLEN (i, 1, result) + 1;
+        }
+    }
+  *first_unused++ = '\0';
+
+  /* Adjust the pointer so it is aligned for
+     storing pointers.  */
+  size_t adjust = ((__alignof__ (char *)
+		    - (first_unused - (char *) 0) % __alignof__ (char *))
+		   % __alignof__ (char *));
+  if (room_left < adjust + sizeof (char *))
+    goto no_more_room;
+  first_unused += adjust;
+  room_left -= adjust;
+  serv->s_aliases = (char **) first_unused;
+
+  /* For the terminating NULL pointer.  */
+  room_left -= (sizeof (char *));
+
+  unsigned int i = 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 *);
+      serv->s_aliases[i++] = line;
+
+      while (*line != '\0' && *line != ' ')
+        ++line;
+
+      if (*line == ' ')
+	*line++ = '\0';
+    }
+  serv->s_aliases[i] = NULL;
+
+  return 1;
+}
+
+
+static enum nss_status
+_nss_create_tablename (int *errnop)
+{
+  if (tablename_val == NULL)
+    {
+      const char *local_dir = nis_local_directory ();
+      size_t local_dir_len = strlen (local_dir);
+      static const char prefix[] = "services.org_dir.";
+
+      char *p = malloc (sizeof (prefix) + local_dir_len);
+      if (p == NULL)
+	{
+	  *errnop = errno;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+
+      memcpy (__stpcpy (p, prefix), local_dir, local_dir_len + 1);
+
+      tablename_len = sizeof (prefix) - 1 + local_dir_len;
+
+      atomic_write_barrier ();
+
+      tablename_val = p;
+    }
+
+  return NSS_STATUS_SUCCESS;
+}
+
+
+enum nss_status
+_nss_nisplus_setservent (int stayopen)
+{
+  enum nss_status status = NSS_STATUS_SUCCESS;
+  int err;
+
+  __libc_lock_lock (lock);
+
+  if (result != NULL)
+    {
+      nis_freeresult (result);
+      result = NULL;
+    }
+
+  if (tablename_val == NULL)
+    status = _nss_create_tablename (&err);
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+enum nss_status
+_nss_nisplus_endservent (void)
+{
+  __libc_lock_lock (lock);
+
+  if (result != NULL)
+    {
+      nis_freeresult (result);
+      result = 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 *errnop)
+{
+  int parse_res;
+
+  /* Get the next entry until we found a correct one. */
+  do
+    {
+      nis_result *saved_res;
+
+      if (result == NULL)
+	{
+	  saved_res = NULL;
+          if (tablename_val == NULL)
+	    {
+	      enum nss_status status = _nss_create_tablename (errnop);
+
+	      if (status != NSS_STATUS_SUCCESS)
+		return status;
+	    }
+
+	  result = nis_first_entry (tablename_val);
+	  if (result == NULL)
+	    {
+	      *errnop = errno;
+	      return NSS_STATUS_TRYAGAIN;
+	    }
+	  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	    return niserr2nss (result->status);
+	}
+      else
+	{
+	  saved_res = result;
+	  result = nis_next_entry (tablename_val, &result->cookie);
+	  if (result == NULL)
+	    {
+	      *errnop = errno;
+	      return NSS_STATUS_TRYAGAIN;
+	    }
+	  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	    {
+	      nis_freeresult (saved_res);
+	      return niserr2nss (result->status);
+	    }
+	}
+
+      parse_res = _nss_nisplus_parse_servent (result, serv, buffer,
+					      buflen, errnop);
+      if (__glibc_unlikely (parse_res == -1))
+	{
+	  nis_freeresult (result);
+	  result = saved_res;
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+      else
+	{
+	  if (saved_res)
+	    nis_freeresult (saved_res);
+	}
+    }
+  while (!parse_res);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_getservent_r (struct servent *result, char *buffer,
+			   size_t buflen, int *errnop)
+{
+  __libc_lock_lock (lock);
+
+  int status = internal_nisplus_getservent_r (result, buffer, buflen, errnop);
+
+  __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 *errnop)
+{
+  if (tablename_val == NULL)
+    {
+      __libc_lock_lock (lock);
+
+      enum nss_status status = _nss_create_tablename (errnop);
+
+      __libc_lock_unlock (lock);
+
+      if (status != NSS_STATUS_SUCCESS)
+	return status;
+    }
+
+  if (name == NULL || protocol == NULL)
+    {
+      *errnop = EINVAL;
+      return NSS_STATUS_NOTFOUND;
+    }
+
+  size_t protocol_len = strlen (protocol);
+  char buf[strlen (name) + protocol_len + 17 + tablename_len];
+  int olderr = errno;
+
+  /* Search at first in the alias list, and use the correct name
+     for the next search */
+  snprintf (buf, sizeof (buf), "[name=%s,proto=%s],%s", name, protocol,
+	    tablename_val);
+  nis_result *result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS | USE_DGRAM,
+				 NULL, NULL);
+
+  if (result != NULL)
+    {
+      char *bufptr = buf;
+
+      /* If we did 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)
+	  || __type_of (NIS_RES_OBJECT (result)) != NIS_ENTRY_OBJ
+	  || strcmp (NIS_RES_OBJECT (result)->EN_data.en_type,
+		     "services_tbl") != 0
+	  || NIS_RES_OBJECT (result)->EN_data.en_cols.en_cols_len < 4)
+	snprintf (buf, sizeof (buf), "[cname=%s,proto=%s],%s", name, protocol,
+		  tablename_val);
+      else
+	{
+	  /* We need to allocate a new buffer since there is no
+	     guarantee the returned name has a length limit.  */
+	  const char *entryval = NISENTRYVAL(0, 0, result);
+	  size_t buflen = (strlen (entryval) + protocol_len + 17
+			   + tablename_len);
+	  bufptr = alloca (buflen);
+	  snprintf (bufptr, buflen, "[cname=%s,proto=%s],%s",
+		    entryval, protocol, tablename_val);
+	}
+
+      nis_freeresult (result);
+      result = nis_list (bufptr, FOLLOW_PATH | FOLLOW_LINKS | USE_DGRAM,
+			 NULL, NULL);
+    }
+
+  if (result == NULL)
+    {
+      *errnop = ENOMEM;
+      return NSS_STATUS_TRYAGAIN;
+    }
+
+  if (__glibc_unlikely (niserr2nss (result->status) != NSS_STATUS_SUCCESS))
+    {
+      enum nss_status status = niserr2nss (result->status);
+
+      __set_errno (olderr);
+
+      nis_freeresult (result);
+      return status;
+    }
+
+  int parse_res = _nss_nisplus_parse_servent (result, serv, buffer, buflen,
+					      errnop);
+  nis_freeresult (result);
+
+  if (__glibc_unlikely (parse_res < 1))
+    {
+      if (parse_res == -1)
+	{
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+      else
+	{
+	  __set_errno (olderr);
+	  return NSS_STATUS_NOTFOUND;
+	}
+    }
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_getservbyport_r (const int number, const char *protocol,
+			      struct servent *serv,
+			      char *buffer, size_t buflen, int *errnop)
+{
+  if (tablename_val == NULL)
+    {
+      __libc_lock_lock (lock);
+
+      enum nss_status status = _nss_create_tablename (errnop);
+
+      __libc_lock_unlock (lock);
+
+      if (status != NSS_STATUS_SUCCESS)
+	return status;
+    }
+
+  if (protocol == NULL)
+    {
+      *errnop = EINVAL;
+      return NSS_STATUS_NOTFOUND;
+    }
+
+  char buf[17 + 3 * sizeof (int) + strlen (protocol) + tablename_len];
+  int olderr = errno;
+
+  snprintf (buf, sizeof (buf), "[port=%d,proto=%s],%s",
+	    number, protocol, tablename_val);
+
+  nis_result *result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS | USE_DGRAM,
+				 NULL, NULL);
+
+  if (result == NULL)
+    {
+      *errnop = ENOMEM;
+      return NSS_STATUS_TRYAGAIN;
+    }
+
+  if (__glibc_unlikely (niserr2nss (result->status) != NSS_STATUS_SUCCESS))
+    {
+      enum nss_status status = niserr2nss (result->status);
+
+      __set_errno (olderr);
+
+      nis_freeresult (result);
+      return status;
+    }
+
+  int parse_res = _nss_nisplus_parse_servent (result, serv, buffer, buflen,
+					      errnop);
+  nis_freeresult (result);
+
+  if (__glibc_unlikely (parse_res < 1))
+    {
+      if (parse_res == -1)
+	{
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+      else
+	{
+	  __set_errno (olderr);
+	  return NSS_STATUS_NOTFOUND;
+	}
+    }
+
+  return NSS_STATUS_SUCCESS;
+}
diff --git a/REORG.TODO/nis/nss_nisplus/nisplus-spwd.c b/REORG.TODO/nis/nss_nisplus/nisplus-spwd.c
new file mode 100644
index 0000000000..e51ba7f969
--- /dev/null
+++ b/REORG.TODO/nis/nss_nisplus/nisplus-spwd.c
@@ -0,0 +1,220 @@
+/* Copyright (C) 1997-2017 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <nss.h>
+#include <errno.h>
+#include <shadow.h>
+#include <string.h>
+#include <libc-lock.h>
+#include <rpcsvc/nis.h>
+
+#include "nss-nisplus.h"
+#include "nisplus-parser.h"
+
+__libc_lock_define_initialized (static, lock)
+
+static nis_result *result;
+
+/* Defined in nisplus-pwd.c.  */
+extern nis_name pwd_tablename_val attribute_hidden;
+extern size_t pwd_tablename_len attribute_hidden;
+extern enum nss_status _nss_pwd_create_tablename (int *errnop);
+
+
+enum nss_status
+_nss_nisplus_setspent (int stayopen)
+{
+  enum nss_status status = NSS_STATUS_SUCCESS;
+  int err;
+
+  __libc_lock_lock (lock);
+
+  if (result != NULL)
+    {
+      nis_freeresult (result);
+      result = NULL;
+    }
+
+  if (pwd_tablename_val == NULL)
+    status = _nss_pwd_create_tablename (&err);
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+enum nss_status
+_nss_nisplus_endspent (void)
+{
+  __libc_lock_lock (lock);
+
+  if (result != NULL)
+    {
+      nis_freeresult (result);
+      result = 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 *errnop)
+{
+  int parse_res;
+
+  /* Get the next entry until we found a correct one. */
+  do
+    {
+      nis_result *saved_res;
+
+      if (result == NULL)
+	{
+	  saved_res = NULL;
+
+	  if (pwd_tablename_val == NULL)
+	    {
+	      enum nss_status status = _nss_pwd_create_tablename (errnop);
+
+	      if (status != NSS_STATUS_SUCCESS)
+		return status;
+	    }
+
+	  result = nis_first_entry (pwd_tablename_val);
+	  if (result == NULL)
+	    {
+	      *errnop = errno;
+	      return NSS_STATUS_TRYAGAIN;
+	    }
+	  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	    return niserr2nss (result->status);
+	}
+      else
+	{
+	  saved_res = result;
+	  result = nis_next_entry (pwd_tablename_val, &result->cookie);
+	  if (result == NULL)
+	    {
+	      *errnop = errno;
+	      return NSS_STATUS_TRYAGAIN;
+	    }
+	  if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
+	    {
+	      nis_freeresult (saved_res);
+	      return niserr2nss (result->status);
+	    }
+	}
+
+      parse_res = _nss_nisplus_parse_spent (result, sp, buffer,
+					    buflen, errnop);
+      if (__glibc_unlikely (parse_res == -1))
+	{
+	  nis_freeresult (result);
+	  result = saved_res;
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+
+      if (saved_res != NULL)
+	nis_freeresult (saved_res);
+    }
+  while (!parse_res);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+enum nss_status
+_nss_nisplus_getspent_r (struct spwd *result, char *buffer, size_t buflen,
+			 int *errnop)
+{
+  int status;
+
+  __libc_lock_lock (lock);
+
+  status = internal_nisplus_getspent_r (result, buffer, buflen, errnop);
+
+  __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 *errnop)
+{
+  int parse_res;
+
+  if (pwd_tablename_val == NULL)
+    {
+      enum nss_status status = _nss_pwd_create_tablename (errnop);
+
+      if (status != NSS_STATUS_SUCCESS)
+	return status;
+    }
+
+  if (name == NULL)
+    {
+      *errnop = EINVAL;
+      return NSS_STATUS_NOTFOUND;
+    }
+
+  nis_result *result;
+  char buf[strlen (name) + 9 + pwd_tablename_len];
+  int olderr = errno;
+
+  snprintf (buf, sizeof (buf), "[name=%s],%s", name, pwd_tablename_val);
+
+  result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS | USE_DGRAM, NULL, NULL);
+
+  if (result == NULL)
+    {
+      *errnop = ENOMEM;
+      return NSS_STATUS_TRYAGAIN;
+    }
+
+  if (__glibc_unlikely (niserr2nss (result->status) != NSS_STATUS_SUCCESS))
+    {
+      enum nss_status status = niserr2nss (result->status);
+
+      __set_errno (olderr);
+
+      nis_freeresult (result);
+      return status;
+    }
+
+  parse_res = _nss_nisplus_parse_spent (result, sp, buffer, buflen, errnop);
+  nis_freeresult (result);
+
+  if (__glibc_unlikely (parse_res < 1))
+    {
+      if (parse_res == -1)
+	{
+	  *errnop = ERANGE;
+	  return NSS_STATUS_TRYAGAIN;
+	}
+      else
+	{
+	  __set_errno (olderr);
+	  return NSS_STATUS_NOTFOUND;
+	}
+    }
+
+  return NSS_STATUS_SUCCESS;
+}
diff --git a/REORG.TODO/nis/rpcsvc/nis.h b/REORG.TODO/nis/rpcsvc/nis.h
new file mode 100644
index 0000000000..933c4d9daf
--- /dev/null
+++ b/REORG.TODO/nis/rpcsvc/nis.h
@@ -0,0 +1,616 @@
+/*
+ * Copyright (c) 2010, Oracle America, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials
+ *       provided with the distribution.
+ *     * Neither the name of the "Oracle America, Inc." nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _RPCSVC_NIS_H
+#define _RPCSVC_NIS_H 1
+
+#include <features.h>
+#include <rpc/rpc.h>
+#include <rpcsvc/nis_tags.h>
+
+__BEGIN_DECLS
+
+/*
+ *	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 : THIS FILE IS NOT GENERATED WITH RPCGEN ! SO YOU HAVE TO
+ *             ADD ALL THE CHANGES ON nis_*.x FILES HERE AGAIN !
+ *
+ *      I have removed all the Solaris internal structs and variables,
+ *      because they are not supported, Sun changed them between various
+ *      releases and they shouldn't be used in user programs.
+ *                                              <kukuk@suse.de>
+ */
+
+
+#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
+#define NIS_PK_DHEXT 4
+
+struct nis_attr {
+	char *zattr_ndx;
+	struct {
+		u_int zattr_val_len;
+		char *zattr_val_val;
+	} zattr_val;
+};
+typedef struct nis_attr nis_attr;
+
+typedef char *nis_name;
+
+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,
+	NIS_BOGUS_OBJ = 0,
+	NIS_NO_OBJ = 1,
+	NIS_DIRECTORY_OBJ = 2,
+	NIS_GROUP_OBJ = 3,
+	NIS_TABLE_OBJ = 4,
+	NIS_ENTRY_OBJ = 5,
+	NIS_LINK_OBJ = 6,
+	NIS_PRIVATE_OBJ = 7
+};
+typedef enum zotypes zotypes;
+
+enum nstype {
+	UNKNOWN = 0,
+	NIS = 1,
+	SUNYP = 2,
+	IVY = 3,
+	DNS = 4,
+	X500 = 5,
+	DNANS = 6,
+	XCHS = 7,
+	CDS = 8,
+};
+typedef enum nstype nstype;
+
+struct oar_mask {
+	uint32_t oa_rights;
+	zotypes oa_otype;
+};
+typedef struct oar_mask oar_mask;
+
+struct endpoint {
+	char *uaddr;
+	char *family;
+	char *proto;
+};
+typedef struct endpoint endpoint;
+
+struct nis_server {
+	nis_name name;
+	struct {
+		u_int ep_len;
+		endpoint *ep_val;
+	} ep;
+	uint32_t key_type;
+	netobj pkey;
+};
+typedef struct nis_server nis_server;
+
+struct directory_obj {
+	nis_name do_name;
+	nstype do_type;
+	struct {
+		u_int do_servers_len;
+		nis_server *do_servers_val;
+	} do_servers;
+	uint32_t do_ttl;
+	struct {
+		u_int do_armask_len;
+		oar_mask *do_armask_val;
+	} do_armask;
+};
+typedef struct directory_obj directory_obj;
+
+#define EN_BINARY 1
+#define EN_CRYPT 2
+#define EN_XDR 4
+#define EN_MODIFIED 8
+#define EN_ASN1 64
+
+struct entry_col {
+	uint32_t ec_flags;
+	struct {
+		u_int ec_value_len;
+		char *ec_value_val;
+	} ec_value;
+};
+typedef struct entry_col entry_col;
+
+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;
+
+struct group_obj {
+	uint32_t gr_flags;
+	struct {
+		u_int gr_members_len;
+		nis_name *gr_members_val;
+	} gr_members;
+};
+typedef struct group_obj group_obj;
+
+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;
+
+#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;
+	uint32_t tc_flags;
+	uint32_t tc_rights;
+};
+typedef struct table_col table_col;
+
+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;
+
+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;
+
+struct nis_oid {
+	uint32_t ctime;
+	uint32_t mtime;
+};
+typedef struct nis_oid nis_oid;
+
+struct nis_object {
+	nis_oid zo_oid;
+	nis_name zo_name;
+	nis_name zo_owner;
+	nis_name zo_group;
+	nis_name zo_domain;
+	uint32_t zo_access;
+	uint32_t zo_ttl;
+	objdata zo_data;
+};
+typedef struct nis_object nis_object;
+
+#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;
+
+struct nis_result {
+	nis_error status;
+	struct {
+		u_int objects_len;
+		nis_object *objects_val;
+	} objects;
+	netobj cookie;
+	uint32_t zticks;
+	uint32_t dticks;
+	uint32_t aticks;
+	uint32_t cticks;
+};
+typedef struct nis_result nis_result;
+
+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;
+
+struct ib_request {
+	nis_name ibr_name;
+	struct {
+		u_int ibr_srch_len;
+		nis_attr *ibr_srch_val;
+	} ibr_srch;
+	uint32_t 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_int ibr_bufsize;
+	netobj ibr_cookie;
+};
+typedef struct ib_request ib_request;
+
+struct ping_args {
+	nis_name dir;
+	uint32_t stamp;
+};
+typedef struct ping_args ping_args;
+
+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;
+
+struct log_entry {
+	uint32_t 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;
+
+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;
+
+struct cp_result {
+	nis_error cp_status;
+	uint32_t cp_zticks;
+	uint32_t cp_dticks;
+};
+typedef struct cp_result cp_result;
+
+struct nis_tag {
+	uint32_t tag_type;
+	char *tag_val;
+};
+typedef struct nis_tag nis_tag;
+
+struct nis_taglist {
+	struct {
+		u_int tags_len;
+		nis_tag *tags_val;
+	} tags;
+};
+typedef struct nis_taglist nis_taglist;
+
+struct dump_args {
+	nis_name da_dir;
+	uint32_t da_time;
+	struct {
+		u_int da_cbhost_len;
+		nis_server *da_cbhost_val;
+	} da_cbhost;
+};
+typedef struct dump_args dump_args;
+
+struct fd_args {
+	nis_name dir_name;
+	nis_name requester;
+};
+typedef struct fd_args fd_args;
+
+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;
+
+/* 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 NIS_WORLD(a, m)        (((a) & (m)) != 0)
+#define NIS_GROUP(a, m)        (((a) & ((m) << 8)) != 0)
+#define NIS_OWNER(a, m)        (((a) & ((m) << 16)) != 0)
+#define NIS_NOBODY(a, m)       (((a) & ((m) << 24)) != 0)
+/*
+ * EOL Alert - The following non-prefixed test macros are
+ * here for backward compatibility, and will be not be present
+ * in future releases - use the NIS_*() macros above.
+ */
+#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
+
+
+/* Prototypes, and extern declarations for the NIS library functions. */
+#include <rpcsvc/nislib.h>
+#endif
+
+/*
+ * 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
+
+#define NIS_PROG 100300
+#define NIS_VERSION 3
+
+#define NIS_LOOKUP 1
+extern  nis_result * nis_lookup_3 (ns_request *, CLIENT *) __THROW;
+extern  nis_result * nis_lookup_3_svc (ns_request *, struct svc_req *) __THROW;
+#define NIS_ADD 2
+extern  nis_result * nis_add_3 (ns_request *, CLIENT *) __THROW;
+extern  nis_result * nis_add_3_svc (ns_request *, struct svc_req *) __THROW;
+#define NIS_MODIFY 3
+extern  nis_result * nis_modify_3 (ns_request *, CLIENT *) __THROW;
+extern  nis_result * nis_modify_3_svc (ns_request *, struct svc_req *) __THROW;
+#define NIS_REMOVE 4
+extern  nis_result * nis_remove_3 (ns_request *, CLIENT *) __THROW;
+extern  nis_result * nis_remove_3_svc (ns_request *, struct svc_req *) __THROW;
+#define NIS_IBLIST 5
+extern  nis_result * nis_iblist_3 (ib_request *, CLIENT *) __THROW;
+extern  nis_result * nis_iblist_3_svc (ib_request *, struct svc_req *) __THROW;
+#define NIS_IBADD 6
+extern  nis_result * nis_ibadd_3 (ib_request *, CLIENT *) __THROW;
+extern  nis_result * nis_ibadd_3_svc (ib_request *, struct svc_req *) __THROW;
+#define NIS_IBMODIFY 7
+extern  nis_result * nis_ibmodify_3 (ib_request *, CLIENT *) __THROW;
+extern  nis_result * nis_ibmodify_3_svc (ib_request *, struct svc_req *)
+     __THROW;
+#define NIS_IBREMOVE 8
+extern  nis_result * nis_ibremove_3 (ib_request *, CLIENT *) __THROW;
+extern  nis_result * nis_ibremove_3_svc (ib_request *, struct svc_req *)
+     __THROW;
+#define NIS_IBFIRST 9
+extern  nis_result * nis_ibfirst_3 (ib_request *, CLIENT *) __THROW;
+extern  nis_result * nis_ibfirst_3_svc (ib_request *, struct svc_req *)
+     __THROW;
+#define NIS_IBNEXT 10
+extern  nis_result * nis_ibnext_3 (ib_request *, CLIENT *) __THROW;
+extern  nis_result * nis_ibnext_3_svc (ib_request *, struct svc_req *) __THROW;
+#define NIS_FINDDIRECTORY 12
+extern  fd_result * nis_finddirectory_3 (fd_args *, CLIENT *) __THROW;
+extern  fd_result * nis_finddirectory_3_svc (fd_args *,
+					     struct svc_req *) __THROW;
+#define NIS_STATUS 14
+extern  nis_taglist * nis_status_3 (nis_taglist *, CLIENT *) __THROW;
+extern  nis_taglist * nis_status_3_svc (nis_taglist *, struct svc_req *)
+     __THROW;
+#define NIS_DUMPLOG 15
+extern  log_result * nis_dumplog_3 (dump_args *, CLIENT *) __THROW;
+extern  log_result * nis_dumplog_3_svc (dump_args *, struct svc_req *) __THROW;
+#define NIS_DUMP 16
+extern  log_result * nis_dump_3 (dump_args *, CLIENT *) __THROW;
+extern  log_result * nis_dump_3_svc (dump_args *, struct svc_req *) __THROW;
+#define NIS_CALLBACK 17
+extern  bool_t * nis_callback_3 (netobj *, CLIENT *) __THROW;
+extern  bool_t * nis_callback_3_svc (netobj *, struct svc_req *) __THROW;
+#define NIS_CPTIME 18
+extern  uint32_t * nis_cptime_3 (nis_name *, CLIENT *) __THROW;
+extern  uint32_t * nis_cptime_3_svc (nis_name *, struct svc_req *) __THROW;
+#define NIS_CHECKPOINT 19
+extern  cp_result * nis_checkpoint_3 (nis_name *, CLIENT *) __THROW;
+extern  cp_result * nis_checkpoint_3_svc (nis_name *, struct svc_req *)
+     __THROW;
+#define NIS_PING 20
+extern  void * nis_ping_3 (ping_args *, CLIENT *) __THROW;
+extern  void * nis_ping_3_svc (ping_args *, struct svc_req *) __THROW;
+#define NIS_SERVSTATE 21
+extern  nis_taglist * nis_servstate_3 (nis_taglist *, CLIENT *) __THROW;
+extern  nis_taglist * nis_servstate_3_svc (nis_taglist *,
+					   struct svc_req *) __THROW;
+#define NIS_MKDIR 22
+extern  nis_error * nis_mkdir_3 (nis_name *, CLIENT *) __THROW;
+extern  nis_error * nis_mkdir_3_svc (nis_name *, struct svc_req *) __THROW;
+#define NIS_RMDIR 23
+extern  nis_error * nis_rmdir_3 (nis_name *, CLIENT *) __THROW;
+extern  nis_error * nis_rmdir_3_svc (nis_name *, struct svc_req *) __THROW;
+#define NIS_UPDKEYS 24
+extern  nis_error * nis_updkeys_3 (nis_name *, CLIENT *) __THROW;
+extern  nis_error * nis_updkeys_3_svc (nis_name *, struct svc_req *) __THROW;
+
+__END_DECLS
+
+#endif /* ! _RPCSVC_NIS_H */
diff --git a/REORG.TODO/nis/rpcsvc/nis.x b/REORG.TODO/nis/rpcsvc/nis.x
new file mode 100644
index 0000000000..e318af29a6
--- /dev/null
+++ b/REORG.TODO/nis/rpcsvc/nis.x
@@ -0,0 +1,474 @@
+%/*
+% * Copyright (c) 2010, Oracle America, Inc.
+% *
+% * Redistribution and use in source and binary forms, with or without
+% * modification, are permitted provided that the following conditions are
+% * met:
+% *
+% *     * Redistributions of source code must retain the above copyright
+% *       notice, this list of conditions and the following disclaimer.
+% *     * Redistributions in binary form must reproduce the above
+% *       copyright notice, this list of conditions and the following
+% *       disclaimer in the documentation and/or other materials
+% *       provided with the distribution.
+% *     * Neither the name of the "Oracle America, Inc." nor the names of its
+% *       contributors may be used to endorse or promote products derived
+% *       from this software without specific prior written permission.
+% *
+% *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+% *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+% *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+% *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+% *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+% *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+% *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+% *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+% *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+% *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+% *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+% *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+% */
+
+#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
+
+/* 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,	/* Generic system error */
+	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		  */
+	uint32_t	zticks;		/* server ticks		  */
+	uint32_t	dticks;		/* DBM ticks.		  */
+	uint32_t	aticks;		/* Cache (accel) ticks	  */
+	uint32_t	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		*/
+	uint32_t	ibr_flags;	/* Optional flags		*/
+	nis_object	ibr_obj<1>;	/* optional object (add/modify) */
+	nis_server	ibr_cbhost<1>;	/* Optional callback info	*/
+	u_int		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 */
+	uint32_t	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 {
+	uint32_t	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	*/
+	uint32_t	cp_zticks;	/* Service 'ticks'		*/
+	uint32_t	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_int).
+ * These are used to report statistics (see tag definitions below)
+ * and to set or reset state variables.
+ */
+struct nis_tag {
+	uint32_t	tag_type;	/* Statistic tag (may vary)	 */
+	string		tag_val<>;	/* Statistic value may also vary */
+};
+
+struct nis_taglist {
+	nis_tag tags<>;			/* List of tags */
+};
+
+struct dump_args {
+	nis_name	da_dir;		/* Directory to dump	*/
+	uint32_t	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	*/
+};
+
+%/*
+% * Structures used for server binding.
+% */
+struct nis_bound_endpoint {
+	endpoint ep;
+	int generation;
+	int rank;
+	uint32_t flags;
+	int hostnum;
+	int epnum;
+	nis_name uaddr;
+	endpoint cbep;
+};
+typedef struct nis_bound_endpoint nis_bound_endpoint;
+
+struct nis_bound_directory {
+	int generation;
+	int min_rank;           /* minimum rank of bound endpoints */
+	int optimal_rank;       /* best possible rank of all endpoints */
+	directory_obj dobj;
+	nis_bound_endpoint BEP<>;
+};
+typedef struct nis_bound_directory nis_bound_directory;
+%#define bep_len BEP.BEP_len
+%#define bep_val BEP.BEP_val
+
+struct nis_active_endpoint {
+	endpoint ep;
+	nis_name hostname;
+	int rank;
+	int uaddr_generation;
+	nis_name uaddr;
+	int cbep_generation;
+	endpoint cbep;
+};
+typedef struct nis_active_endpoint nis_active_endpoint;
+
+%/* defines for nis_bound_endpoint.flags */
+%#define NIS_BOUND 0x1
+%#define NIS_TRANSIENT_ERRORS 0x2
+
+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 */
+		uint32_t    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_int	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 NIS_WORLD(a, m)	(((a) & (m)) != 0)
+%#define NIS_GROUP(a, m)	(((a) & ((m) << 8)) != 0)
+%#define NIS_OWNER(a, m)	(((a) & ((m) << 16)) != 0)
+%#define NIS_NOBODY(a, m)	(((a) & ((m) << 24)) != 0)
+%/*
+% * EOL Alert - The following non-prefixed test macros are
+% * here for backward compatability, and will be not be present
+% * in future releases - use the NIS_*() macros above.
+% */
+%#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/REORG.TODO/nis/rpcsvc/nis_callback.h b/REORG.TODO/nis/rpcsvc/nis_callback.h
new file mode 100644
index 0000000000..6f05728e2a
--- /dev/null
+++ b/REORG.TODO/nis/rpcsvc/nis_callback.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2010, Oracle America, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials
+ *       provided with the distribution.
+ *     * Neither the name of the "Oracle America, Inc." nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _RPCSVC_NIS_CALLBACK_H
+#define _RPCSVC_NIS_CALLBACK_H 1
+
+#include <rpc/rpc.h>
+#include <rpcsvc/nis.h>
+
+__BEGIN_DECLS
+
+typedef nis_object *obj_p;
+
+struct cback_data {
+	struct {
+		u_int entries_len;
+		obj_p *entries_val;
+	} entries;
+};
+typedef struct cback_data cback_data;
+
+#define CB_PROG 100302
+#define CB_VERS 1
+
+#define CBPROC_RECEIVE 1
+extern  bool_t * cbproc_receive_1 (cback_data *, CLIENT *) __THROW;
+extern  bool_t * cbproc_receive_1_svc (cback_data *, struct svc_req *) __THROW;
+
+#define CBPROC_FINISH 2
+extern  void * cbproc_finish_1 (void *, CLIENT *) __THROW;
+extern  void * cbproc_finish_1_svc (void *, struct svc_req *) __THROW;
+
+#define CBPROC_ERROR 3
+extern  void * cbproc_error_1 (nis_error *, CLIENT *) __THROW;
+extern  void * cbproc_error_1_svc (nis_error *, struct svc_req *) __THROW;
+extern int cb_prog_1_freeresult (SVCXPRT *, xdrproc_t, caddr_t) __THROW;
+
+/* the xdr functions */
+
+extern  bool_t xdr_obj_p (XDR *, obj_p*) __THROW;
+extern  bool_t xdr_cback_data (XDR *, cback_data*) __THROW;
+
+__END_DECLS
+
+#endif /* !_RPCVSC_NIS_CALLBACK_H */
diff --git a/REORG.TODO/nis/rpcsvc/nis_callback.x b/REORG.TODO/nis/rpcsvc/nis_callback.x
new file mode 100644
index 0000000000..0fdca9eeec
--- /dev/null
+++ b/REORG.TODO/nis/rpcsvc/nis_callback.x
@@ -0,0 +1,63 @@
+%/*
+% * Copyright (c) 2010, Oracle America, Inc.
+% *
+% * Redistribution and use in source and binary forms, with or without
+% * modification, are permitted provided that the following conditions are
+% * met:
+% *
+% *     * Redistributions of source code must retain the above copyright
+% *       notice, this list of conditions and the following disclaimer.
+% *     * Redistributions in binary form must reproduce the above
+% *       copyright notice, this list of conditions and the following
+% *       disclaimer in the documentation and/or other materials
+% *       provided with the distribution.
+% *     * Neither the name of the "Oracle America, Inc." nor the names of its
+% *       contributors may be used to endorse or promote products derived
+% *       from this software without specific prior written permission.
+% *
+% *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+% *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+% *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+% *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+% *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+% *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+% *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+% *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+% *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+% *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+% *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+% *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+% */
+
+/*
+ *	nis_callback.x
+ */
+
+%#pragma ident	"@(#)nis_callback.x	1.7	94/05/03"
+
+/*
+ * "@(#)zns_cback.x 1.2 90/09/10"
+ *
+ * RPCL description of the Callback Service.
+ */
+
+#ifdef RPC_HDR
+%#include <rpcsvc/nis.h>
+#endif
+#ifdef RPC_XDR
+%#include "nis_clnt.h"
+#endif
+
+typedef nis_object	*obj_p;
+
+struct cback_data {
+	obj_p		entries<>;	/* List of objects */
+};
+
+program CB_PROG {
+	version CB_VERS {
+		bool	CBPROC_RECEIVE(cback_data) = 1;
+		void	CBPROC_FINISH(void) = 2;
+		void	CBPROC_ERROR(nis_error) = 3;
+	} = 1;
+} = 100302;
diff --git a/REORG.TODO/nis/rpcsvc/nis_object.x b/REORG.TODO/nis/rpcsvc/nis_object.x
new file mode 100644
index 0000000000..774b38fa9c
--- /dev/null
+++ b/REORG.TODO/nis/rpcsvc/nis_object.x
@@ -0,0 +1,328 @@
+/*
+ *	nis_object.x
+ *
+ * Copyright (c) 2010, Oracle America, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials
+ *       provided with the distribution.
+ *     * Neither the name of the "Oracle America, Inc." nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+%#pragma ident	"@(#)nis_object.x	1.12	97/11/19"
+
+#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 */
+const NIS_PK_DHEXT     = 4;	/* Extended Diffie-Hellman for RPC-GSS */
+
+/*
+ * 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.
+ *
+ * EOL Alert - The non-prefixed names are present for backward
+ * compatability only, and will not exist in future releases. Use
+ * the NIS_* names for future compatability.
+ */
+
+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)	*/
+
+	NIS_BOGUS_OBJ	= 0,	/* Uninitialized object structure	*/
+	NIS_NO_OBJ	= 1,	/* NULL object (no data)		*/
+	NIS_DIRECTORY_OBJ = 2, /* Directory object describing domain	*/
+	NIS_GROUP_OBJ	= 3,	/* Group object (a list of names)	*/
+	NIS_TABLE_OBJ	= 4,	/* Table object (a database schema)	*/
+	NIS_ENTRY_OBJ	= 5,	/* Entry object (a database record)	*/
+	NIS_LINK_OBJ	= 6,	/* A name link.				*/
+	NIS_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 {
+	uint32_t	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  */
+	uint32_t	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		 */
+	uint32_t   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 {
+	uint32_t	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 {
+	uint32_t	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		   */
+	uint32_t	tc_flags;	/* control flags	   */
+	uint32_t	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 NIS_DIRECTORY_OBJ :
+		struct directory_obj di_data;
+	case NIS_GROUP_OBJ :
+		struct group_obj gr_data;
+	case NIS_TABLE_OBJ :
+		struct table_obj ta_data;
+	case NIS_ENTRY_OBJ:
+		struct entry_obj en_data;
+	case NIS_LINK_OBJ :
+		struct link_obj li_data;
+	case NIS_PRIVATE_OBJ :
+		opaque	po_data<>;
+	case NIS_NO_OBJ :
+		void;
+	case NIS_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 {
+	uint32_t ctime;		/* Time of objects creation	*/
+	uint32_t 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	*/
+	uint32_t zo_access;	/* Access rights (owner, group, world)	*/
+	uint32_t 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/REORG.TODO/nis/rpcsvc/nis_tags.h b/REORG.TODO/nis/rpcsvc/nis_tags.h
new file mode 100644
index 0000000000..c2dc7fd269
--- /dev/null
+++ b/REORG.TODO/nis/rpcsvc/nis_tags.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2010, Oracle America, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials
+ *       provided with the distribution.
+ *     * Neither the name of the "Oracle America, Inc." nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ *	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
+
+#if 0
+#pragma ident	"@(#)nis_tags.h	1.16	96/10/25"
+#endif
+/* from file: zns_tags.h	1.7 */
+
+#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 */
+
+/* Lookup and List function flags (continued) */
+#define	SOFT_LOOKUP	(1<<14)	/* The "old default" return on failure  */
+
+/* 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_READONLY	12	/* Set read only mode		*/
+#define	TAG_READWRITE	14	/* Reset read-write mode	*/
+
+#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/REORG.TODO/nis/rpcsvc/nislib.h b/REORG.TODO/nis/rpcsvc/nislib.h
new file mode 100644
index 0000000000..52fbba4b8f
--- /dev/null
+++ b/REORG.TODO/nis/rpcsvc/nislib.h
@@ -0,0 +1,286 @@
+/* Copyright (C) 1997-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef	__RPCSVC_NISLIB_H__
+#define	__RPCSVC_NISLIB_H__
+
+#include <rpcsvc/nis.h>
+
+__BEGIN_DECLS
+
+typedef const char *const_nis_name;
+
+/* nis_names: These functions are used to locate and manipulate all NIS+
+ * objects except the NIS+ entry objects.
+ *
+ * nis_lookup (name, flags) resolves a NIS+ name and returns a copy of
+ *                          that object  from a NIS+ server.
+ *    const nis_name name: name of the object to be resolved
+ *    unsigned int flags: logically ORing zero or more flags (FOLLOW_LINKS,
+ *                          HARD_LOOKUP, [NO_CACHE], MASTER_ONLY, EXPAND_NAME)
+ *
+ * nis_add (name, obj) adds objects to the NIS+ namespace.
+ *    const nis_name name: fully qualified NIS+ name.
+ *    const nis_object *obj: object members zo_name and zo_domain will be
+ *                           constructed from name.
+ *
+ * nis_remove (name, obj) removes objects from the NIS+ namespace.
+ *    const nis_name name: fully qualified NIS+ name.
+ *    const nis_object *obj: if not NULL, it is assumed to point to a copy
+ *                           of the object being removed. In this case, if
+ *                           the object on the server does not have the same
+ *                           object identifier as the  object  being  passed,
+ *                           the operation will fail with the NIS_NOTSAMEOBJ
+ *                           error.
+ *
+ * nis_modify (name, obj) can change specific attributes of an object
+ *                        that already exists in the namespace.
+ */
+extern nis_result *nis_lookup (const_nis_name name, unsigned int flags)
+     __THROW;
+extern nis_result *nis_add (const_nis_name name, const nis_object *obj)
+     __THROW;
+extern nis_result *nis_remove (const_nis_name name,
+			       const nis_object *obj) __THROW;
+extern nis_result *nis_modify (const_nis_name name,
+			       const nis_object *obj) __THROW;
+
+/* nis_tables: These functions are used to search and modify NIS+ tables.
+ *
+ * nis_list (table_name, flags, callback(table_name, obj, userdata), userdata)
+ *           search a table in the NIS+ namespace.
+ *    const nis_name table_name: indexed name ([xx=yy],table.dir)
+ *    unsigned int flags: logically ORing one or more flags (FOLLOW_LINKS,
+ *                      [FOLLOW_PATH], HARD_LOOKUP, [ALL_RESULTS], [NO_CACHE],
+ *                      MASTER_ONLY, EXPAND_NAME, RETURN_RESULT)
+ *    callback(): callback is an optional pointer to a function that will
+ *                process the ENTRY type objects that are returned from the
+ *                search. If this pointer is NULL, then all entries that match
+ *                the search criteria are returned in the nis_result structure,
+ *                otherwise  this  function  will  be  called once for each
+ *                entry returned.
+ *    void *userdata: passed to callback function along with the returned
+ *                    entry object.
+ *
+ * nis_add_entry (table_name, obj, flags) will add the NIS+ object to the
+ *                                        NIS+ table_name.
+ *    const nis_name table_name
+ *    const nis_object *obj
+ *    unsigned int flags: 0, ADD_OVERWRITE, RETURN_RESULT
+ *
+ * nis_modify_entry (name, obj, flags) modifies an object identified by name.
+ *    const nis_name name: object identifier
+ *    const nis_object *obj: should point to an entry with the EN_MODIFIED
+ *                           flag set in each column that contains new
+ *                           information.
+ *    unsigned int flags: 0, MOD_SAMEOBJ, RETURN_RESULT
+ *
+ * nis_remove_entry (table_name, obj, flags) removes a set of entries
+ *                                 identified by table_name from the table.
+ *    const nis_name table_name: indexed NIS+ name
+ *    const nis_object *obj: if obj is non-null, it is presumed to point to
+ *                           a cached copy of the entry. When the removal is
+ *                           attempted, and the object that would be removed
+ *                           is not the same as the cached object pointed to
+ *                           by object then the operation will fail with an
+ *                           NIS_NOTSAMEOBJ error
+ *    unsigned int flags: 0, REM_MULTIPLE
+ *
+ * nis_first_entry (table_name) fetches entries from a table one at a time.
+ *    const nis_name table_name
+ *
+ * nis_next_entry (table_name, cookie) retrieves the "next" entry from a
+ *                                     table specified by table_name.
+ *    const nis_name table_name:
+ *    const netobj *cookie: The value of cookie from the nis_result structure
+ *                          form the previous call.
+ */
+extern nis_result *nis_list (const_nis_name __name, unsigned int __flags,
+			     int (*__callback)(const_nis_name __table_name,
+					       const nis_object *__obj,
+					       const void *__userdata),
+			     const void *__userdata) __THROW;
+extern nis_result *nis_add_entry (const_nis_name __table_name,
+				  const nis_object *__obj,
+				  unsigned int __flags) __THROW;
+extern nis_result *nis_modify_entry (const_nis_name __name,
+				     const nis_object *__obj,
+				     unsigned int __flags) __THROW;
+extern nis_result *nis_remove_entry (const_nis_name __table_name,
+				     const nis_object *__obj,
+				     unsigned int __flags) __THROW;
+extern nis_result *nis_first_entry (const_nis_name __table_name) __THROW;
+extern nis_result *nis_next_entry (const_nis_name __table_name,
+				   const netobj *__cookie) __THROW;
+/*
+** nis_server
+*/
+extern nis_error nis_mkdir (const_nis_name __dirname,
+			    const nis_server *__machine) __THROW;
+extern nis_error nis_rmdir (const_nis_name __dirname,
+			    const nis_server *__machine) __THROW;
+extern nis_error nis_servstate (const nis_server *__machine,
+				const nis_tag *__tags, int __numtags,
+				nis_tag **__result) __THROW;
+extern nis_error nis_stats (const nis_server *__machine,
+			    const nis_tag *__tags, int __numtags,
+			    nis_tag **__result) __THROW;
+extern void nis_freetags (nis_tag *__tags, int __numtags) __THROW;
+extern nis_server **nis_getservlist (const_nis_name __dirname) __THROW;
+extern void nis_freeservlist (nis_server **__machines) __THROW;
+
+/*
+** nis_subr
+*/
+extern nis_name nis_leaf_of (const_nis_name __name) __THROW;
+extern nis_name nis_leaf_of_r (const_nis_name __name, char *__buffer,
+			       size_t __buflen) __THROW;
+extern nis_name nis_name_of (const_nis_name __name) __THROW;
+extern nis_name nis_name_of_r (const_nis_name __name, char *__buffer,
+			       size_t __buflen) __THROW;
+extern nis_name nis_domain_of (const_nis_name __name) __THROW;
+extern nis_name nis_domain_of_r (const_nis_name __name, char *__buffer,
+				 size_t __buflen) __THROW;
+extern nis_name *nis_getnames (const_nis_name __name) __THROW;
+extern void nis_freenames (nis_name *__namelist) __THROW;
+extern name_pos nis_dir_cmp (const_nis_name __n1, const_nis_name __n2) __THROW;
+extern nis_object *nis_clone_object (const nis_object *__src,
+				     nis_object *__dest) __THROW;
+extern void nis_destroy_object (nis_object *__obj) __THROW;
+extern void nis_print_object (const nis_object *__obj) __THROW;
+
+/*
+** nis_local_names
+*/
+extern nis_name nis_local_group (void) __THROW;
+extern nis_name nis_local_directory (void) __THROW;
+extern nis_name nis_local_principal (void) __THROW;
+extern nis_name nis_local_host (void) __THROW;
+
+/*
+** nis_error
+*/
+extern const char *nis_sperrno (const nis_error __status) __THROW;
+extern void nis_perror (const nis_error __status, const char *__label) __THROW;
+extern void nis_lerror (const nis_error __status, const char *__label) __THROW;
+extern char *nis_sperror (const nis_error status, const char *__label) __THROW;
+extern char *nis_sperror_r (const nis_error __status, const char *__label,
+			    char *__buffer, size_t __buflen) __THROW;
+/*
+** nis_groups
+*/
+extern bool_t nis_ismember (const_nis_name __principal,
+			    const_nis_name __group) __THROW;
+extern nis_error nis_addmember (const_nis_name __member,
+				const_nis_name __group) __THROW;
+extern nis_error nis_removemember (const_nis_name __member,
+				   const_nis_name __group) __THROW;
+extern nis_error nis_creategroup (const_nis_name __group,
+				  unsigned int __flags) __THROW;
+extern nis_error nis_destroygroup (const_nis_name __group) __THROW;
+extern void nis_print_group_entry (const_nis_name __group) __THROW;
+extern nis_error nis_verifygroup (const_nis_name __group) __THROW;
+
+/*
+** nis_ping
+*/
+extern void nis_ping (const_nis_name __dirname, uint32_t __utime,
+		      const nis_object *__dirobj) __THROW;
+extern nis_result *nis_checkpoint (const_nis_name __dirname) __THROW;
+
+/*
+** nis_print (XXX INTERNAL FUNCTIONS, SHOULD NOT BE USED !!)
+*/
+extern void nis_print_result (const nis_result *__result) __THROW;
+extern void nis_print_rights (unsigned int __rights) __THROW;
+extern void nis_print_directory (const directory_obj *__dirobj) __THROW;
+extern void nis_print_group (const group_obj *__grpobj) __THROW;
+extern void nis_print_table (const table_obj *__tblobj) __THROW;
+extern void nis_print_link (const link_obj *__lnkobj) __THROW;
+extern void nis_print_entry (const entry_obj *__enobj) __THROW;
+
+/*
+** nis_file (XXX INTERNAL FUNCTIONS, SHOULD NOT BE USED !!)
+*/
+extern directory_obj *readColdStartFile (void) __THROW;
+extern bool_t writeColdStartFile (const directory_obj *__dirobj) __THROW;
+extern nis_object *nis_read_obj (const char *__obj) __THROW;
+extern bool_t nis_write_obj (const char *__file, const nis_object *__obj) __THROW;
+
+/*
+** nis_clone - (XXX INTERNAL FUNCTIONS, SHOULD NOT BE USED !!)
+*/
+extern directory_obj *nis_clone_directory (const directory_obj *__src,
+					   directory_obj *__dest) __THROW;
+extern nis_result *nis_clone_result (const nis_result *__src,
+				     nis_result *__dest) __THROW;
+
+/* nis_free - nis_freeresult */
+extern void nis_freeresult (nis_result *__result) __THROW;
+/* (XXX THE FOLLOWING ARE INTERNAL FUNCTIONS, SHOULD NOT BE USED !!) */
+extern void nis_free_request (ib_request *__req) __THROW;
+extern void nis_free_directory (directory_obj *__dirobj) __THROW;
+extern void nis_free_object (nis_object *__obj) __THROW;
+
+/* (XXX INTERNAL FUNCTIONS, SHOULD NOT BE USED !!) */
+extern nis_name __nis_default_owner (char *) __THROW;
+extern nis_name __nis_default_group (char *) __THROW;
+extern uint32_t __nis_default_ttl (char *) __THROW;
+extern unsigned int __nis_default_access (char *, unsigned int) __THROW;
+extern fd_result *__nis_finddirectory (directory_obj *, const_nis_name) __THROW;
+extern void __free_fdresult (fd_result *) __THROW;
+extern uint32_t __nis_hash (const void *__keyarg, size_t __len) __THROW;
+
+/* NIS+ cache locking */
+extern int __nis_lock_cache (void) __THROW;
+extern int __nis_unlock_cache (void) __THROW;
+
+/* (XXX INTERNAL FUNCTIONS, ONLY FOR rpc.nisd AND glibc !!) */
+#if defined (NIS_INTERNAL) || defined (_LIBC)
+
+struct dir_binding
+{
+  CLIENT *clnt;                  /* RPC CLIENT handle */
+  nis_server *server_val;        /* List of servers */
+  unsigned int server_len;       /* # of servers */
+  unsigned int server_used;      /* Which server we are bind in the moment ? */
+  unsigned int current_ep;       /* Which endpoint of the server are in use? */
+  unsigned int trys;             /* How many server have we tried ? */
+  unsigned int class;            /* From which class is server_val ? */
+  bool_t master_only;            /* Is only binded to the master */
+  bool_t use_auth;               /* Do we use AUTH ? */
+  bool_t use_udp;                /* Do we use UDP ? */
+  struct sockaddr_in addr;       /* Server's IP address */
+  int socket;                    /* Server's local socket */
+};
+typedef struct dir_binding dir_binding;
+
+extern nis_error __nisbind_create (dir_binding *, const nis_server *,
+				   unsigned int, unsigned int, unsigned int,
+				   unsigned int) __THROW;
+extern nis_error __nisbind_connect (dir_binding *) __THROW;
+extern nis_error __nisbind_next (dir_binding *) __THROW;
+extern void __nisbind_destroy (dir_binding *) __THROW;
+extern nis_error __nisfind_server (const_nis_name, int, directory_obj **,
+				   dir_binding *, unsigned int) __THROW;
+
+#endif
+
+__END_DECLS
+
+#endif	/* __RPCSVC_NISLIB_H__ */
diff --git a/REORG.TODO/nis/rpcsvc/yp.h b/REORG.TODO/nis/rpcsvc/yp.h
new file mode 100644
index 0000000000..968b74c42e
--- /dev/null
+++ b/REORG.TODO/nis/rpcsvc/yp.h
@@ -0,0 +1,339 @@
+/*
+ * Copyright (c) 2010, Oracle America, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials
+ *       provided with the distribution.
+ *     * Neither the name of the "Oracle America, Inc." nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __RPCSVC_YP_H__
+#define __RPCSVC_YP_H__
+
+#include <features.h>
+#include <rpc/rpc.h>
+
+#define YPMAXRECORD 1024
+#define YPMAXDOMAIN 64
+#define YPMAXMAP 64
+#define YPMAXPEER 64
+
+enum ypstat {
+	YP_TRUE = 1,
+	YP_NOMORE = 2,
+	YP_FALSE = 0,
+	YP_NOMAP = -1,
+	YP_NODOM = -2,
+	YP_NOKEY = -3,
+	YP_BADOP = -4,
+	YP_BADDB = -5,
+	YP_YPERR = -6,
+	YP_BADARGS = -7,
+	YP_VERS = -8,
+};
+typedef enum ypstat ypstat;
+
+enum ypxfrstat {
+	YPXFR_SUCC = 1,
+	YPXFR_AGE = 2,
+	YPXFR_NOMAP = -1,
+	YPXFR_NODOM = -2,
+	YPXFR_RSRC = -3,
+	YPXFR_RPC = -4,
+	YPXFR_MADDR = -5,
+	YPXFR_YPERR = -6,
+	YPXFR_BADARGS = -7,
+	YPXFR_DBM = -8,
+	YPXFR_FILE = -9,
+	YPXFR_SKEW = -10,
+	YPXFR_CLEAR = -11,
+	YPXFR_FORCE = -12,
+	YPXFR_XFRERR = -13,
+	YPXFR_REFUSED = -14,
+};
+typedef enum ypxfrstat ypxfrstat;
+
+typedef char *domainname;
+typedef char *mapname;
+typedef char *peername;
+
+typedef struct {
+  u_int keydat_len;
+  char *keydat_val;
+} keydat;
+
+typedef struct {
+  u_int valdat_len;
+  char *valdat_val;
+} valdat;
+
+struct ypmap_parms {
+  domainname domain;
+  mapname map;
+  u_int ordernum;
+  peername peer;
+};
+typedef struct ypmap_parms ypmap_parms;
+
+struct ypreq_key {
+  domainname domain;
+  mapname map;
+  keydat key;
+};
+typedef struct ypreq_key ypreq_key;
+
+struct ypreq_nokey {
+  domainname domain;
+  mapname map;
+};
+typedef struct ypreq_nokey ypreq_nokey;
+
+struct ypreq_xfr {
+  ypmap_parms map_parms;
+  u_int transid;
+  u_int prog;
+  u_int port;
+};
+typedef struct ypreq_xfr ypreq_xfr;
+
+struct ypresp_val {
+  ypstat stat;
+  valdat val;
+};
+typedef struct ypresp_val ypresp_val;
+
+struct ypresp_key_val {
+  ypstat stat;
+#ifdef STUPID_SUN_BUG
+  /* This is the form as distributed by Sun.  But even the Sun NIS
+     servers expect the values in the other order.  So their
+     implementation somehow must change the order internally.  We
+     don't want to follow this bad example since the user should be
+     able to use rpcgen on this file.  */
+  keydat key;
+  valdat val;
+#else
+  valdat val;
+  keydat key;
+#endif
+};
+typedef struct ypresp_key_val ypresp_key_val;
+
+struct ypresp_master {
+  ypstat stat;
+  peername peer;
+};
+typedef struct ypresp_master ypresp_master;
+
+struct ypresp_order {
+  ypstat stat;
+  u_int ordernum;
+};
+typedef struct ypresp_order ypresp_order;
+
+struct ypresp_all {
+  bool_t more;
+  union {
+    ypresp_key_val val;
+  } ypresp_all_u;
+};
+typedef struct ypresp_all ypresp_all;
+
+struct ypresp_xfr {
+  u_int transid;
+  ypxfrstat xfrstat;
+};
+typedef struct ypresp_xfr ypresp_xfr;
+
+struct ypmaplist {
+  mapname map;
+  struct ypmaplist *next;
+};
+typedef struct ypmaplist ypmaplist;
+
+struct ypresp_maplist {
+  ypstat stat;
+  ypmaplist *maps;
+};
+typedef struct ypresp_maplist ypresp_maplist;
+
+enum yppush_status {
+  YPPUSH_SUCC = 1,
+  YPPUSH_AGE = 2,
+  YPPUSH_NOMAP = -1,
+  YPPUSH_NODOM = -2,
+  YPPUSH_RSRC = -3,
+  YPPUSH_RPC = -4,
+  YPPUSH_MADDR = -5,
+  YPPUSH_YPERR = -6,
+  YPPUSH_BADARGS = -7,
+  YPPUSH_DBM = -8,
+  YPPUSH_FILE = -9,
+  YPPUSH_SKEW = -10,
+  YPPUSH_CLEAR = -11,
+  YPPUSH_FORCE = -12,
+  YPPUSH_XFRERR = -13,
+  YPPUSH_REFUSED = -14,
+};
+typedef enum yppush_status yppush_status;
+
+struct yppushresp_xfr {
+  u_int transid;
+  yppush_status status;
+};
+typedef struct yppushresp_xfr yppushresp_xfr;
+
+enum ypbind_resptype {
+  YPBIND_SUCC_VAL = 1,
+  YPBIND_FAIL_VAL = 2,
+};
+typedef enum ypbind_resptype ypbind_resptype;
+
+struct ypbind_binding {
+  char ypbind_binding_addr[4];
+  char ypbind_binding_port[2];
+};
+typedef struct ypbind_binding ypbind_binding;
+
+struct ypbind_resp {
+  ypbind_resptype ypbind_status;
+  union {
+    u_int ypbind_error;
+    ypbind_binding ypbind_bindinfo;
+  } ypbind_resp_u;
+};
+typedef struct ypbind_resp ypbind_resp;
+
+#define YPBIND_ERR_ERR 1
+#define YPBIND_ERR_NOSERV 2
+#define YPBIND_ERR_RESC 3
+
+struct ypbind_setdom {
+  domainname ypsetdom_domain;
+  ypbind_binding ypsetdom_binding;
+  u_int ypsetdom_vers;
+};
+typedef struct ypbind_setdom ypbind_setdom;
+
+__BEGIN_DECLS
+
+#define YPPROG 100004
+#define YPVERS 2
+
+#define YPPROC_NULL 0
+extern  void *ypproc_null_2 (void *, CLIENT *);
+extern  void *ypproc_null_2_svc (void *, struct svc_req *);
+#define YPPROC_DOMAIN 1
+extern  bool_t *ypproc_domain_2 (domainname *, CLIENT *);
+extern  bool_t *ypproc_domain_2_svc (domainname *, struct svc_req *);
+#define YPPROC_DOMAIN_NONACK 2
+extern  bool_t *ypproc_domain_nonack_2 (domainname *, CLIENT *);
+extern  bool_t *ypproc_domain_nonack_2_svc (domainname *, struct svc_req *);
+#define YPPROC_MATCH 3
+extern  ypresp_val *ypproc_match_2 (ypreq_key *, CLIENT *);
+extern  ypresp_val *ypproc_match_2_svc (ypreq_key *, struct svc_req *);
+#define YPPROC_FIRST 4
+extern  ypresp_key_val *ypproc_first_2 (ypreq_key *, CLIENT *);
+extern  ypresp_key_val *ypproc_first_2_svc (ypreq_key *, struct svc_req *);
+#define YPPROC_NEXT 5
+extern  ypresp_key_val *ypproc_next_2 (ypreq_key *, CLIENT *);
+extern  ypresp_key_val *ypproc_next_2_svc (ypreq_key *, struct svc_req *);
+#define YPPROC_XFR 6
+extern  ypresp_xfr *ypproc_xfr_2 (ypreq_xfr *, CLIENT *);
+extern  ypresp_xfr *ypproc_xfr_2_svc (ypreq_xfr *, struct svc_req *);
+#define YPPROC_CLEAR 7
+extern  void *ypproc_clear_2 (void *, CLIENT *);
+extern  void *ypproc_clear_2_svc (void *, struct svc_req *);
+#define YPPROC_ALL 8
+extern  ypresp_all *ypproc_all_2 (ypreq_nokey *, CLIENT *);
+extern  ypresp_all *ypproc_all_2_svc (ypreq_nokey *, struct svc_req *);
+#define YPPROC_MASTER 9
+extern  ypresp_master *ypproc_master_2 (ypreq_nokey *, CLIENT *);
+extern  ypresp_master *ypproc_master_2_svc (ypreq_nokey *, struct svc_req *);
+#define YPPROC_ORDER 10
+extern  ypresp_order *ypproc_order_2 (ypreq_nokey *, CLIENT *);
+extern  ypresp_order *ypproc_order_2_svc (ypreq_nokey *, struct svc_req *);
+#define YPPROC_MAPLIST 11
+extern  ypresp_maplist *ypproc_maplist_2 (domainname *, CLIENT *);
+extern  ypresp_maplist *ypproc_maplist_2_svc (domainname *, struct svc_req *);
+extern int ypprog_2_freeresult (SVCXPRT *, xdrproc_t, caddr_t);
+
+
+#define YPPUSH_XFRRESPPROG (0x40000000)
+#define YPPUSH_XFRRESPVERS 1
+
+#define YPPUSHPROC_NULL 0
+extern  void *yppushproc_null_1 (void *, CLIENT *);
+extern  void *yppushproc_null_1_svc (void *, struct svc_req *);
+#define YPPUSHPROC_XFRRESP 1
+extern  void *yppushproc_xfrresp_1 (yppushresp_xfr *, CLIENT *);
+extern  void *yppushproc_xfrresp_1_svc (yppushresp_xfr *, struct svc_req *);
+extern int yppush_xfrrespprog_1_freeresult (SVCXPRT *, xdrproc_t, caddr_t);
+
+
+#define YPBINDPROG 100007
+#define YPBINDVERS 2
+
+#define YPBINDPROC_NULL 0
+extern  void *ypbindproc_null_2 (void *, CLIENT *);
+extern  void *ypbindproc_null_2_svc (void *, struct svc_req *);
+#define YPBINDPROC_DOMAIN 1
+extern  ypbind_resp *ypbindproc_domain_2 (domainname *, CLIENT *);
+extern  ypbind_resp *ypbindproc_domain_2_svc (domainname *, struct svc_req *);
+#define YPBINDPROC_SETDOM 2
+extern  void *ypbindproc_setdom_2 (ypbind_setdom *, CLIENT *);
+extern  void *ypbindproc_setdom_2_svc (ypbind_setdom *, struct svc_req *);
+extern int ypbindprog_2_freeresult (SVCXPRT *, xdrproc_t, caddr_t);
+
+
+extern  bool_t xdr_ypstat (XDR *, ypstat*);
+extern  bool_t xdr_ypxfrstat (XDR *, ypxfrstat*);
+extern  bool_t xdr_domainname (XDR *, domainname*);
+extern  bool_t xdr_mapname (XDR *, mapname*);
+extern  bool_t xdr_peername (XDR *, peername*);
+extern  bool_t xdr_keydat (XDR *, keydat*);
+extern  bool_t xdr_valdat (XDR *, valdat*);
+extern  bool_t xdr_ypmap_parms (XDR *, ypmap_parms*);
+extern  bool_t xdr_ypreq_key (XDR *, ypreq_key*);
+extern  bool_t xdr_ypreq_nokey (XDR *, ypreq_nokey*);
+extern  bool_t xdr_ypreq_xfr (XDR *, ypreq_xfr*);
+extern  bool_t xdr_ypresp_val (XDR *, ypresp_val*);
+extern  bool_t xdr_ypresp_key_val (XDR *, ypresp_key_val*);
+extern  bool_t xdr_ypresp_master (XDR *, ypresp_master*);
+extern  bool_t xdr_ypresp_order (XDR *, ypresp_order*);
+extern  bool_t xdr_ypresp_all (XDR *, ypresp_all*);
+extern  bool_t xdr_ypresp_xfr (XDR *, ypresp_xfr*);
+extern  bool_t xdr_ypmaplist (XDR *, ypmaplist*);
+extern  bool_t xdr_ypresp_maplist (XDR *, ypresp_maplist*);
+extern  bool_t xdr_yppush_status (XDR *, yppush_status*);
+extern  bool_t xdr_yppushresp_xfr (XDR *, yppushresp_xfr*);
+extern  bool_t xdr_ypbind_resptype (XDR *, ypbind_resptype*);
+extern  bool_t xdr_ypbind_binding (XDR *, ypbind_binding*);
+extern  bool_t xdr_ypbind_resp (XDR *, ypbind_resp*);
+extern  bool_t xdr_ypbind_setdom (XDR *, ypbind_setdom*);
+
+__END_DECLS
+
+#endif /* !__RPCSVC_YP_H__ */
diff --git a/REORG.TODO/nis/rpcsvc/yp.x b/REORG.TODO/nis/rpcsvc/yp.x
new file mode 100644
index 0000000000..269ae6f606
--- /dev/null
+++ b/REORG.TODO/nis/rpcsvc/yp.x
@@ -0,0 +1,311 @@
+/* @(#)yp.x	2.1 88/08/01 4.0 RPCSRC */
+
+/*
+ * Copyright (c) 2010, Oracle America, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials
+ *       provided with the distribution.
+ *     * Neither the name of the "Oracle America, Inc." nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Protocol description file for the Yellow Pages Service
+ */
+
+const YPMAXRECORD = 1024;
+const YPMAXDOMAIN = 64;
+const YPMAXMAP = 64;
+const YPMAXPEER = 64;
+
+
+enum ypstat {
+	YP_TRUE		=  1,
+	YP_NOMORE	=  2,
+	YP_FALSE	=  0,
+	YP_NOMAP	= -1,
+	YP_NODOM	= -2,
+	YP_NOKEY	= -3,
+	YP_BADOP	= -4,
+	YP_BADDB	= -5,
+	YP_YPERR	= -6,
+	YP_BADARGS	= -7,
+	YP_VERS		= -8
+};
+
+
+enum ypxfrstat {
+	YPXFR_SUCC	=  1,
+	YPXFR_AGE	=  2,
+	YPXFR_NOMAP	= -1,
+	YPXFR_NODOM	= -2,
+	YPXFR_RSRC	= -3,
+	YPXFR_RPC	= -4,
+	YPXFR_MADDR	= -5,
+	YPXFR_YPERR	= -6,
+	YPXFR_BADARGS	= -7,
+	YPXFR_DBM	= -8,
+	YPXFR_FILE	= -9,
+	YPXFR_SKEW	= -10,
+	YPXFR_CLEAR	= -11,
+	YPXFR_FORCE	= -12,
+	YPXFR_XFRERR	= -13,
+	YPXFR_REFUSED	= -14
+};
+
+
+typedef string domainname<YPMAXDOMAIN>;
+typedef string mapname<YPMAXMAP>;
+typedef string peername<YPMAXPEER>;
+typedef opaque keydat<YPMAXRECORD>;
+typedef opaque valdat<YPMAXRECORD>;
+
+
+struct ypmap_parms {
+	domainname domain;
+	mapname map;
+	unsigned int ordernum;
+	peername peer;
+};
+
+struct ypreq_key {
+	domainname domain;
+	mapname map;
+	keydat key;
+};
+
+struct ypreq_nokey {
+	domainname domain;
+	mapname map;
+};
+
+struct ypreq_xfr {
+	ypmap_parms map_parms;
+	unsigned int transid;
+	unsigned int prog;
+	unsigned int port;
+};
+
+
+struct ypresp_val {
+	ypstat stat;
+	valdat val;
+};
+
+struct ypresp_key_val {
+	ypstat stat;
+#ifdef STUPID_SUN_BUG
+	/* This is the form as distributed by Sun.  But even the Sun NIS
+	   servers expect the values in the other order.  So their
+	   implementation somehow must change the order internally.  We
+	   don't want to follow this bad example since the user should be
+	   able to use rpcgen on this file.  */
+	keydat key;
+	valdat val;
+#else
+	valdat val;
+	keydat key;
+#endif
+};
+
+
+struct ypresp_master {
+	ypstat stat;
+	peername peer;
+};
+
+struct ypresp_order {
+	ypstat stat;
+	unsigned int ordernum;
+};
+
+union ypresp_all switch (bool more) {
+case TRUE:
+	ypresp_key_val val;
+case FALSE:
+	void;
+};
+
+struct ypresp_xfr {
+	unsigned int transid;
+	ypxfrstat xfrstat;
+};
+
+struct ypmaplist {
+	mapname map;
+	ypmaplist *next;
+};
+
+struct ypresp_maplist {
+	ypstat stat;
+	ypmaplist *maps;
+};
+
+enum yppush_status {
+	YPPUSH_SUCC	=  1,	/* Success */
+	YPPUSH_AGE	=  2,	/* Master's version not newer */
+	YPPUSH_NOMAP	= -1,	/* Can't find server for map */
+	YPPUSH_NODOM	= -2,	/* Domain not supported */
+	YPPUSH_RSRC	= -3,	/* Local resource alloc failure */
+	YPPUSH_RPC	= -4,	/* RPC failure talking to server */
+	YPPUSH_MADDR	= -5,	/* Can't get master address */
+	YPPUSH_YPERR	= -6,	/* YP server/map db error */
+	YPPUSH_BADARGS	= -7,	/* Request arguments bad */
+	YPPUSH_DBM	= -8,	/* Local dbm operation failed */
+	YPPUSH_FILE	= -9,	/* Local file I/O operation failed */
+	YPPUSH_SKEW	= -10,	/* Map version skew during transfer */
+	YPPUSH_CLEAR	= -11,	/* Can't send "Clear" req to local ypserv */
+	YPPUSH_FORCE	= -12,	/* No local order number in map  use -f flag. */
+	YPPUSH_XFRERR	= -13,	/* ypxfr error */
+	YPPUSH_REFUSED	= -14	/* Transfer request refused by ypserv */
+};
+
+struct yppushresp_xfr {
+	unsigned transid;
+	yppush_status status;
+};
+
+/*
+ * Response structure and overall result status codes.  Success and failure
+ * represent two separate response message types.
+ */
+
+enum ypbind_resptype {
+	YPBIND_SUCC_VAL = 1,
+	YPBIND_FAIL_VAL = 2
+};
+
+struct ypbind_binding {
+    opaque ypbind_binding_addr[4]; /* In network order */
+    opaque ypbind_binding_port[2]; /* In network order */
+};
+
+union ypbind_resp switch (ypbind_resptype ypbind_status) {
+case YPBIND_FAIL_VAL:
+	unsigned ypbind_error;
+case YPBIND_SUCC_VAL:
+	ypbind_binding ypbind_bindinfo;
+};
+
+/* Detailed failure reason codes for response field ypbind_error*/
+
+const YPBIND_ERR_ERR    = 1;	/* Internal error */
+const YPBIND_ERR_NOSERV = 2;	/* No bound server for passed domain */
+const YPBIND_ERR_RESC   = 3;	/* System resource allocation failure */
+
+
+/*
+ * Request data structure for ypbind "Set domain" procedure.
+ */
+struct ypbind_setdom {
+	domainname ypsetdom_domain;
+	ypbind_binding ypsetdom_binding;
+	unsigned ypsetdom_vers;
+};
+
+
+/*
+ * YP access protocol
+ */
+program YPPROG {
+	version YPVERS {
+		void
+		YPPROC_NULL(void) = 0;
+
+		bool
+		YPPROC_DOMAIN(domainname) = 1;
+
+		bool
+		YPPROC_DOMAIN_NONACK(domainname) = 2;
+
+		ypresp_val
+		YPPROC_MATCH(ypreq_key) = 3;
+
+		ypresp_key_val
+		YPPROC_FIRST(ypreq_key) = 4;
+
+		ypresp_key_val
+		YPPROC_NEXT(ypreq_key) = 5;
+
+		ypresp_xfr
+		YPPROC_XFR(ypreq_xfr) = 6;
+
+		void
+		YPPROC_CLEAR(void) = 7;
+
+		ypresp_all
+		YPPROC_ALL(ypreq_nokey) = 8;
+
+		ypresp_master
+		YPPROC_MASTER(ypreq_nokey) = 9;
+
+		ypresp_order
+		YPPROC_ORDER(ypreq_nokey) = 10;
+
+		ypresp_maplist
+		YPPROC_MAPLIST(domainname) = 11;
+	} = 2;
+} = 100004;
+
+
+/*
+ * YPPUSHPROC_XFRRESP is the callback routine for result of YPPROC_XFR
+ */
+program YPPUSH_XFRRESPPROG {
+	version YPPUSH_XFRRESPVERS {
+		void
+		YPPUSHPROC_NULL(void) = 0;
+
+#ifdef STUPID_SUN_BUG
+		/* This is the form as distributed by Sun.  But even
+		   the Sun NIS servers expect the values in the other
+		   order.  So their implementation somehow must change
+		   the order internally.  We don't want to follow this
+		   bad example since the user should be able to use
+		   rpcgen on this file.  */
+		yppushresp_xfr
+		YPPUSHPROC_XFRRESP(void) = 1;
+#else
+		void
+		YPPUSHPROC_XFRRESP(yppushresp_xfr) = 1;
+#endif
+	} = 1;
+} = 0x40000000;	/* transient: could be anything up to 0x5fffffff */
+
+/*
+ * YP binding protocol
+ */
+program YPBINDPROG {
+	version YPBINDVERS {
+		void
+		YPBINDPROC_NULL(void) = 0;
+
+		ypbind_resp
+		YPBINDPROC_DOMAIN(domainname) = 1;
+
+		void
+		YPBINDPROC_SETDOM(ypbind_setdom) = 2;
+	} = 2;
+} = 100007;
diff --git a/REORG.TODO/nis/rpcsvc/yp_prot.h b/REORG.TODO/nis/rpcsvc/yp_prot.h
new file mode 100644
index 0000000000..ae0db3688e
--- /dev/null
+++ b/REORG.TODO/nis/rpcsvc/yp_prot.h
@@ -0,0 +1,366 @@
+/*
+ * This file contains symbols and structures defining the rpc protocol
+ * between the NIS clients and the NIS servers.  The servers
+ * are the NIS database servers, and the NIS binders.
+ */
+
+#ifndef _RPCSVC_YP_PROT_H
+#define _RPCSVC_YP_PROT_H
+
+#include <features.h>
+
+#include <rpc/rpc.h>
+#include <rpcsvc/ypclnt.h>
+
+__BEGIN_DECLS
+
+/*
+ * The following procedures are supported by the protocol:
+ *
+ * YPPROC_NULL() returns () takes nothing, returns nothing.  This indicates
+ * that the NIS server is alive.
+ *
+ * YPPROC_DOMAIN (char *) returns (bool_t) TRUE.  Indicates that the
+ * responding NIS server does serve the named domain; FALSE indicates no
+ * support.
+ *
+ * YPPROC_DOMAIN_NONACK (char *) returns (TRUE) if the NIS server does serve
+ * the named domain, otherwise does not return.  Used in the broadcast case.
+ *
+ * YPPROC_MATCH (struct ypreq_key) returns (struct ypresp_val).  Returns the
+ * right-hand value for a passed left-hand key, within a named map and
+ * domain.
+ *
+ * YPPROC_FIRST (struct ypreq_nokey) returns (struct ypresp_key_val).
+ * Returns the first key-value pair from a named domain and map.
+ *
+ * YPPROC_NEXT (struct ypreq_key) returns (struct ypresp_key_val).  Returns
+ * the key-value pair following a passed key-value pair within a named
+ * domain and map.
+ *
+ * YPPROC_XFR (struct ypreq_xfr) returns nothing.  Indicates to a server that
+ * a map should be updated.
+ *
+ * YPPROC_CLEAR	takes nothing, returns nothing.  Instructs a NIS server to
+ * close the current map, so that old versions of the disk file don't get
+ * held open.
+ *
+ * YPPROC_ALL (struct ypreq_nokey), returns
+ * 	union switch (bool_t more) {
+ *		TRUE:	(struct ypresp_key_val);
+ *		FALSE:	(struct) {};
+ *	}
+ *
+ * YPPROC_MASTER (struct ypreq_nokey), returns (ypresp_master)
+ *
+ * YPPROC_ORDER (struct ypreq_nokey), returns (ypresp_order)
+ *
+ * YPPROC_MAPLIST (char *), returns (struct ypmaplist *)
+ */
+
+/* Program and version symbols, magic numbers */
+
+#define YPPROG		100004
+#define YPVERS		2
+#define YPVERS_ORIG	1
+#define YPMAXRECORD	1024
+#define YPMAXDOMAIN	64 /* XXX orig. yp_prot.h defines 256 */
+#define YPMAXMAP	64
+#define YPMAXPEER	64 /* XXX orig. yp_prot.h defines 256 */
+
+/* byte size of a large NIS packet */
+#define YPMSGSZ		1600
+
+typedef struct {
+  u_int keydat_len;
+  char *keydat_val;
+} keydat_t;
+
+typedef struct {
+  u_int valdat_len;
+  char *valdat_val;
+} valdat_t;
+
+struct ypmap_parms {
+  char *domain;			/* Null string means not available */
+  char *map;			/* Null string means not available */
+  unsigned int ordernum;	/* 0 means not available */
+  char *owner;			/* Null string means not available */
+};
+
+/*
+ * Request parameter structures
+ */
+
+struct ypreq_key {
+  const char *domain;
+  const char *map;
+  keydat_t keydat;
+};
+
+struct ypreq_nokey {
+  char *domain;
+  char *map;
+};
+
+struct ypreq_xfr {
+  struct ypmap_parms map_parms;
+  u_int transid;
+  u_int proto;
+  u_int port;
+};
+
+#define ypxfr_domain map_parms.domain
+#define ypxfr_map map_parms.map
+#define ypxfr_ordernum map_parms.ordernum
+#define ypxfr_owner map_parms.owner
+
+/* Return status values */
+
+enum ypstat {
+  YP_TRUE = 1,		/* General purpose success code */
+#define YP_TRUE YP_TRUE
+  YP_NOMORE = 2,	/* No more entries in map */
+#define YP_NOMORE YP_NOMORE
+  YP_FALSE = 0,		/* General purpose failure code */
+#define YP_FALSE YP_FALSE
+  YP_NOMAP = -1,	/* No such map in domain */
+#define YP_NOMAP YP_NOMAP
+  YP_NODOM = -2,	/* Domain not supported */
+#define YP_NODOM YP_NODOM
+  YP_NOKEY = -3,	/* No such key in map */
+#define YP_NOKEY YP_NOKEY
+  YP_BADOP = -4,	/* Invalid operation */
+#define YP_BADOP YP_BADOP
+  YP_BADDB = -5,	/* Server data base is bad */
+#define YP_BADDB YP_BADDB
+  YP_YPERR = -6,	/* NIS server error */
+#define YP_YPERR YP_YPERR
+  YP_BADARGS = -7,	/* Request arguments bad */
+#define YP_BADARGS YP_BADARGS
+  YP_VERS = -8,		/* NIS server version mismatch - server can't supply
+			   requested service. */
+#define YP_VERS YP_VERS
+};
+
+/*
+ * Response parameter structures
+ */
+
+typedef enum ypstat ypstat;
+
+struct ypresp_val {
+  ypstat status;
+  valdat_t valdat;
+};
+
+struct ypresp_key_val {
+  ypstat status;
+#ifdef STUPID_SUN_BUG
+  /* This is the form as distributed by Sun.  But even the Sun NIS
+     servers expect the values in the other order.  So their
+     implementation somehow must change the order internally.  We
+     don't want to follow this bad example since the user should be
+     able to use rpcgen on this file.  */
+  keydat_t keydat;
+  valdat_t valdat;
+#else
+  valdat_t valdat;
+  keydat_t keydat;
+#endif
+};
+
+struct ypresp_master {
+  ypstat status;
+  char *master;
+};
+
+struct ypresp_order {
+  ypstat status;
+  u_int ordernum;
+};
+
+struct ypmaplist {
+  char *map;
+#define ypml_name map
+  struct ypmaplist *next;
+#define ypml_next next
+};
+
+struct ypresp_maplist {
+  ypstat status;
+  struct ypmaplist *list;
+};
+
+/*
+ * Procedure symbols.  YPPROC_NULL, YPPROC_DOMAIN, and YPPROC_DOMAIN_NONACK
+ * must keep the same values (0, 1, and 2) that they had in the first version
+ * of the protocol.
+ */
+
+#define YPPROC_NULL	0
+#define YPPROC_DOMAIN	1
+#define YPPROC_DOMAIN_NONACK 2
+#define YPPROC_MATCH	3
+#define YPPROC_FIRST	4
+#define YPPROC_NEXT	5
+#define YPPROC_XFR	6
+#define YPPROC_CLEAR	7
+#define YPPROC_ALL	8
+#define YPPROC_MASTER	9
+#define YPPROC_ORDER	10
+#define YPPROC_MAPLIST	11
+#define	YPPROC_NEWXFR	12
+
+/*
+ *		Protocol between clients and NIS binder servers
+ */
+
+/*
+ * The following procedures are supported by the protocol:
+ *
+ * YPBINDPROC_NULL() returns ()
+ * 	takes nothing, returns nothing
+ *
+ * YPBINDPROC_DOMAIN takes (char *) returns (struct ypbind_resp)
+ *
+ * YPBINDPROC_SETDOM takes (struct ypbind_setdom) returns nothing
+ */
+
+/* Program and version symbols, magic numbers */
+
+#define YPBINDPROG		100007
+#define YPBINDVERS		2
+#define YPBINDVERS_ORIG		1
+
+/* Procedure symbols */
+
+#define YPBINDPROC_NULL		0
+#define YPBINDPROC_DOMAIN	1
+#define YPBINDPROC_SETDOM	2
+/*
+ * Response structure and overall result status codes.  Success and failure
+ * represent two separate response message types.
+ */
+
+enum ypbind_resptype {YPBIND_SUCC_VAL = 1, YPBIND_FAIL_VAL = 2};
+
+struct ypbind_binding {
+  struct in_addr ypbind_binding_addr;	        /* In network order */
+  unsigned short int ypbind_binding_port;	/* In network order */
+};
+
+struct ypbind_resp {
+  enum ypbind_resptype ypbind_status;
+  union {
+    u_int ypbind_error;
+    struct ypbind_binding ypbind_bindinfo;
+  } ypbind_respbody;
+};
+
+
+/* Detailed failure reason codes for response field ypbind_error*/
+
+#define YPBIND_ERR_ERR 1		/* Internal error */
+#define YPBIND_ERR_NOSERV 2		/* No bound server for passed domain */
+#define YPBIND_ERR_RESC 3		/* System resource allocation failure */
+
+/*
+ * Request data structure for ypbind "Set domain" procedure.
+ */
+struct ypbind_setdom {
+  char *ypsetdom_domain;
+  struct ypbind_binding ypsetdom_binding;
+  u_int ypsetdom_vers;
+};
+#define ypsetdom_addr ypsetdom_binding.ypbind_binding_addr
+#define ypsetdom_port ypsetdom_binding.ypbind_binding_port
+
+/*
+ *		Protocol between clients (ypxfr, only) and yppush
+ *		yppush speaks a protocol in the transient range, which
+ *		is supplied to ypxfr as a command-line parameter when it
+ *		is activated by ypserv.
+ */
+#define YPPUSHVERS		1
+#define YPPUSHVERS_ORIG		1
+
+/* Procedure symbols */
+
+#define YPPUSHPROC_NULL		0
+#define YPPUSHPROC_XFRRESP	1
+
+/* Status values for yppushresp_xfr.status */
+
+enum yppush_status {
+  YPPUSH_SUCC = 1,		/* Success */
+#define YPPUSH_SUCC	YPPUSH_SUCC
+  YPPUSH_AGE = 2,		/* Master's version not newer */
+#define YPPUSH_AGE	YPPUSH_AGE
+  YPPUSH_NOMAP = -1,		/* Can't find server for map */
+#define YPPUSH_NOMAP 	YPPUSH_NOMAP
+  YPPUSH_NODOM = -2,		/* Domain not supported */
+#define YPPUSH_NODOM 	YPPUSH_NODOM
+  YPPUSH_RSRC = -3,		/* Local resouce alloc failure */
+#define YPPUSH_RSRC 	YPPUSH_RSRC
+  YPPUSH_RPC = -4,		/* RPC failure talking to server */
+#define YPPUSH_RPC 	YPPUSH_RPC
+  YPPUSH_MADDR = -5,		/* Can't get master address */
+#define YPPUSH_MADDR	YPPUSH_MADDR
+  YPPUSH_YPERR = -6,		/* NIS server/map db error */
+#define YPPUSH_YPERR 	YPPUSH_YPERR
+  YPPUSH_BADARGS = -7,		/* Request arguments bad */
+#define YPPUSH_BADARGS 	YPPUSH_BADARGS
+  YPPUSH_DBM = -8,		/* Local dbm operation failed */
+#define YPPUSH_DBM	YPPUSH_DBM
+  YPPUSH_FILE = -9,		/* Local file I/O operation failed */
+#define YPPUSH_FILE	YPPUSH_FILE
+  YPPUSH_SKEW = -10,		/* Map version skew during transfer */
+#define YPPUSH_SKEW	YPPUSH_SKEW
+  YPPUSH_CLEAR = -11,		/* Can't send "Clear" req to local ypserv */
+#define YPPUSH_CLEAR	YPPUSH_CLEAR
+  YPPUSH_FORCE = -12,		/* No local order number in map - use -f flag*/
+#define YPPUSH_FORCE	YPPUSH_FORCE
+  YPPUSH_XFRERR = -13,		/* ypxfr error */
+#define YPPUSH_XFRERR	YPPUSH_XFRERR
+  YPPUSH_REFUSED = -14,		/* Transfer request refused by ypserv */
+#define YPPUSH_REFUSED	YPPUSH_REFUSED
+  YPPUSH_NOALIAS = -15		/* Alias not found for map or domain */
+#define	YPPUSH_NOALIAS	YPPUSH_NOALIAS
+};
+typedef enum yppush_status yppush_status;
+
+struct yppushresp_xfr {
+  u_int transid;
+  yppush_status status;
+};
+
+struct ypresp_all {
+  bool_t more;
+  union {
+    struct ypresp_key_val val;
+  } ypresp_all_u;
+};
+
+extern bool_t xdr_ypreq_key (XDR *__xdrs, struct ypreq_key * __objp);
+extern bool_t xdr_ypreq_nokey (XDR *__xdrs, struct ypreq_nokey * __objp);
+extern bool_t xdr_ypreq_xfr (XDR *__xdrs, struct ypreq_xfr * __objp);
+extern bool_t xdr_ypresp_val (XDR *__xdrs, struct ypresp_val * __objp);
+extern bool_t xdr_ypresp_key_val (XDR *__xdrs, struct ypresp_key_val * __objp);
+extern bool_t xdr_ypbind_resp (XDR *__xdrs, struct ypbind_resp * __objp);
+extern bool_t xdr_ypbind_setdom (XDR *__xdrs, struct ypbind_setdom * __objp);
+extern bool_t xdr_ypmap_parms (XDR *__xdrs, struct ypmap_parms * __objp);
+extern bool_t xdr_yppushresp_xfr (XDR *__xdrs, struct yppushresp_xfr * __objp);
+extern bool_t xdr_ypresp_order (XDR *__xdrs, struct ypresp_order  * __objp);
+extern bool_t xdr_ypresp_master (XDR *__xdrs, struct ypresp_master * __objp);
+extern bool_t xdr_ypall (XDR *__xdrs, struct ypall_callback * __objp);
+extern bool_t xdr_ypresp_maplist (XDR *__xdrs, struct ypresp_maplist * __objp);
+extern bool_t xdr_ypbind_binding (XDR *__xdrs, struct ypbind_binding * __objp);
+extern bool_t xdr_ypbind_resptype (XDR *__xdrs, enum ypbind_resptype * __objp);
+extern bool_t xdr_ypstat (XDR *__xdrs, enum ypbind_resptype * __objp);
+extern bool_t xdr_ypresp_all (XDR *__xdrs, struct ypresp_all  * __objp);
+extern bool_t xdr_domainname (XDR *__xdrs, char ** __objp);
+
+__END_DECLS
+
+#endif	/* _RPCSVC_YP_PROT_H */
diff --git a/REORG.TODO/nis/rpcsvc/ypclnt.h b/REORG.TODO/nis/rpcsvc/ypclnt.h
new file mode 100644
index 0000000000..8f59ad4eae
--- /dev/null
+++ b/REORG.TODO/nis/rpcsvc/ypclnt.h
@@ -0,0 +1,88 @@
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+
+#ifndef	__RPCSVC_YPCLNT_H__
+#define	__RPCSVC_YPCLNT_H__
+
+#include <features.h>
+
+/* Some defines */
+#define YPERR_SUCCESS	0		/* There is no error */
+#define	YPERR_BADARGS	1		/* Args to function are bad */
+#define	YPERR_RPC 	2		/* RPC failure */
+#define	YPERR_DOMAIN	3		/* Can't bind to a server with this domain */
+#define	YPERR_MAP	4		/* No such map in server's domain */
+#define	YPERR_KEY	5		/* No such key in map */
+#define	YPERR_YPERR	6		/* Internal yp server or client error */
+#define	YPERR_RESRC	7		/* Local resource allocation failure */
+#define	YPERR_NOMORE	8		/* No more records in map database */
+#define	YPERR_PMAP	9		/* Can't communicate with portmapper */
+#define	YPERR_YPBIND	10		/* Can't communicate with ypbind */
+#define	YPERR_YPSERV	11		/* Can't communicate with ypserv */
+#define	YPERR_NODOM	12		/* Local domain name not set */
+#define	YPERR_BADDB	13		/* yp data base is bad */
+#define	YPERR_VERS	14		/* YP version mismatch */
+#define	YPERR_ACCESS	15		/* Access violation */
+#define	YPERR_BUSY	16		/* Database is busy */
+
+/* Types of update operations */
+#define	YPOP_CHANGE	1		/* Change, do not add */
+#define	YPOP_INSERT	2		/* Add, do not change */
+#define	YPOP_DELETE	3		/* Delete this entry */
+#define	YPOP_STORE	4		/* Add, or change */
+
+__BEGIN_DECLS
+
+/* struct ypall_callback * is the arg which must be passed to yp_all.  */
+struct ypall_callback
+  {
+    int (*foreach) (int __status, char *__key, int __keylen,
+		    char *__val, int __vallen, char *__data);
+    char *data;
+  };
+
+/* External NIS client function references.  */
+extern int yp_bind (const char *) __THROW;
+extern void yp_unbind (const char *) __THROW;
+extern int yp_get_default_domain (char **) __THROW;
+extern int yp_match (const char *, const char *, const char *,
+		     const int, char **, int *) __THROW;
+extern int yp_first (const char *, const char *, char **,
+		     int *, char **, int *) __THROW;
+extern int yp_next (const char *, const char *, const char *,
+		    const int, char **, int *, char **, int *) __THROW;
+extern int yp_master (const char *, const char *, char **) __THROW;
+extern int yp_order (const char *, const char *, unsigned int *) __THROW;
+extern int yp_all (const char *, const char *,
+		   const struct ypall_callback *) __THROW;
+extern const char *yperr_string (const int) __THROW;
+extern const char *ypbinderr_string (const int) __THROW;
+extern int ypprot_err (const int) __THROW;
+extern int yp_update (char *, char *, unsigned int,  char *,
+		      int, char *, int) __THROW;
+#if 0
+extern int yp_maplist (const char *, struct ypmaplist **) __THROW;
+#endif
+
+/* This functions exists only under BSD and Linux systems.  */
+extern int __yp_check (char **) __THROW;
+
+__END_DECLS
+
+#endif	/* __RPCSVC_YPCLNT_H__ */
diff --git a/REORG.TODO/nis/rpcsvc/ypupd.h b/REORG.TODO/nis/rpcsvc/ypupd.h
new file mode 100644
index 0000000000..d07fd4d744
--- /dev/null
+++ b/REORG.TODO/nis/rpcsvc/ypupd.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2010, Oracle America, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials
+ *       provided with the distribution.
+ *     * Neither the name of the "Oracle America, Inc." nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/* from @(#)ypupdate_prot.x	1.3 91/03/11 TIRPC 1.0 */
+
+#ifndef __RPCSVC_YPUPD_H__
+#define __RPCSVC_YPUPD_H__
+
+#include <features.h>
+
+#include <rpc/rpc.h>
+
+#define MAXMAPNAMELEN 255
+#define MAXYPDATALEN 1023
+#define MAXERRMSGLEN 255
+
+__BEGIN_DECLS
+
+typedef struct {
+	u_int yp_buf_len;
+	char *yp_buf_val;
+} yp_buf;
+
+extern  bool_t xdr_yp_buf (XDR *, yp_buf*);
+
+struct ypupdate_args {
+	char *mapname;
+	yp_buf key;
+	yp_buf datum;
+};
+typedef struct ypupdate_args ypupdate_args;
+
+extern  bool_t xdr_ypupdate_args (XDR *, ypupdate_args*);
+
+struct ypdelete_args {
+	char *mapname;
+	yp_buf key;
+};
+typedef struct ypdelete_args ypdelete_args;
+
+extern  bool_t xdr_ypdelete_args (XDR *, ypdelete_args*);
+
+#define YPU_PROG 100028
+#define YPU_VERS 1
+
+#define YPU_CHANGE 1
+extern  u_int * ypu_change_1 (ypupdate_args *, CLIENT *);
+extern  u_int * ypu_change_1_svc (ypupdate_args *, struct svc_req *);
+#define YPU_INSERT 2
+extern  u_int * ypu_insert_1 (ypupdate_args *, CLIENT *);
+extern  u_int * ypu_insert_1_svc (ypupdate_args *, struct svc_req *);
+#define YPU_DELETE 3
+extern  u_int * ypu_delete_1 (ypdelete_args *, CLIENT *);
+extern  u_int * ypu_delete_1_svc (ypdelete_args *, struct svc_req *);
+#define YPU_STORE 4
+extern  u_int * ypu_store_1 (ypupdate_args *, CLIENT *);
+extern  u_int * ypu_store_1_svc (ypupdate_args *, struct svc_req *);
+
+__END_DECLS
+
+#endif /* !__RPCSVC_YPUPD_H__ */
diff --git a/REORG.TODO/nis/yp_xdr.c b/REORG.TODO/nis/yp_xdr.c
new file mode 100644
index 0000000000..0081b4c926
--- /dev/null
+++ b/REORG.TODO/nis/yp_xdr.c
@@ -0,0 +1,330 @@
+/*
+ * Copyright (c) 2010, Oracle America, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials
+ *       provided with the distribution.
+ *     * Neither the name of the "Oracle America, Inc." nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <rpcsvc/yp.h>
+#include <rpcsvc/ypclnt.h>
+#include <shlib-compat.h>
+
+/* The NIS v2 protocol suggests 1024 bytes as a maximum length of all fields.
+   Current Linux systems don't use this limit. To remain compatible with
+   recent Linux systems we choose limits large enough to load large key and
+   data values, but small enough to not pose a DoS threat. */
+
+#define XDRMAXNAME 1024
+#define XDRMAXRECORD (16 * 1024 * 1024)
+
+bool_t
+xdr_ypstat (XDR *xdrs, ypstat *objp)
+{
+  return xdr_enum (xdrs, (enum_t *) objp);
+}
+libnsl_hidden_nolink_def (xdr_ypstat, GLIBC_2_0)
+
+bool_t
+xdr_ypxfrstat (XDR *xdrs, ypxfrstat *objp)
+{
+  return xdr_enum (xdrs, (enum_t *) objp);
+}
+libnsl_hidden_nolink_def (xdr_ypxfrstat, GLIBC_2_0)
+
+bool_t
+xdr_domainname (XDR *xdrs, domainname *objp)
+{
+  return xdr_string (xdrs, objp, XDRMAXNAME);
+}
+libnsl_hidden_nolink_def (xdr_domainname, GLIBC_2_0)
+
+bool_t
+xdr_mapname (XDR *xdrs, mapname *objp)
+{
+  return xdr_string (xdrs, objp, XDRMAXNAME);
+}
+libnsl_hidden_nolink_def (xdr_mapname, GLIBC_2_0)
+
+bool_t
+xdr_peername (XDR *xdrs, peername *objp)
+{
+  return xdr_string (xdrs, objp, XDRMAXNAME);
+}
+libnsl_hidden_nolink_def (xdr_peername, GLIBC_2_0)
+
+bool_t
+xdr_keydat (XDR *xdrs, keydat *objp)
+{
+  return xdr_bytes (xdrs, (char **) &objp->keydat_val,
+		    (u_int *) &objp->keydat_len, XDRMAXRECORD);
+}
+libnsl_hidden_nolink_def (xdr_keydat, GLIBC_2_0)
+
+bool_t
+xdr_valdat (XDR *xdrs, valdat *objp)
+{
+  return xdr_bytes (xdrs, (char **) &objp->valdat_val,
+		    (u_int *) &objp->valdat_len, XDRMAXRECORD);
+}
+libnsl_hidden_nolink_def (xdr_valdat, GLIBC_2_0)
+
+bool_t
+xdr_ypmap_parms (XDR *xdrs, ypmap_parms *objp)
+{
+  if (!xdr_domainname (xdrs, &objp->domain))
+    return FALSE;
+  if (!xdr_mapname (xdrs, &objp->map))
+    return FALSE;
+  if (!xdr_u_int (xdrs, &objp->ordernum))
+    return FALSE;
+  return xdr_peername (xdrs, &objp->peer);
+}
+libnsl_hidden_nolink_def (xdr_ypmap_parms, GLIBC_2_0)
+
+bool_t
+xdr_ypreq_key (XDR *xdrs, ypreq_key *objp)
+{
+  if (!xdr_domainname (xdrs, &objp->domain))
+    return FALSE;
+  if (!xdr_mapname (xdrs, &objp->map))
+    return FALSE;
+  return xdr_keydat (xdrs, &objp->key);
+}
+libnsl_hidden_nolink_def (xdr_ypreq_key, GLIBC_2_0)
+
+bool_t
+xdr_ypreq_nokey (XDR *xdrs, ypreq_nokey *objp)
+{
+  if (!xdr_domainname (xdrs, &objp->domain))
+    return FALSE;
+  return xdr_mapname (xdrs, &objp->map);
+}
+libnsl_hidden_nolink_def (xdr_ypreq_nokey, GLIBC_2_0)
+
+bool_t
+xdr_ypreq_xfr (XDR *xdrs, ypreq_xfr *objp)
+{
+  if (!xdr_ypmap_parms (xdrs, &objp->map_parms))
+    return FALSE;
+  if (!xdr_u_int (xdrs, &objp->transid))
+    return FALSE;
+  if (!xdr_u_int (xdrs, &objp->prog))
+    return FALSE;
+  return xdr_u_int (xdrs, &objp->port);
+}
+libnsl_hidden_nolink_def (xdr_ypreq_xfr, GLIBC_2_0)
+
+bool_t
+xdr_ypresp_val (XDR *xdrs, ypresp_val *objp)
+{
+  if (!xdr_ypstat (xdrs, &objp->stat))
+    return FALSE;
+  return xdr_valdat (xdrs, &objp->val);
+}
+libnsl_hidden_nolink_def (xdr_ypresp_val, GLIBC_2_0)
+
+bool_t
+xdr_ypresp_key_val (XDR *xdrs, ypresp_key_val *objp)
+{
+  if (!xdr_ypstat (xdrs, &objp->stat))
+    return FALSE;
+  if (!xdr_valdat (xdrs, &objp->val))
+    return FALSE;
+  return xdr_keydat (xdrs, &objp->key);
+}
+libnsl_hidden_nolink_def (xdr_ypresp_key_val, GLIBC_2_0)
+
+bool_t
+xdr_ypresp_master (XDR *xdrs, ypresp_master *objp)
+{
+  if (!xdr_ypstat (xdrs, &objp->stat))
+    return FALSE;
+  return xdr_peername (xdrs, &objp->peer);
+}
+libnsl_hidden_nolink_def (xdr_ypresp_master, GLIBC_2_0)
+
+bool_t
+xdr_ypresp_order (XDR *xdrs, ypresp_order *objp)
+{
+  if (!xdr_ypstat (xdrs, &objp->stat))
+    return FALSE;
+  return xdr_u_int (xdrs, &objp->ordernum);
+}
+libnsl_hidden_nolink_def (xdr_ypresp_order, GLIBC_2_0)
+
+bool_t
+xdr_ypresp_all (XDR *xdrs, ypresp_all *objp)
+{
+  if (!xdr_bool (xdrs, &objp->more))
+    return FALSE;
+  switch (objp->more)
+    {
+    case TRUE:
+      return xdr_ypresp_key_val (xdrs, &objp->ypresp_all_u.val);
+    case FALSE:
+      break;
+    default:
+      return FALSE;
+    }
+  return TRUE;
+}
+libnsl_hidden_nolink_def (xdr_ypresp_all, GLIBC_2_0)
+
+bool_t
+xdr_ypresp_xfr (XDR *xdrs, ypresp_xfr *objp)
+{
+  if (!xdr_u_int (xdrs, &objp->transid))
+    return FALSE;
+  return xdr_ypxfrstat (xdrs, &objp->xfrstat);
+}
+libnsl_hidden_nolink_def (xdr_ypresp_xfr, GLIBC_2_0)
+
+bool_t
+xdr_ypmaplist (XDR *xdrs, ypmaplist *objp)
+{
+  if (!xdr_mapname (xdrs, &objp->map))
+    return FALSE;
+  /* Prevent gcc warning about alias violation.  */
+  char **tp = (void *) &objp->next;
+  return xdr_pointer (xdrs, tp, sizeof (ypmaplist), (xdrproc_t) xdr_ypmaplist);
+}
+libnsl_hidden_nolink_def (xdr_ypmaplist, GLIBC_2_0)
+
+bool_t
+xdr_ypresp_maplist (XDR *xdrs, ypresp_maplist *objp)
+{
+  if (!xdr_ypstat (xdrs, &objp->stat))
+    return FALSE;
+  /* Prevent gcc warning about alias violation.  */
+  char **tp = (void *) &objp->maps;
+  return xdr_pointer (xdrs, tp, sizeof (ypmaplist), (xdrproc_t) xdr_ypmaplist);
+}
+libnsl_hidden_nolink_def (xdr_ypresp_maplist, GLIBC_2_0)
+
+bool_t
+xdr_yppush_status (XDR *xdrs, yppush_status *objp)
+{
+  return xdr_enum (xdrs, (enum_t *) objp);
+}
+libnsl_hidden_nolink_def (xdr_yppush_status, GLIBC_2_0)
+
+bool_t
+xdr_yppushresp_xfr (XDR *xdrs, yppushresp_xfr *objp)
+{
+  if (!xdr_u_int (xdrs, &objp->transid))
+    return FALSE;
+  return xdr_yppush_status (xdrs, &objp->status);
+}
+libnsl_hidden_nolink_def (xdr_yppushresp_xfr, GLIBC_2_0)
+
+bool_t
+xdr_ypbind_resptype (XDR *xdrs, ypbind_resptype *objp)
+{
+  return xdr_enum (xdrs, (enum_t *) objp);
+}
+libnsl_hidden_nolink_def (xdr_ypbind_resptype, GLIBC_2_0)
+
+bool_t
+xdr_ypbind_binding (XDR *xdrs, ypbind_binding *objp)
+{
+  if (!xdr_opaque (xdrs, objp->ypbind_binding_addr, 4))
+    return FALSE;
+  return xdr_opaque (xdrs, objp->ypbind_binding_port, 2);
+}
+libnsl_hidden_nolink_def (xdr_ypbind_binding, GLIBC_2_0)
+
+bool_t
+xdr_ypbind_resp (XDR *xdrs, ypbind_resp *objp)
+{
+  if (!xdr_ypbind_resptype (xdrs, &objp->ypbind_status))
+    return FALSE;
+  switch (objp->ypbind_status)
+    {
+    case YPBIND_FAIL_VAL:
+      return xdr_u_int (xdrs, &objp->ypbind_resp_u.ypbind_error);
+    case YPBIND_SUCC_VAL:
+      return xdr_ypbind_binding (xdrs, &objp->ypbind_resp_u.ypbind_bindinfo);
+    }
+  return FALSE;
+}
+libnsl_hidden_nolink_def (xdr_ypbind_resp, GLIBC_2_0)
+
+bool_t
+xdr_ypbind_setdom (XDR *xdrs, ypbind_setdom *objp)
+{
+  if (!xdr_domainname (xdrs, &objp->ypsetdom_domain))
+    return FALSE;
+  if (!xdr_ypbind_binding (xdrs, &objp->ypsetdom_binding))
+    return FALSE;
+  return xdr_u_int (xdrs, &objp->ypsetdom_vers);
+}
+libnsl_hidden_nolink_def (xdr_ypbind_setdom, GLIBC_2_0)
+
+bool_t
+xdr_ypall(XDR *xdrs, struct ypall_callback *incallback)
+{
+    struct ypresp_key_val out;
+    char key[YPMAXRECORD], val[YPMAXRECORD];
+
+    /*
+     * Set up key/val struct to be used during the transaction.
+     */
+    memset(&out, 0, sizeof out);
+    out.key.keydat_val = key;
+    out.key.keydat_len = sizeof(key);
+    out.val.valdat_val = val;
+    out.val.valdat_len = sizeof(val);
+
+    for (;;) {
+	bool_t more, status;
+
+	/* Values pending? */
+	if (!xdr_bool(xdrs, &more))
+	    return FALSE;           /* can't tell! */
+	if (!more)
+	    return TRUE;            /* no more */
+
+	/* Transfer key/value pair. */
+	status = xdr_ypresp_key_val(xdrs, &out);
+
+	/*
+	 * If we succeeded, call the callback function.
+	 * The callback will return TRUE when it wants
+	 * no more values.  If we fail, indicate the
+	 * error.
+	 */
+	if (status) {
+	    if ((*incallback->foreach)(out.stat,
+				       (char *)out.key.keydat_val, out.key.keydat_len,
+				       (char *)out.val.valdat_val, out.val.valdat_len,
+				       incallback->data))
+		return TRUE;
+	} else
+	    return FALSE;
+    }
+}
+/* XXX libnsl_hidden_nolink_def(xdr_ypall, GLIBC_2_2) */
diff --git a/REORG.TODO/nis/ypclnt.c b/REORG.TODO/nis/ypclnt.c
new file mode 100644
index 0000000000..a03e347685
--- /dev/null
+++ b/REORG.TODO/nis/ypclnt.c
@@ -0,0 +1,1030 @@
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <libintl.h>
+#include <rpc/rpc.h>
+#include <rpcsvc/nis.h>
+#include <rpcsvc/yp.h>
+#include <rpcsvc/ypclnt.h>
+#include <rpcsvc/ypupd.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <libc-lock.h>
+#include <shlib-compat.h>
+
+/* This should only be defined on systems with a BSD compatible ypbind */
+#ifndef BINDINGDIR
+# define BINDINGDIR "/var/yp/binding"
+#endif
+
+struct dom_binding
+  {
+    struct dom_binding *dom_pnext;
+    char dom_domain[YPMAXDOMAIN + 1];
+    struct sockaddr_in dom_server_addr;
+    int dom_socket;
+    CLIENT *dom_client;
+  };
+typedef struct dom_binding dom_binding;
+
+static const struct timeval RPCTIMEOUT = {25, 0};
+static const struct timeval UDPTIMEOUT = {5, 0};
+static int const MAXTRIES = 2;
+static char ypdomainname[NIS_MAXNAMELEN + 1];
+__libc_lock_define_initialized (static, ypbindlist_lock)
+static dom_binding *ypbindlist = NULL;
+
+
+static void
+yp_bind_client_create (const char *domain, dom_binding *ysd,
+		       struct ypbind_resp *ypbr)
+{
+  ysd->dom_server_addr.sin_family = AF_INET;
+  memcpy (&ysd->dom_server_addr.sin_port,
+	  ypbr->ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port,
+	  sizeof (ysd->dom_server_addr.sin_port));
+  memcpy (&ysd->dom_server_addr.sin_addr.s_addr,
+	  ypbr->ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
+	  sizeof (ysd->dom_server_addr.sin_addr.s_addr));
+  strncpy (ysd->dom_domain, domain, YPMAXDOMAIN);
+  ysd->dom_domain[YPMAXDOMAIN] = '\0';
+
+  ysd->dom_socket = RPC_ANYSOCK;
+  ysd->dom_client = __libc_clntudp_bufcreate (&ysd->dom_server_addr, YPPROG,
+					      YPVERS, UDPTIMEOUT,
+					      &ysd->dom_socket,
+					      UDPMSGSIZE, UDPMSGSIZE,
+					      SOCK_CLOEXEC);
+}
+
+#if USE_BINDINGDIR
+static void
+yp_bind_file (const char *domain, dom_binding *ysd)
+{
+  char path[sizeof (BINDINGDIR) + strlen (domain) + 3 * sizeof (unsigned) + 3];
+
+  snprintf (path, sizeof (path), "%s/%s.%u", BINDINGDIR, domain, YPBINDVERS);
+  int fd = open (path, O_RDONLY);
+  if (fd >= 0)
+    {
+      /* We have a binding file and could save a RPC call.  The file
+	 contains a port number and the YPBIND_RESP record.  The port
+	 number (16 bits) can be ignored.  */
+      struct ypbind_resp ypbr;
+
+      if (pread (fd, &ypbr, sizeof (ypbr), 2) == sizeof (ypbr))
+	yp_bind_client_create (domain, ysd, &ypbr);
+
+      close (fd);
+    }
+}
+#endif
+
+static int
+yp_bind_ypbindprog (const char *domain, dom_binding *ysd)
+{
+  struct sockaddr_in clnt_saddr;
+  struct ypbind_resp ypbr;
+  int clnt_sock;
+  CLIENT *client;
+
+  clnt_saddr.sin_family = AF_INET;
+  clnt_saddr.sin_port = 0;
+  clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+  clnt_sock = RPC_ANYSOCK;
+  client = clnttcp_create (&clnt_saddr, YPBINDPROG, YPBINDVERS,
+			   &clnt_sock, 0, 0);
+  if (client == NULL)
+    return YPERR_YPBIND;
+
+  /* Check the port number -- should be < IPPORT_RESERVED.
+     If not, it's possible someone has registered a bogus
+     ypbind with the portmapper and is trying to trick us. */
+  if (ntohs (clnt_saddr.sin_port) >= IPPORT_RESERVED)
+    {
+      clnt_destroy (client);
+      return YPERR_YPBIND;
+    }
+
+  if (clnt_call (client, YPBINDPROC_DOMAIN,
+		 (xdrproc_t) xdr_domainname, (caddr_t) &domain,
+		 (xdrproc_t) xdr_ypbind_resp,
+		 (caddr_t) &ypbr, RPCTIMEOUT) != RPC_SUCCESS)
+    {
+      clnt_destroy (client);
+      return YPERR_YPBIND;
+    }
+
+  clnt_destroy (client);
+
+  if (ypbr.ypbind_status != YPBIND_SUCC_VAL)
+    {
+      fprintf (stderr, "YPBINDPROC_DOMAIN: %s\n",
+	       ypbinderr_string (ypbr.ypbind_resp_u.ypbind_error));
+      return YPERR_DOMAIN;
+    }
+  memset (&ysd->dom_server_addr, '\0', sizeof ysd->dom_server_addr);
+
+  yp_bind_client_create (domain, ysd, &ypbr);
+
+  return YPERR_SUCCESS;
+}
+
+static int
+__yp_bind (const char *domain, dom_binding **ypdb)
+{
+  dom_binding *ysd = NULL;
+  int is_new = 0;
+
+  if (domain == NULL || domain[0] == '\0')
+    return YPERR_BADARGS;
+
+  ysd = *ypdb;
+  while (ysd != NULL)
+    {
+      if (strcmp (domain, ysd->dom_domain) == 0)
+	break;
+      ysd = ysd->dom_pnext;
+    }
+
+  if (ysd == NULL)
+    {
+      is_new = 1;
+      ysd = (dom_binding *) calloc (1, sizeof *ysd);
+      if (__glibc_unlikely (ysd == NULL))
+	return YPERR_RESRC;
+    }
+
+#if USE_BINDINGDIR
+  /* Try binding dir at first if we have no binding */
+  if (ysd->dom_client == NULL)
+    yp_bind_file (domain, ysd);
+#endif /* USE_BINDINGDIR */
+
+  if (ysd->dom_client == NULL)
+    {
+      int retval = yp_bind_ypbindprog (domain, ysd);
+      if (retval != YPERR_SUCCESS)
+	{
+	  if (is_new)
+	    free (ysd);
+	  return retval;
+	}
+    }
+
+  if (ysd->dom_client == NULL)
+    {
+      if (is_new)
+	free (ysd);
+      return YPERR_YPSERV;
+    }
+
+  if (is_new)
+    {
+      ysd->dom_pnext = *ypdb;
+      *ypdb = ysd;
+    }
+
+  return YPERR_SUCCESS;
+}
+
+static void
+__yp_unbind (dom_binding *ydb)
+{
+  clnt_destroy (ydb->dom_client);
+  free (ydb);
+}
+
+int
+yp_bind (const char *indomain)
+{
+  int status;
+
+  __libc_lock_lock (ypbindlist_lock);
+
+  status = __yp_bind (indomain, &ypbindlist);
+
+  __libc_lock_unlock (ypbindlist_lock);
+
+  return status;
+}
+libnsl_hidden_nolink_def (yp_bind, GLIBC_2_0)
+
+static void
+yp_unbind_locked (const char *indomain)
+{
+  dom_binding *ydbptr, *ydbptr2;
+
+  ydbptr2 = NULL;
+  ydbptr = ypbindlist;
+
+  while (ydbptr != NULL)
+    {
+      if (strcmp (ydbptr->dom_domain, indomain) == 0)
+	{
+	  dom_binding *work;
+
+	  work = ydbptr;
+	  if (ydbptr2 == NULL)
+	    ypbindlist = ypbindlist->dom_pnext;
+	  else
+	    ydbptr2 = ydbptr->dom_pnext;
+	  __yp_unbind (work);
+	  break;
+	}
+      ydbptr2 = ydbptr;
+      ydbptr = ydbptr->dom_pnext;
+    }
+}
+
+void
+yp_unbind (const char *indomain)
+{
+  __libc_lock_lock (ypbindlist_lock);
+
+  yp_unbind_locked (indomain);
+
+  __libc_lock_unlock (ypbindlist_lock);
+
+  return;
+}
+libnsl_hidden_nolink_def(yp_unbind, GLIBC_2_0)
+
+static int
+__ypclnt_call (const char *domain, u_long prog, xdrproc_t xargs,
+	       caddr_t req, xdrproc_t xres, caddr_t resp, dom_binding **ydb,
+	       int print_error)
+{
+  enum clnt_stat result;
+
+  result = clnt_call ((*ydb)->dom_client, prog,
+		      xargs, req, xres, resp, RPCTIMEOUT);
+
+  if (result != RPC_SUCCESS)
+    {
+      /* We don't print an error message, if we try our old,
+	 cached data. Only print this for data, which should work.  */
+      if (print_error)
+	clnt_perror ((*ydb)->dom_client, "do_ypcall: clnt_call");
+
+      return YPERR_RPC;
+    }
+
+  return YPERR_SUCCESS;
+}
+
+static int
+do_ypcall (const char *domain, u_long prog, xdrproc_t xargs,
+	   caddr_t req, xdrproc_t xres, caddr_t resp)
+{
+  dom_binding *ydb;
+  int status;
+  int saved_errno = errno;
+
+  status = YPERR_YPERR;
+
+  __libc_lock_lock (ypbindlist_lock);
+  ydb = ypbindlist;
+  while (ydb != NULL)
+    {
+      if (strcmp (domain, ydb->dom_domain) == 0)
+	{
+          if (__yp_bind (domain, &ydb) == 0)
+	    {
+	      /* Call server, print no error message, do not unbind.  */
+	      status = __ypclnt_call (domain, prog, xargs, req, xres,
+				      resp, &ydb, 0);
+	      if (status == YPERR_SUCCESS)
+	        {
+		  __libc_lock_unlock (ypbindlist_lock);
+	          __set_errno (saved_errno);
+	          return status;
+	        }
+	    }
+	  /* We use ypbindlist, and the old cached data is
+	     invalid. unbind now and create a new binding */
+	  yp_unbind_locked (domain);
+
+	  break;
+	}
+      ydb = ydb->dom_pnext;
+    }
+  __libc_lock_unlock (ypbindlist_lock);
+
+  /* First try with cached data failed. Now try to get
+     current data from the system.  */
+  ydb = NULL;
+  if (__yp_bind (domain, &ydb) == 0)
+    {
+      status = __ypclnt_call (domain, prog, xargs, req, xres,
+			      resp, &ydb, 1);
+      __yp_unbind (ydb);
+    }
+
+#if USE_BINDINGDIR
+  /* If we support binding dir data, we have a third chance:
+     Ask ypbind.  */
+  if (status != YPERR_SUCCESS)
+    {
+      ydb = calloc (1, sizeof (dom_binding));
+      if (ydb != NULL && yp_bind_ypbindprog (domain, ydb) == YPERR_SUCCESS)
+	{
+	  status = __ypclnt_call (domain, prog, xargs, req, xres,
+				  resp, &ydb, 1);
+	  __yp_unbind (ydb);
+	}
+      else
+	free (ydb);
+    }
+#endif
+
+  __set_errno (saved_errno);
+
+  return status;
+}
+
+/* Like do_ypcall, but translate the status value if necessary.  */
+static int
+do_ypcall_tr (const char *domain, u_long prog, xdrproc_t xargs,
+	      caddr_t req, xdrproc_t xres, caddr_t resp)
+{
+  int status = do_ypcall (domain, prog, xargs, req, xres, resp);
+  if (status == YPERR_SUCCESS)
+    /* We cast to ypresp_val although the pointer could also be of
+       type ypresp_key_val or ypresp_master or ypresp_order or
+       ypresp_maplist.  But the stat element is in a common prefix so
+       this does not matter.  */
+    status = ypprot_err (((struct ypresp_val *) resp)->stat);
+  return status;
+}
+
+
+__libc_lock_define_initialized (static, domainname_lock)
+
+int
+yp_get_default_domain (char **outdomain)
+{
+  int result = YPERR_SUCCESS;;
+  *outdomain = NULL;
+
+  __libc_lock_lock (domainname_lock);
+
+  if (ypdomainname[0] == '\0')
+    {
+      if (getdomainname (ypdomainname, NIS_MAXNAMELEN))
+	result = YPERR_NODOM;
+      else if (strcmp (ypdomainname, "(none)") == 0)
+	{
+	  /* If domainname is not set, some systems will return "(none)" */
+	  ypdomainname[0] = '\0';
+	  result = YPERR_NODOM;
+	}
+      else
+	*outdomain = ypdomainname;
+    }
+  else
+    *outdomain = ypdomainname;
+
+  __libc_lock_unlock (domainname_lock);
+
+  return result;
+}
+libnsl_hidden_nolink_def (yp_get_default_domain, GLIBC_2_0)
+
+int
+__yp_check (char **domain)
+{
+  char *unused;
+
+  if (ypdomainname[0] == '\0')
+    if (yp_get_default_domain (&unused))
+      return 0;
+
+  if (domain)
+    *domain = ypdomainname;
+
+  if (yp_bind (ypdomainname) == 0)
+    return 1;
+  return 0;
+}
+libnsl_hidden_nolink_def(__yp_check, GLIBC_2_0)
+
+int
+yp_match (const char *indomain, const char *inmap, const char *inkey,
+	  const int inkeylen, char **outval, int *outvallen)
+{
+  ypreq_key req;
+  ypresp_val resp;
+  enum clnt_stat result;
+
+  if (indomain == NULL || indomain[0] == '\0' ||
+      inmap == NULL || inmap[0] == '\0' ||
+      inkey == NULL || inkey[0] == '\0' || inkeylen <= 0)
+    return YPERR_BADARGS;
+
+  req.domain = (char *) indomain;
+  req.map = (char *) inmap;
+  req.key.keydat_val = (char *) inkey;
+  req.key.keydat_len = inkeylen;
+
+  *outval = NULL;
+  *outvallen = 0;
+  memset (&resp, '\0', sizeof (resp));
+
+  result = do_ypcall_tr (indomain, YPPROC_MATCH, (xdrproc_t) xdr_ypreq_key,
+			 (caddr_t) &req, (xdrproc_t) xdr_ypresp_val,
+			 (caddr_t) &resp);
+
+  if (result != YPERR_SUCCESS)
+    return result;
+
+  *outvallen = resp.val.valdat_len;
+  *outval = malloc (*outvallen + 1);
+  int status = YPERR_RESRC;
+  if (__glibc_likely (*outval != NULL))
+    {
+      memcpy (*outval, resp.val.valdat_val, *outvallen);
+      (*outval)[*outvallen] = '\0';
+      status = YPERR_SUCCESS;
+    }
+
+  xdr_free ((xdrproc_t) xdr_ypresp_val, (char *) &resp);
+
+  return status;
+}
+libnsl_hidden_nolink_def(yp_match, GLIBC_2_0)
+
+int
+yp_first (const char *indomain, const char *inmap, char **outkey,
+	  int *outkeylen, char **outval, int *outvallen)
+{
+  ypreq_nokey req;
+  ypresp_key_val resp;
+  enum clnt_stat result;
+
+  if (indomain == NULL || indomain[0] == '\0' ||
+      inmap == NULL || inmap[0] == '\0')
+    return YPERR_BADARGS;
+
+  req.domain = (char *) indomain;
+  req.map = (char *) inmap;
+
+  *outkey = *outval = NULL;
+  *outkeylen = *outvallen = 0;
+  memset (&resp, '\0', sizeof (resp));
+
+  result = do_ypcall (indomain, YPPROC_FIRST, (xdrproc_t) xdr_ypreq_nokey,
+		      (caddr_t) &req, (xdrproc_t) xdr_ypresp_key_val,
+		      (caddr_t) &resp);
+
+  if (result != RPC_SUCCESS)
+    return YPERR_RPC;
+  if (resp.stat != YP_TRUE)
+    return ypprot_err (resp.stat);
+
+  int status;
+  if (__builtin_expect ((*outkey  = malloc (resp.key.keydat_len + 1)) != NULL
+			&& (*outval = malloc (resp.val.valdat_len
+					      + 1)) != NULL, 1))
+    {
+      *outkeylen = resp.key.keydat_len;
+      memcpy (*outkey, resp.key.keydat_val, *outkeylen);
+      (*outkey)[*outkeylen] = '\0';
+
+      *outvallen = resp.val.valdat_len;
+      memcpy (*outval, resp.val.valdat_val, *outvallen);
+      (*outval)[*outvallen] = '\0';
+
+      status = YPERR_SUCCESS;
+    }
+  else
+    {
+      free (*outkey);
+      status = YPERR_RESRC;
+    }
+
+  xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
+
+  return status;
+}
+libnsl_hidden_nolink_def(yp_first, GLIBC_2_0)
+
+int
+yp_next (const char *indomain, const char *inmap, const char *inkey,
+	 const int inkeylen, char **outkey, int *outkeylen, char **outval,
+	 int *outvallen)
+{
+  ypreq_key req;
+  ypresp_key_val resp;
+  enum clnt_stat result;
+
+  if (indomain == NULL || indomain[0] == '\0' ||
+      inmap == NULL || inmap[0] == '\0' ||
+      inkeylen <= 0 || inkey == NULL || inkey[0] == '\0')
+    return YPERR_BADARGS;
+
+  req.domain = (char *) indomain;
+  req.map = (char *) inmap;
+  req.key.keydat_val = (char *) inkey;
+  req.key.keydat_len = inkeylen;
+
+  *outkey = *outval = NULL;
+  *outkeylen = *outvallen = 0;
+  memset (&resp, '\0', sizeof (resp));
+
+  result = do_ypcall_tr (indomain, YPPROC_NEXT, (xdrproc_t) xdr_ypreq_key,
+			 (caddr_t) &req, (xdrproc_t) xdr_ypresp_key_val,
+			 (caddr_t) &resp);
+
+  if (result != YPERR_SUCCESS)
+    return result;
+
+  int status;
+  if (__builtin_expect ((*outkey  = malloc (resp.key.keydat_len + 1)) != NULL
+			&& (*outval = malloc (resp.val.valdat_len
+					      + 1)) != NULL, 1))
+    {
+      *outkeylen = resp.key.keydat_len;
+      memcpy (*outkey, resp.key.keydat_val, *outkeylen);
+      (*outkey)[*outkeylen] = '\0';
+
+      *outvallen = resp.val.valdat_len;
+      memcpy (*outval, resp.val.valdat_val, *outvallen);
+      (*outval)[*outvallen] = '\0';
+
+      status = YPERR_SUCCESS;
+    }
+  else
+    {
+      free (*outkey);
+      status = YPERR_RESRC;
+    }
+
+  xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
+
+  return status;
+}
+libnsl_hidden_nolink_def(yp_next, GLIBC_2_0)
+
+int
+yp_master (const char *indomain, const char *inmap, char **outname)
+{
+  ypreq_nokey req;
+  ypresp_master resp;
+  enum clnt_stat result;
+
+  if (indomain == NULL || indomain[0] == '\0' ||
+      inmap == NULL || inmap[0] == '\0')
+    return YPERR_BADARGS;
+
+  req.domain = (char *) indomain;
+  req.map = (char *) inmap;
+
+  memset (&resp, '\0', sizeof (ypresp_master));
+
+  result = do_ypcall_tr (indomain, YPPROC_MASTER, (xdrproc_t) xdr_ypreq_nokey,
+			 (caddr_t) &req, (xdrproc_t) xdr_ypresp_master,
+			 (caddr_t) &resp);
+
+  if (result != YPERR_SUCCESS)
+    return result;
+
+  *outname = strdup (resp.peer);
+  xdr_free ((xdrproc_t) xdr_ypresp_master, (char *) &resp);
+
+  return *outname == NULL ? YPERR_YPERR : YPERR_SUCCESS;
+}
+libnsl_hidden_nolink_def (yp_master, GLIBC_2_0)
+
+int
+yp_order (const char *indomain, const char *inmap, unsigned int *outorder)
+{
+  struct ypreq_nokey req;
+  struct ypresp_order resp;
+  enum clnt_stat result;
+
+  if (indomain == NULL || indomain[0] == '\0' ||
+      inmap == NULL || inmap[0] == '\0')
+    return YPERR_BADARGS;
+
+  req.domain = (char *) indomain;
+  req.map = (char *) inmap;
+
+  memset (&resp, '\0', sizeof (resp));
+
+  result = do_ypcall_tr (indomain, YPPROC_ORDER, (xdrproc_t) xdr_ypreq_nokey,
+			 (caddr_t) &req, (xdrproc_t) xdr_ypresp_order,
+			 (caddr_t) &resp);
+
+  if (result != YPERR_SUCCESS)
+    return result;
+
+  *outorder = resp.ordernum;
+  xdr_free ((xdrproc_t) xdr_ypresp_order, (char *) &resp);
+
+  return result;
+}
+libnsl_hidden_nolink_def(yp_order, GLIBC_2_0)
+
+struct ypresp_all_data
+{
+  unsigned long status;
+  void *data;
+  int (*foreach) (int status, char *key, int keylen,
+		  char *val, int vallen, char *data);
+};
+
+static bool_t
+__xdr_ypresp_all (XDR *xdrs, struct ypresp_all_data *objp)
+{
+  while (1)
+    {
+      struct ypresp_all resp;
+
+      memset (&resp, '\0', sizeof (struct ypresp_all));
+      if (!xdr_ypresp_all (xdrs, &resp))
+	{
+	  xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
+	  objp->status = YP_YPERR;
+	  return FALSE;
+	}
+      if (resp.more == 0)
+	{
+	  xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
+	  objp->status = YP_NOMORE;
+	  return TRUE;
+	}
+
+      switch (resp.ypresp_all_u.val.stat)
+	{
+	case YP_TRUE:
+	  {
+	    char key[resp.ypresp_all_u.val.key.keydat_len + 1];
+	    char val[resp.ypresp_all_u.val.val.valdat_len + 1];
+	    int keylen = resp.ypresp_all_u.val.key.keydat_len;
+	    int vallen = resp.ypresp_all_u.val.val.valdat_len;
+
+	    /* We are not allowed to modify the key and val data.
+	       But we are allowed to add data behind the buffer,
+	       if we don't modify the length. So add an extra NUL
+	       character to avoid trouble with broken code. */
+	    objp->status = YP_TRUE;
+	    *((char *) __mempcpy (key, resp.ypresp_all_u.val.key.keydat_val,
+				  keylen)) = '\0';
+	    *((char *) __mempcpy (val, resp.ypresp_all_u.val.val.valdat_val,
+				  vallen)) = '\0';
+	    xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
+	    if ((*objp->foreach) (objp->status, key, keylen,
+				  val, vallen, objp->data))
+	      return TRUE;
+	  }
+	  break;
+	default:
+	  objp->status = resp.ypresp_all_u.val.stat;
+	  xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
+	  /* Sun says we don't need to make this call, but must return
+	     immediately. Since Solaris makes this call, we will call
+	     the callback function, too. */
+	  (*objp->foreach) (objp->status, NULL, 0, NULL, 0, objp->data);
+	  return TRUE;
+	}
+    }
+}
+
+int
+yp_all (const char *indomain, const char *inmap,
+	const struct ypall_callback *incallback)
+{
+  struct ypreq_nokey req;
+  dom_binding *ydb = NULL;
+  int try, res;
+  enum clnt_stat result;
+  struct sockaddr_in clnt_sin;
+  CLIENT *clnt;
+  struct ypresp_all_data data;
+  int clnt_sock;
+  int saved_errno = errno;
+
+  if (indomain == NULL || indomain[0] == '\0'
+      || inmap == NULL || inmap[0] == '\0')
+    return YPERR_BADARGS;
+
+  try = 0;
+  res = YPERR_YPERR;
+
+  while (try < MAXTRIES && res != YPERR_SUCCESS)
+    {
+      if (__yp_bind (indomain, &ydb) != 0)
+	{
+	  __set_errno (saved_errno);
+	  return YPERR_DOMAIN;
+	}
+
+      clnt_sock = RPC_ANYSOCK;
+      clnt_sin = ydb->dom_server_addr;
+      clnt_sin.sin_port = 0;
+
+      /* We don't need the UDP connection anymore.  */
+      __yp_unbind (ydb);
+      ydb = NULL;
+
+      clnt = clnttcp_create (&clnt_sin, YPPROG, YPVERS, &clnt_sock, 0, 0);
+      if (clnt == NULL)
+	{
+	  __set_errno (saved_errno);
+	  return YPERR_PMAP;
+	}
+      req.domain = (char *) indomain;
+      req.map = (char *) inmap;
+
+      data.foreach = incallback->foreach;
+      data.data = (void *) incallback->data;
+
+      result = clnt_call (clnt, YPPROC_ALL, (xdrproc_t) xdr_ypreq_nokey,
+			  (caddr_t) &req, (xdrproc_t) __xdr_ypresp_all,
+			  (caddr_t) &data, RPCTIMEOUT);
+
+      if (__glibc_unlikely (result != RPC_SUCCESS))
+	{
+	  /* Print the error message only on the last try.  */
+	  if (try == MAXTRIES - 1)
+	    clnt_perror (clnt, "yp_all: clnt_call");
+	  res = YPERR_RPC;
+	}
+      else
+	res = YPERR_SUCCESS;
+
+      clnt_destroy (clnt);
+
+      if (res == YPERR_SUCCESS && data.status != YP_NOMORE)
+	{
+	  __set_errno (saved_errno);
+	  return ypprot_err (data.status);
+	}
+      ++try;
+    }
+
+  __set_errno (saved_errno);
+
+  return res;
+}
+libnsl_hidden_nolink_def (yp_all, GLIBC_2_0)
+
+int
+yp_maplist (const char *indomain, struct ypmaplist **outmaplist)
+{
+  struct ypresp_maplist resp;
+  enum clnt_stat result;
+
+  if (indomain == NULL || indomain[0] == '\0')
+    return YPERR_BADARGS;
+
+  memset (&resp, '\0', sizeof (resp));
+
+  result = do_ypcall_tr (indomain, YPPROC_MAPLIST, (xdrproc_t) xdr_domainname,
+			 (caddr_t) &indomain, (xdrproc_t) xdr_ypresp_maplist,
+			 (caddr_t) &resp);
+
+  if (__glibc_likely (result == YPERR_SUCCESS))
+    {
+      *outmaplist = resp.maps;
+      /* We don't free the list, this will be done by ypserv
+	 xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
+    }
+
+  return result;
+}
+
+const char *
+yperr_string (const int error)
+{
+  const char *str;
+  switch (error)
+    {
+    case YPERR_SUCCESS:
+      str = N_("Success");
+      break;
+    case YPERR_BADARGS:
+      str = N_("Request arguments bad");
+      break;
+    case YPERR_RPC:
+      str = N_("RPC failure on NIS operation");
+      break;
+    case YPERR_DOMAIN:
+      str = N_("Can't bind to server which serves this domain");
+      break;
+    case YPERR_MAP:
+      str = N_("No such map in server's domain");
+      break;
+    case YPERR_KEY:
+      str = N_("No such key in map");
+      break;
+    case YPERR_YPERR:
+      str = N_("Internal NIS error");
+      break;
+    case YPERR_RESRC:
+      str = N_("Local resource allocation failure");
+      break;
+    case YPERR_NOMORE:
+      str = N_("No more records in map database");
+      break;
+    case YPERR_PMAP:
+      str = N_("Can't communicate with portmapper");
+      break;
+    case YPERR_YPBIND:
+      str = N_("Can't communicate with ypbind");
+      break;
+    case YPERR_YPSERV:
+      str = N_("Can't communicate with ypserv");
+      break;
+    case YPERR_NODOM:
+      str = N_("Local domain name not set");
+      break;
+    case YPERR_BADDB:
+      str = N_("NIS map database is bad");
+      break;
+    case YPERR_VERS:
+      str = N_("NIS client/server version mismatch - can't supply service");
+      break;
+    case YPERR_ACCESS:
+      str = N_("Permission denied");
+      break;
+    case YPERR_BUSY:
+      str = N_("Database is busy");
+      break;
+    default:
+      str = N_("Unknown NIS error code");
+      break;
+    }
+  return _(str);
+}
+libnsl_hidden_nolink_def(yperr_string, GLIBC_2_0)
+
+static const int8_t yp_2_yperr[] =
+  {
+#define YP2YPERR(yp, yperr)  [YP_##yp - YP_VERS] = YPERR_##yperr
+    YP2YPERR (TRUE, SUCCESS),
+    YP2YPERR (NOMORE, NOMORE),
+    YP2YPERR (FALSE, YPERR),
+    YP2YPERR (NOMAP, MAP),
+    YP2YPERR (NODOM, DOMAIN),
+    YP2YPERR (NOKEY, KEY),
+    YP2YPERR (BADOP, YPERR),
+    YP2YPERR (BADDB, BADDB),
+    YP2YPERR (YPERR, YPERR),
+    YP2YPERR (BADARGS, BADARGS),
+    YP2YPERR (VERS, VERS)
+  };
+int
+ypprot_err (const int code)
+{
+  if (code < YP_VERS || code > YP_NOMORE)
+    return YPERR_YPERR;
+  return yp_2_yperr[code - YP_VERS];
+}
+libnsl_hidden_nolink_def (ypprot_err, GLIBC_2_0)
+
+const char *
+ypbinderr_string (const int error)
+{
+  const char *str;
+  switch (error)
+    {
+    case 0:
+      str = N_("Success");
+      break;
+    case YPBIND_ERR_ERR:
+      str = N_("Internal ypbind error");
+      break;
+    case YPBIND_ERR_NOSERV:
+      str = N_("Domain not bound");
+      break;
+    case YPBIND_ERR_RESC:
+      str = N_("System resource allocation failure");
+      break;
+    default:
+      str = N_("Unknown ypbind error");
+      break;
+    }
+  return _(str);
+}
+libnsl_hidden_nolink_def (ypbinderr_string, GLIBC_2_0)
+
+#define WINDOW 60
+
+int
+yp_update (char *domain, char *map, unsigned ypop,
+	   char *key, int keylen, char *data, int datalen)
+{
+  union
+    {
+      ypupdate_args update_args;
+      ypdelete_args delete_args;
+    }
+  args;
+  xdrproc_t xdr_argument;
+  unsigned res = 0;
+  CLIENT *clnt;
+  char *master;
+  struct sockaddr saddr;
+  char servername[MAXNETNAMELEN + 1];
+  int r;
+
+  if (!domain || !map || !key || (ypop != YPOP_DELETE && !data))
+    return YPERR_BADARGS;
+
+  args.update_args.mapname = map;
+  args.update_args.key.yp_buf_len = keylen;
+  args.update_args.key.yp_buf_val = key;
+  args.update_args.datum.yp_buf_len = datalen;
+  args.update_args.datum.yp_buf_val = data;
+
+  if ((r = yp_master (domain, map, &master)) != YPERR_SUCCESS)
+    return r;
+
+  if (!host2netname (servername, master, domain))
+    {
+      fputs (_("yp_update: cannot convert host to netname\n"), stderr);
+      free (master);
+      return YPERR_YPERR;
+    }
+
+  clnt = clnt_create (master, YPU_PROG, YPU_VERS, "tcp");
+
+  /* We do not need the string anymore.  */
+  free (master);
+
+  if (clnt == NULL)
+    {
+      clnt_pcreateerror ("yp_update: clnt_create");
+      return YPERR_RPC;
+    }
+
+  if (!clnt_control (clnt, CLGET_SERVER_ADDR, (char *) &saddr))
+    {
+      fputs (_("yp_update: cannot get server address\n"), stderr);
+      return YPERR_RPC;
+    }
+
+  switch (ypop)
+    {
+    case YPOP_CHANGE:
+    case YPOP_INSERT:
+    case YPOP_STORE:
+      xdr_argument = (xdrproc_t) xdr_ypupdate_args;
+      break;
+    case YPOP_DELETE:
+      xdr_argument = (xdrproc_t) xdr_ypdelete_args;
+      break;
+    default:
+      return YPERR_BADARGS;
+      break;
+    }
+
+  clnt->cl_auth = authdes_create (servername, WINDOW, &saddr, NULL);
+
+  if (clnt->cl_auth == NULL)
+    clnt->cl_auth = authunix_create_default ();
+
+again:
+  r = clnt_call (clnt, ypop, xdr_argument, (caddr_t) &args,
+		 (xdrproc_t) xdr_u_int, (caddr_t) &res, RPCTIMEOUT);
+
+  if (r == RPC_AUTHERROR)
+    {
+      if (clnt->cl_auth->ah_cred.oa_flavor == AUTH_DES)
+	{
+	  auth_destroy (clnt->cl_auth);
+	  clnt->cl_auth = authunix_create_default ();
+	  goto again;
+	}
+      else
+	return YPERR_ACCESS;
+    }
+  if (r != RPC_SUCCESS)
+    {
+      clnt_perror (clnt, "yp_update: clnt_call");
+      return YPERR_RPC;
+    }
+  return res;
+}
+libnsl_hidden_nolink_def(yp_update, GLIBC_2_0)
diff --git a/REORG.TODO/nis/ypupdate_xdr.c b/REORG.TODO/nis/ypupdate_xdr.c
new file mode 100644
index 0000000000..bbfb2fb683
--- /dev/null
+++ b/REORG.TODO/nis/ypupdate_xdr.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2010, Oracle America, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials
+ *       provided with the distribution.
+ *     * Neither the name of the "Oracle America, Inc." nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <rpcsvc/ypupd.h>
+#include <shlib-compat.h>
+
+bool_t
+xdr_yp_buf (XDR *xdrs, yp_buf *objp)
+{
+  return xdr_bytes (xdrs, (char **) &objp->yp_buf_val,
+		    (u_int *) &objp->yp_buf_len, ~0);
+}
+libnsl_hidden_nolink_def (xdr_yp_buf, GLIBC_2_0)
+
+bool_t
+xdr_ypupdate_args (XDR *xdrs, ypupdate_args *objp)
+{
+  if (!xdr_string (xdrs, &objp->mapname, ~0))
+    return FALSE;
+  if (!xdr_yp_buf (xdrs, &objp->key))
+    return FALSE;
+  return xdr_yp_buf (xdrs, &objp->datum);
+}
+libnsl_hidden_nolink_def (xdr_ypupdate_args, GLIBC_2_0)
+
+bool_t
+xdr_ypdelete_args (XDR *xdrs, ypdelete_args *objp)
+{
+  if (!xdr_string (xdrs, &objp->mapname, ~0))
+    return FALSE;
+  return xdr_yp_buf (xdrs, &objp->key);
+}
+libnsl_hidden_nolink_def (xdr_ypdelete_args, GLIBC_2_0)