about summary refs log tree commit diff
path: root/nss/nss_files/files-parse.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2009-04-23 18:29:30 +0000
committerUlrich Drepper <drepper@redhat.com>2009-04-23 18:29:30 +0000
commit829fea46179b8d5cf25f8eae0b78550e3539ad60 (patch)
tree6f89526d907c86329565d6ebc825aaf7a32fa1d1 /nss/nss_files/files-parse.c
parent5497de87c94539c327c8341f3633b99d5b2dd674 (diff)
downloadglibc-829fea46179b8d5cf25f8eae0b78550e3539ad60.tar.gz
glibc-829fea46179b8d5cf25f8eae0b78550e3539ad60.tar.xz
glibc-829fea46179b8d5cf25f8eae0b78550e3539ad60.zip
[BZ #9955]
2009-04-23  Ulrich Drepper  <drepper@redhat.com>
	[BZ #9955]
	* gshadow/Makefile: New file.
	* gshadow/Versions: New file.
	* gshadow/fgetsgent.c: New file.
	* gshadow/fgetsgent_r.c: New file.
	* gshadow/getsgent.c: New file.
	* gshadow/getsgent_r.c: New file.
	* gshadow/getsgnam.c: New file.
	* gshadow/getsgnam_r.c: New file.
	* gshadow/gshadow.h: New file.
	* gshadow/putsgent.c: New file.
	* gshadow/sgetsgent.c: New file.
	* gshadow/sgetsgent_r.c: New file.
	* gshadow/tst-gshadow.c: New file.
	* include/gshadow.h: New file.
	* Makeconfig (all-subdirs): Add gshadow.
	* Makefile (installed-headers): Add gshadow/gshadow.h.
	* nss/Makefile (databases): Add sgrp.
	* nss/Versions: Add gshadow functions as private exports.
	* nss/nsswitch.conf: Add gshadow entry.
	* nss/sgrp-lookup.c: New file.
	* nss/nss_files/files-parse.c: Add STRING_LIST macro.  Rewrite
	parse_list to handle STRING_LIST and TRAILING_LIST_PARSER.
	* nss/nss_files/files-sgrp.c: New file.
	* sysdeps/generic/paths.h: Add _PATH_GSHADOW.
	* sysdeps/unix/sysv/linux/paths.h: Likewise.
Diffstat (limited to 'nss/nss_files/files-parse.c')
-rw-r--r--nss/nss_files/files-parse.c88
1 files changed, 68 insertions, 20 deletions
diff --git a/nss/nss_files/files-parse.c b/nss/nss_files/files-parse.c
index 66615da26c..3603762f8e 100644
--- a/nss/nss_files/files-parse.c
+++ b/nss/nss_files/files-parse.c
@@ -103,6 +103,7 @@ parse_line (char *line, struct STRUCTURE *result,			      \
 	    EXTRA_ARGS_DECL)						      \
 {									      \
   ENTDATA_DECL (data)							      \
+  BUFFER_PREPARE							      \
   char *p = strpbrk (line, EOLSET "\n");				      \
   if (p != NULL)							      \
     *p = '\0';								      \
@@ -127,6 +128,21 @@ nss_files_parse_hidden_def (parse_line)
       }									      \
   }
 
+# define STRING_LIST(variable, terminator_c) \
+  {									      \
+    char **list = parse_list (&line, buf_start, buf_end, terminator_c,	      \
+			      errnop);					      \
+    if (list)								      \
+      variable = list;							      \
+    else								      \
+      return -1;		/* -1 indicates we ran out of space.  */      \
+									      \
+    /* Determine the new end of the buffer.  */				      \
+    while (*list != NULL)						      \
+      ++list;								      \
+    buf_start = (char *) (list + 1);					      \
+  }
+
 /* Helper function.  */
 static inline uint32_t
 __attribute__ ((always_inline))
@@ -178,12 +194,39 @@ strtou32 (const char *nptr, char **endptr, int base)
 
 
 # ifndef TRAILING_LIST_MEMBER
+#  define BUFFER_PREPARE /* Nothing to do.  */
 #  define TRAILING_LIST_PARSER /* Nothing to do.  */
 # else
 
-#  define TRAILING_LIST_PARSER						      \
+# define BUFFER_PREPARE \
+  char *buf_start = NULL;						      \
+  char *buf_end = (char *) data + datalen;				      \
+  if (line >= data->linebuffer && line < buf_end)			      \
+    /* Find the end of the line buffer, we will use the space in	      \
+       DATA after it for storing the vector of pointers.  */		      \
+    buf_start = strchr (line, '\0') + 1;				      \
+  else									      \
+    /* LINE does not point within DATA->linebuffer, so that space is	      \
+       not being used for scratch space right now.  We can use all of	      \
+       it for the pointer vector storage.  */				      \
+    buf_start = data->linebuffer;					      \
+
+#  define TRAILING_LIST_PARSER \
 {									      \
-  char **list = parse_list (line, data, datalen, errnop);		      \
+  if (buf_start == NULL)						      \
+    {									      \
+      if (line >= data->linebuffer && line < buf_end)			      \
+	/* Find the end of the line buffer, we will use the space in	      \
+	   DATA after it for storing the vector of pointers.  */	      \
+	buf_start = strchr (line, '\0') + 1;				      \
+      else								      \
+	/* LINE does not point within DATA->linebuffer, so that space is      \
+	   not being used for scratch space right now.  We can use all of     \
+	   it for the pointer vector storage.  */			      \
+	buf_start = data->linebuffer;					      \
+    }									      \
+									      \
+  char **list = parse_list (&line, buf_start, buf_end, '\0', errnop);	      \
   if (list)								      \
     result->TRAILING_LIST_MEMBER = list;				      \
   else 									      \
@@ -192,19 +235,12 @@ strtou32 (const char *nptr, char **endptr, int base)
 
 static inline char **
 __attribute ((always_inline))
-parse_list (char *line, struct parser_data *data, size_t datalen, int *errnop)
+parse_list (char **linep, char *eol, char *buf_end, int terminator_c,
+	    int *errnop)
 {
-  char *eol, **list, **p;
-
-  if (line >= data->linebuffer && line < (char *) data + datalen)
-    /* Find the end of the line buffer, we will use the space in DATA after
-       it for storing the vector of pointers.  */
-    eol = strchr (line, '\0') + 1;
-  else
-    /* LINE does not point within DATA->linebuffer, so that space is
-       not being used for scratch space right now.  We can use all of
-       it for the pointer vector storage.  */
-    eol = data->linebuffer;
+  char *line = *linep;
+  char **list, **p;
+
   /* Adjust the pointer so it is aligned for storing pointers.  */
   eol += __alignof__ (char *) - 1;
   eol -= (eol - (char *) 0) % __alignof__ (char *);
@@ -214,25 +250,30 @@ parse_list (char *line, struct parser_data *data, size_t datalen, int *errnop)
   p = list;
   while (1)
     {
-      char *elt;
-
-      if ((size_t) ((char *) &p[1] - (char *) data) > datalen)
+      if ((char *) (p + 2) > buf_end)
 	{
 	  /* We cannot fit another pointer in the buffer.  */
 	  *errnop = ERANGE;
 	  return NULL;
 	}
+
       if (*line == '\0')
 	break;
+      if (*line == terminator_c)
+	{
+	  ++line;
+	  break;
+	}
 
       /* Skip leading white space.  This might not be portable but useful.  */
       while (isspace (*line))
 	++line;
 
-      elt = line;
+      char *elt = line;
       while (1)
 	{
-	  if (*line == '\0' || TRAILING_LIST_SEPARATOR_P (*line))
+	  if (*line == '\0' || *line == terminator_c
+	      || TRAILING_LIST_SEPARATOR_P (*line))
 	    {
 	      /* End of the next entry.  */
 	      if (line > elt)
@@ -241,13 +282,20 @@ parse_list (char *line, struct parser_data *data, size_t datalen, int *errnop)
 
 	      /* Terminate string if necessary.  */
 	      if (*line != '\0')
-		*line++ = '\0';
+		{
+		  char endc = *line;
+		  *line++ = '\0';
+		  if (endc == terminator_c)
+		    goto out;
+		}
 	      break;
 	    }
 	  ++line;
 	}
     }
+ out:
   *p = NULL;
+  *linep = line;
 
   return list;
 }