about summary refs log tree commit diff
path: root/REORG.TODO/pwd
diff options
context:
space:
mode:
authorZack Weinberg <zackw@panix.com>2017-06-08 15:39:03 -0400
committerZack Weinberg <zackw@panix.com>2017-06-08 15:39:03 -0400
commit5046dbb4a7eba5eccfd258f92f4735c9ffc8d069 (patch)
tree4470480d904b65cf14ca524f96f79eca818c3eaf /REORG.TODO/pwd
parent199fc19d3aaaf57944ef036e15904febe877fc93 (diff)
downloadglibc-zack/build-layout-experiment.tar.gz
glibc-zack/build-layout-experiment.tar.xz
glibc-zack/build-layout-experiment.zip
Prepare for radical source tree reorganization. zack/build-layout-experiment
All top-level files and directories are moved into a temporary storage
directory, REORG.TODO, except for files that will certainly still
exist in their current form at top level when we're done (COPYING,
COPYING.LIB, LICENSES, NEWS, README), all old ChangeLog files (which
are moved to the new directory OldChangeLogs, instead), and the
generated file INSTALL (which is just deleted; in the new order, there
will be no generated files checked into version control).
Diffstat (limited to 'REORG.TODO/pwd')
-rw-r--r--REORG.TODO/pwd/Makefile42
-rw-r--r--REORG.TODO/pwd/Versions19
-rw-r--r--REORG.TODO/pwd/fgetpwent.c84
-rw-r--r--REORG.TODO/pwd/fgetpwent_r.c110
-rw-r--r--REORG.TODO/pwd/getpw.c62
-rw-r--r--REORG.TODO/pwd/getpwent.c29
-rw-r--r--REORG.TODO/pwd/getpwent_r.c29
-rw-r--r--REORG.TODO/pwd/getpwnam.c29
-rw-r--r--REORG.TODO/pwd/getpwnam_r.c29
-rw-r--r--REORG.TODO/pwd/getpwuid.c29
-rw-r--r--REORG.TODO/pwd/getpwuid_r.c29
-rw-r--r--REORG.TODO/pwd/putpwent.c64
-rw-r--r--REORG.TODO/pwd/pwd.h188
-rw-r--r--REORG.TODO/pwd/tst-getpw.c114
-rw-r--r--REORG.TODO/pwd/tst-putpwent.c168
15 files changed, 1025 insertions, 0 deletions
diff --git a/REORG.TODO/pwd/Makefile b/REORG.TODO/pwd/Makefile
new file mode 100644
index 0000000000..05426a4cb1
--- /dev/null
+++ b/REORG.TODO/pwd/Makefile
@@ -0,0 +1,42 @@
+# Copyright (C) 1991-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/>.
+
+#
+#	Sub-makefile for pwd portion of the library.
+#
+subdir	:= pwd
+
+include ../Makeconfig
+
+headers := pwd.h
+
+routines := fgetpwent getpw putpwent \
+	    getpwent getpwnam getpwuid \
+	    getpwent_r getpwnam_r getpwuid_r fgetpwent_r
+
+tests := tst-getpw tst-putpwent
+
+include ../Rules
+
+ifeq ($(have-thread-library),yes)
+
+CFLAGS-getpwent_r.c = -fexceptions
+CFLAGS-getpwent.c = -fexceptions
+CFLAGS-getpw.c = -fexceptions
+CFLAGS-fgetpwent_r.c = $(libio-mtsafe)
+
+endif
diff --git a/REORG.TODO/pwd/Versions b/REORG.TODO/pwd/Versions
new file mode 100644
index 0000000000..b56970019a
--- /dev/null
+++ b/REORG.TODO/pwd/Versions
@@ -0,0 +1,19 @@
+libc {
+  GLIBC_2.0 {
+    # e*
+    endpwent;
+
+    # f*
+    fgetpwent; fgetpwent_r;
+
+    # g*
+    getpw; getpwent; getpwent_r; getpwnam; getpwnam_r; getpwuid; getpwuid_r;
+
+    # p*
+    putpwent; setpwent;
+  }
+  GLIBC_2.1.2 {
+    # g*
+    getpwent_r; getpwuid_r; getpwnam_r;
+  }
+}
diff --git a/REORG.TODO/pwd/fgetpwent.c b/REORG.TODO/pwd/fgetpwent.c
new file mode 100644
index 0000000000..40fd67d068
--- /dev/null
+++ b/REORG.TODO/pwd/fgetpwent.c
@@ -0,0 +1,84 @@
+/* Copyright (C) 1991-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 <errno.h>
+#include <libc-lock.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+/* We need to protect the dynamic buffer handling.  */
+__libc_lock_define_initialized (static, lock);
+
+libc_freeres_ptr (static char *buffer);
+
+/* Read one entry from the given stream.  */
+struct passwd *
+fgetpwent (FILE *stream)
+{
+  static size_t buffer_size;
+  static struct passwd resbuf;
+  fpos_t pos;
+  struct passwd *result;
+  int save;
+
+  if (fgetpos (stream, &pos) != 0)
+    return NULL;
+
+  /* Get lock.  */
+  __libc_lock_lock (lock);
+
+  /* Allocate buffer if not yet available.  */
+  if (buffer == NULL)
+    {
+      buffer_size = NSS_BUFLEN_PASSWD;
+      buffer = malloc (buffer_size);
+    }
+
+  while (buffer != NULL
+	 && (__fgetpwent_r (stream, &resbuf, buffer, buffer_size, &result)
+	     == ERANGE))
+    {
+      char *new_buf;
+      buffer_size += NSS_BUFLEN_PASSWD;
+      new_buf = realloc (buffer, buffer_size);
+      if (new_buf == NULL)
+	{
+	  /* We are out of memory.  Free the current buffer so that the
+	     process gets a chance for a normal termination.  */
+	  save = errno;
+	  free (buffer);
+	  __set_errno (save);
+	}
+      buffer = new_buf;
+
+      /* Reset the stream.  */
+      if (fsetpos (stream, &pos) != 0)
+	buffer = NULL;
+    }
+
+  if (buffer == NULL)
+    result = NULL;
+
+  /* Release lock.  Preserve error value.  */
+  save = errno;
+  __libc_lock_unlock (lock);
+  __set_errno (save);
+
+  return result;
+}
diff --git a/REORG.TODO/pwd/fgetpwent_r.c b/REORG.TODO/pwd/fgetpwent_r.c
new file mode 100644
index 0000000000..8aa8f69372
--- /dev/null
+++ b/REORG.TODO/pwd/fgetpwent_r.c
@@ -0,0 +1,110 @@
+/* Copyright (C) 1991-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 <pwd.h>
+
+#define flockfile(s) _IO_flockfile (s)
+#define funlockfile(s) _IO_funlockfile (s)
+
+/* Define a line parsing function using the common code
+   used in the nss_files module.  */
+
+#define STRUCTURE	passwd
+#define ENTNAME		pwent
+struct pwent_data {};
+
+#include <nss/nss_files/files-parse.c>
+LINE_PARSER
+(,
+ STRING_FIELD (result->pw_name, ISCOLON, 0);
+ if (line[0] == '\0'
+     && (result->pw_name[0] == '+' || result->pw_name[0] == '-'))
+   {
+     /* This a special case.  We allow lines containing only a `+' sign
+	since this is used for nss_compat.  All other services will
+	reject this entry later.  Initialize all other fields now.  */
+     result->pw_passwd = NULL;
+     result->pw_uid = 0;
+     result->pw_gid = 0;
+     result->pw_gecos = NULL;
+     result->pw_dir = NULL;
+     result->pw_shell = NULL;
+   }
+ else
+   {
+     STRING_FIELD (result->pw_passwd, ISCOLON, 0);
+     if (result->pw_name[0] == '+' || result->pw_name[0] == '-')
+       {
+	 INT_FIELD_MAYBE_NULL (result->pw_uid, ISCOLON, 0, 10, , 0)
+	 INT_FIELD_MAYBE_NULL (result->pw_gid, ISCOLON, 0, 10, , 0)
+       }
+     else
+       {
+	 INT_FIELD (result->pw_uid, ISCOLON, 0, 10,)
+	 INT_FIELD (result->pw_gid, ISCOLON, 0, 10,)
+       }
+     STRING_FIELD (result->pw_gecos, ISCOLON, 0);
+     STRING_FIELD (result->pw_dir, ISCOLON, 0);
+     result->pw_shell = line;
+   }
+ )
+
+
+/* Read one entry from the given stream.  */
+int
+__fgetpwent_r (FILE *stream, struct passwd *resbuf, char *buffer,
+	       size_t buflen, struct passwd **result)
+{
+  char *p;
+
+  flockfile (stream);
+  do
+    {
+      buffer[buflen - 1] = '\xff';
+      p = fgets_unlocked (buffer, buflen, stream);
+      if (p == NULL && feof_unlocked (stream))
+	{
+	  funlockfile (stream);
+	  *result = NULL;
+	  __set_errno (ENOENT);
+	  return errno;
+	}
+      if (p == NULL || buffer[buflen - 1] != '\xff')
+	{
+	  funlockfile (stream);
+	  *result = NULL;
+	  __set_errno (ERANGE);
+	  return errno;
+	}
+
+      /* 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_line (p, resbuf, (void *) buffer, buflen, &errno));
+
+  funlockfile (stream);
+
+  *result = resbuf;
+  return 0;
+}
+weak_alias (__fgetpwent_r, fgetpwent_r)
diff --git a/REORG.TODO/pwd/getpw.c b/REORG.TODO/pwd/getpw.c
new file mode 100644
index 0000000000..0a73f2832a
--- /dev/null
+++ b/REORG.TODO/pwd/getpw.c
@@ -0,0 +1,62 @@
+/* Copyright (C) 1991-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 <alloca.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <pwd.h>
+
+
+/* Re-construct the password-file line for the given uid
+   in the given buffer.  This knows the format that the caller
+   will expect, but this need not be the format of the password file.  */
+
+int __getpw (__uid_t uid, char *buf);
+
+int
+__getpw (__uid_t uid, char *buf)
+{
+  size_t buflen;
+  char *tmpbuf;
+  struct passwd resbuf, *p;
+
+  if (buf == NULL)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  buflen = __sysconf (_SC_GETPW_R_SIZE_MAX);
+  tmpbuf = alloca (buflen);
+
+  if (__getpwuid_r (uid, &resbuf, tmpbuf, buflen, &p) != 0)
+    return -1;
+
+  if (p == NULL)
+    return -1;
+
+  if (sprintf (buf, "%s:%s:%lu:%lu:%s:%s:%s", p->pw_name, p->pw_passwd,
+	       (unsigned long int) p->pw_uid, (unsigned long int) p->pw_gid,
+	       p->pw_gecos, p->pw_dir, p->pw_shell) < 0)
+    return -1;
+
+  return 0;
+}
+weak_alias (__getpw, getpw)
+
+link_warning (getpw, "the `getpw' function is dangerous and should not be used.")
diff --git a/REORG.TODO/pwd/getpwent.c b/REORG.TODO/pwd/getpwent.c
new file mode 100644
index 0000000000..a42c33d859
--- /dev/null
+++ b/REORG.TODO/pwd/getpwent.c
@@ -0,0 +1,29 @@
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU 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>
+
+
+#define LOOKUP_TYPE	struct passwd
+#define SETFUNC_NAME	setpwent
+#define	GETFUNC_NAME	getpwent
+#define	ENDFUNC_NAME	endpwent
+#define DATABASE_NAME	passwd
+#define BUFLEN		NSS_BUFLEN_PASSWD
+
+#include "../nss/getXXent.c"
diff --git a/REORG.TODO/pwd/getpwent_r.c b/REORG.TODO/pwd/getpwent_r.c
new file mode 100644
index 0000000000..963c9734a7
--- /dev/null
+++ b/REORG.TODO/pwd/getpwent_r.c
@@ -0,0 +1,29 @@
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU 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>
+
+
+#define LOOKUP_TYPE	struct passwd
+#define SETFUNC_NAME	setpwent
+#define	GETFUNC_NAME	getpwent
+#define	ENDFUNC_NAME	endpwent
+#define DATABASE_NAME	passwd
+#define BUFLEN		NSS_BUFLEN_PASSWD
+
+#include "../nss/getXXent_r.c"
diff --git a/REORG.TODO/pwd/getpwnam.c b/REORG.TODO/pwd/getpwnam.c
new file mode 100644
index 0000000000..96b2dd2022
--- /dev/null
+++ b/REORG.TODO/pwd/getpwnam.c
@@ -0,0 +1,29 @@
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU 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>
+
+
+#define LOOKUP_TYPE	struct passwd
+#define FUNCTION_NAME	getpwnam
+#define DATABASE_NAME	passwd
+#define ADD_PARAMS	const char *name
+#define ADD_VARIABLES	name
+#define BUFLEN		NSS_BUFLEN_PASSWD
+
+#include "../nss/getXXbyYY.c"
diff --git a/REORG.TODO/pwd/getpwnam_r.c b/REORG.TODO/pwd/getpwnam_r.c
new file mode 100644
index 0000000000..1df0425d54
--- /dev/null
+++ b/REORG.TODO/pwd/getpwnam_r.c
@@ -0,0 +1,29 @@
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU 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>
+
+
+#define LOOKUP_TYPE	struct passwd
+#define FUNCTION_NAME	getpwnam
+#define DATABASE_NAME	passwd
+#define ADD_PARAMS	const char *name
+#define ADD_VARIABLES	name
+#define BUFLEN		NSS_BUFLEN_PASSWD
+
+#include <nss/getXXbyYY_r.c>
diff --git a/REORG.TODO/pwd/getpwuid.c b/REORG.TODO/pwd/getpwuid.c
new file mode 100644
index 0000000000..08e2b71395
--- /dev/null
+++ b/REORG.TODO/pwd/getpwuid.c
@@ -0,0 +1,29 @@
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU 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>
+
+
+#define LOOKUP_TYPE	struct passwd
+#define FUNCTION_NAME	getpwuid
+#define DATABASE_NAME	passwd
+#define ADD_PARAMS	uid_t uid
+#define ADD_VARIABLES	uid
+#define BUFLEN		NSS_BUFLEN_PASSWD
+
+#include "../nss/getXXbyYY.c"
diff --git a/REORG.TODO/pwd/getpwuid_r.c b/REORG.TODO/pwd/getpwuid_r.c
new file mode 100644
index 0000000000..d439a9fca7
--- /dev/null
+++ b/REORG.TODO/pwd/getpwuid_r.c
@@ -0,0 +1,29 @@
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU 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>
+
+
+#define LOOKUP_TYPE	struct passwd
+#define FUNCTION_NAME	getpwuid
+#define DATABASE_NAME	passwd
+#define ADD_PARAMS	uid_t uid
+#define ADD_VARIABLES	uid
+#define BUFLEN		NSS_BUFLEN_PASSWD
+
+#include <nss/getXXbyYY_r.c>
diff --git a/REORG.TODO/pwd/putpwent.c b/REORG.TODO/pwd/putpwent.c
new file mode 100644
index 0000000000..61feb9a01b
--- /dev/null
+++ b/REORG.TODO/pwd/putpwent.c
@@ -0,0 +1,64 @@
+/* Copyright (C) 1991-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 <errno.h>
+#include <stdio.h>
+#include <pwd.h>
+#include <nss.h>
+
+#define _S(x)	x ?: ""
+
+/* Write an entry to the given stream.  This must know the format of
+   the password file.  If the input contains invalid characters,
+   return EINVAL, or replace them with spaces (if they are contained
+   in the GECOS field).  */
+int
+putpwent (const struct passwd *p, FILE *stream)
+{
+  if (p == NULL || stream == NULL
+      || p->pw_name == NULL || !__nss_valid_field (p->pw_name)
+      || !__nss_valid_field (p->pw_passwd)
+      || !__nss_valid_field (p->pw_dir)
+      || !__nss_valid_field (p->pw_shell))
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  int ret;
+  char *gecos_alloc;
+  const char *gecos = __nss_rewrite_field (p->pw_gecos, &gecos_alloc);
+
+  if (gecos == NULL)
+    return -1;
+
+  if (p->pw_name[0] == '+' || p->pw_name[0] == '-')
+      ret = fprintf (stream, "%s:%s:::%s:%s:%s\n",
+		     p->pw_name, _S (p->pw_passwd),
+		     gecos, _S (p->pw_dir), _S (p->pw_shell));
+  else
+      ret = fprintf (stream, "%s:%s:%lu:%lu:%s:%s:%s\n",
+		     p->pw_name, _S (p->pw_passwd),
+		     (unsigned long int) p->pw_uid,
+		     (unsigned long int) p->pw_gid,
+		     gecos, _S (p->pw_dir), _S (p->pw_shell));
+
+  free (gecos_alloc);
+  if (ret >= 0)
+    ret = 0;
+  return ret;
+}
diff --git a/REORG.TODO/pwd/pwd.h b/REORG.TODO/pwd/pwd.h
new file mode 100644
index 0000000000..100f33eb4e
--- /dev/null
+++ b/REORG.TODO/pwd/pwd.h
@@ -0,0 +1,188 @@
+/* Copyright (C) 1991-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/>.  */
+
+/*
+ *	POSIX Standard: 9.2.2 User Database Access	<pwd.h>
+ */
+
+#ifndef	_PWD_H
+#define	_PWD_H	1
+
+#include <features.h>
+
+__BEGIN_DECLS
+
+#include <bits/types.h>
+
+#define __need_size_t
+#include <stddef.h>
+
+#if defined __USE_XOPEN || defined __USE_XOPEN2K
+/* The Single Unix specification says that some more types are
+   available here.  */
+# ifndef __gid_t_defined
+typedef __gid_t gid_t;
+#  define __gid_t_defined
+# endif
+
+# ifndef __uid_t_defined
+typedef __uid_t uid_t;
+#  define __uid_t_defined
+# endif
+#endif
+
+/* The passwd structure.  */
+struct passwd
+{
+  char *pw_name;		/* Username.  */
+  char *pw_passwd;		/* Password.  */
+  __uid_t pw_uid;		/* User ID.  */
+  __gid_t pw_gid;		/* Group ID.  */
+  char *pw_gecos;		/* Real name.  */
+  char *pw_dir;			/* Home directory.  */
+  char *pw_shell;		/* Shell program.  */
+};
+
+
+#ifdef __USE_MISC
+# include <bits/types/FILE.h>
+#endif
+
+
+#if defined __USE_MISC || defined __USE_XOPEN_EXTENDED
+/* Rewind the password-file stream.
+
+   This function is a possible cancellation point and therefore not
+   marked with __THROW.  */
+extern void setpwent (void);
+
+/* Close the password-file stream.
+
+   This function is a possible cancellation point and therefore not
+   marked with __THROW.  */
+extern void endpwent (void);
+
+/* Read an entry from the password-file stream, opening it if necessary.
+
+   This function is a possible cancellation point and therefore not
+   marked with __THROW.  */
+extern struct passwd *getpwent (void);
+#endif
+
+#ifdef	__USE_MISC
+/* Read an entry from STREAM.
+
+   This function is not part of POSIX and therefore no official
+   cancellation point.  But due to similarity with an POSIX interface
+   or due to the implementation it is a cancellation point and
+   therefore not marked with __THROW.  */
+extern struct passwd *fgetpwent (FILE *__stream) __nonnull ((1));
+
+/* Write the given entry onto the given stream.
+
+   This function is not part of POSIX and therefore no official
+   cancellation point.  But due to similarity with an POSIX interface
+   or due to the implementation it is a cancellation point and
+   therefore not marked with __THROW.  */
+extern int putpwent (const struct passwd *__restrict __p,
+		     FILE *__restrict __f);
+#endif
+
+/* Search for an entry with a matching user ID.
+
+   This function is a possible cancellation point and therefore not
+   marked with __THROW.  */
+extern struct passwd *getpwuid (__uid_t __uid);
+
+/* Search for an entry with a matching username.
+
+   This function is a possible cancellation point and therefore not
+   marked with __THROW.  */
+extern struct passwd *getpwnam (const char *__name) __nonnull ((1));
+
+#ifdef __USE_POSIX
+
+# ifdef __USE_MISC
+/* Reasonable value for the buffer sized used in the reentrant
+   functions below.  But better use `sysconf'.  */
+#  define NSS_BUFLEN_PASSWD	1024
+# endif
+
+/* Reentrant versions of some of the functions above.
+
+   PLEASE NOTE: the `getpwent_r' function is not (yet) standardized.
+   The interface may change in later versions of this library.  But
+   the interface is designed following the principals used for the
+   other reentrant functions so the chances are good this is what the
+   POSIX people would choose.  */
+
+# ifdef __USE_MISC
+/* This function is not part of POSIX and therefore no official
+   cancellation point.  But due to similarity with an POSIX interface
+   or due to the implementation it is a cancellation point and
+   therefore not marked with __THROW.  */
+extern int getpwent_r (struct passwd *__restrict __resultbuf,
+		       char *__restrict __buffer, size_t __buflen,
+		       struct passwd **__restrict __result)
+		       __nonnull ((1, 2, 4));
+# endif
+
+extern int getpwuid_r (__uid_t __uid,
+		       struct passwd *__restrict __resultbuf,
+		       char *__restrict __buffer, size_t __buflen,
+		       struct passwd **__restrict __result)
+		       __nonnull ((2, 3, 5));
+
+extern int getpwnam_r (const char *__restrict __name,
+		       struct passwd *__restrict __resultbuf,
+		       char *__restrict __buffer, size_t __buflen,
+		       struct passwd **__restrict __result)
+		       __nonnull ((1, 2, 3, 5));
+
+
+# ifdef	__USE_MISC
+/* Read an entry from STREAM.  This function is not standardized and
+   probably never will.
+
+   This function is not part of POSIX and therefore no official
+   cancellation point.  But due to similarity with an POSIX interface
+   or due to the implementation it is a cancellation point and
+   therefore not marked with __THROW.  */
+extern int fgetpwent_r (FILE *__restrict __stream,
+			struct passwd *__restrict __resultbuf,
+			char *__restrict __buffer, size_t __buflen,
+			struct passwd **__restrict __result)
+			__nonnull ((1, 2, 3, 5));
+# endif
+
+#endif	/* POSIX or reentrant */
+
+#ifdef __USE_GNU
+/* Re-construct the password-file line for the given uid
+   in the given buffer.  This knows the format that the caller
+   will expect, but this need not be the format of the password file.
+
+   This function is not part of POSIX and therefore no official
+   cancellation point.  But due to similarity with an POSIX interface
+   or due to the implementation it is a cancellation point and
+   therefore not marked with __THROW.  */
+extern int getpw (__uid_t __uid, char *__buffer);
+#endif
+
+__END_DECLS
+
+#endif /* pwd.h  */
diff --git a/REORG.TODO/pwd/tst-getpw.c b/REORG.TODO/pwd/tst-getpw.c
new file mode 100644
index 0000000000..c90c4ed34b
--- /dev/null
+++ b/REORG.TODO/pwd/tst-getpw.c
@@ -0,0 +1,114 @@
+/* Copyright (C) 1999-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 <stdio.h>
+#include <pwd.h>
+#include <errno.h>
+#include <stdbool.h>
+
+/* We want to test getpw by calling it with a uid that does
+   exist and one that doesn't exist. We track if we've met those
+   conditions and exit. We also track if we've failed due to lack
+   of memory. That constitutes all of the standard failure cases.  */
+bool seen_hit;
+bool seen_miss;
+bool seen_oom;
+
+/* How many errors we've had while running the test.  */
+int errors;
+
+static void
+check (uid_t uid)
+{
+  int ret;
+  char buf[1024];
+
+  ret = getpw (uid, buf);
+
+  /* Successfully read a password line.  */
+  if (ret == 0 && !seen_hit)
+    {
+      printf ("PASS: Read a password line given a uid.\n");
+      seen_hit = true;
+    }
+
+  /* Failed to read a password line. Why?  */
+  if (ret == -1)
+    {
+      /* No entry?  Technically the errno could be any number
+	 of values including ESRCH, EBADP or EPERM depending
+	 on the quality of the nss module that implements the
+	 underlying lookup. It should be 0 for getpw.*/
+      if (errno == 0 && !seen_miss)
+	{
+	  printf ("PASS: Found an invalid uid.\n");
+	  seen_miss = true;
+	  return;
+	}
+
+      /* Out of memory?  */
+      if (errno == ENOMEM && !seen_oom)
+	{
+	  printf ("FAIL: Failed with ENOMEM.\n");
+	  seen_oom = true;
+	  errors++;
+	}
+
+      /* We don't expect any other values for errno.  */
+      if (errno != ENOMEM && errno != 0)
+	errors++;
+    }
+}
+
+static int
+do_test (void)
+{
+  int ret;
+  uid_t uid;
+
+  /* Should return -1 and set errnot to EINVAL.  */
+  ret = getpw (0, NULL);
+  if (ret == -1 && errno == EINVAL)
+    {
+      printf ("PASS: NULL buffer returns -1 and sets errno to EINVAL.\n");
+    }
+  else
+    {
+      printf ("FAIL: NULL buffer did not return -1 or set errno to EINVAL.\n");
+      errors++;
+    }
+
+  /* Look for one matching uid, one non-found uid and then stop.
+     Set an upper limit at the 16-bit UID mark; no need to go farther.  */
+  for (uid = 0; uid < ((uid_t) 65535); ++uid)
+    {
+      check (uid);
+      if (seen_miss && seen_hit)
+	break;
+    }
+
+  if (!seen_hit)
+    printf ("FAIL: Did not read even one password line given a uid.\n");
+
+  if (!seen_miss)
+    printf ("FAIL: Did not find even one invalid uid.\n");
+
+  return errors;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/REORG.TODO/pwd/tst-putpwent.c b/REORG.TODO/pwd/tst-putpwent.c
new file mode 100644
index 0000000000..7eafd0eb73
--- /dev/null
+++ b/REORG.TODO/pwd/tst-putpwent.c
@@ -0,0 +1,168 @@
+/* Test for processing of invalid passwd entries.  [BZ #18724]
+   Copyright (C) 2015-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 <errno.h>
+#include <pwd.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+static bool errors;
+
+static void
+check (struct passwd p, const char *expected)
+{
+  char *buf;
+  size_t buf_size;
+  FILE *f = open_memstream (&buf, &buf_size);
+
+  if (f == NULL)
+    {
+      printf ("open_memstream: %m\n");
+      errors = true;
+      return;
+    }
+
+  int ret = putpwent (&p, f);
+
+  if (expected == NULL)
+    {
+      if (ret == -1)
+	{
+	  if (errno != EINVAL)
+	    {
+	      printf ("putpwent: unexpected error code: %m\n");
+	      errors = true;
+	    }
+	}
+      else
+	{
+	  printf ("putpwent: unexpected success (\"%s\")\n", p.pw_name);
+	  errors = true;
+	}
+    }
+  else
+    {
+      /* Expect success.  */
+      size_t expected_length = strlen (expected);
+      if (ret == 0)
+	{
+	  long written = ftell (f);
+
+	  if (written <= 0 || fflush (f) < 0)
+	    {
+	      printf ("stream error: %m\n");
+	      errors = true;
+	    }
+	  else if (buf[written - 1] != '\n')
+	    {
+	      printf ("FAILED: \"%s\" without newline\n", expected);
+	      errors = true;
+	    }
+	  else if (strncmp (buf, expected, written - 1) != 0
+		   || written - 1 != expected_length)
+	    {
+	      printf ("FAILED: \"%s\" (%ld), expected \"%s\" (%zu)\n",
+		      buf, written - 1, expected, expected_length);
+	      errors = true;
+	    }
+	}
+      else
+	{
+	  printf ("FAILED: putpwent (expected \"%s\"): %m\n", expected);
+	  errors = true;
+	}
+    }
+
+  fclose (f);
+  free (buf);
+}
+
+static int
+do_test (void)
+{
+  check ((struct passwd) {
+      .pw_name = (char *) "root",
+    },
+    "root::0:0:::");
+  check ((struct passwd) {
+      .pw_name = (char *) "root",
+      .pw_passwd = (char *) "password",
+    },
+    "root:password:0:0:::");
+  check ((struct passwd) {
+      .pw_name = (char *) "root",
+      .pw_passwd = (char *) "password",
+      .pw_uid = 12,
+      .pw_gid = 34,
+      .pw_gecos = (char *) "gecos",
+      .pw_dir = (char *) "home",
+      .pw_shell = (char *) "shell",
+    },
+    "root:password:12:34:gecos:home:shell");
+  check ((struct passwd) {
+      .pw_name = (char *) "root",
+      .pw_passwd = (char *) "password",
+      .pw_uid = 12,
+      .pw_gid = 34,
+      .pw_gecos = (char *) ":ge\n:cos\n",
+      .pw_dir = (char *) "home",
+      .pw_shell = (char *) "shell",
+    },
+    "root:password:12:34: ge  cos :home:shell");
+
+  /* Bad values.  */
+  {
+    static const char *const bad_strings[] = {
+      ":",
+      "\n",
+      ":bad",
+      "\nbad",
+      "b:ad",
+      "b\nad",
+      "bad:",
+      "bad\n",
+      "b:a\nd",
+      NULL
+    };
+    for (const char *const *bad = bad_strings; *bad != NULL; ++bad)
+      {
+	check ((struct passwd) {
+	    .pw_name = (char *) *bad,
+	  }, NULL);
+	check ((struct passwd) {
+	    .pw_name = (char *) "root",
+	    .pw_passwd = (char *) *bad,
+	  }, NULL);
+	check ((struct passwd) {
+	    .pw_name = (char *) "root",
+	    .pw_dir = (char *) *bad,
+	  }, NULL);
+	check ((struct passwd) {
+	    .pw_name = (char *) "root",
+	    .pw_shell = (char *) *bad,
+	  }, NULL);
+      }
+  }
+
+  return errors > 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"