(get_next_alias): Use __strcasecmp instead of strcasecmp.
[kopensolaris-gnu/glibc.git] / nss / nss_files / files-parse.c
index 1f3b138..198b359 100644 (file)
@@ -1,33 +1,45 @@
 /* Common code for file-based database parsers in nss_files module.
-Copyright (C) 1996 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
+   Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
 
-The GNU C Library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public License as
-published by the Free Software Foundation; either version 2 of the
-License, or (at your option) any later version.
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
 
-The GNU C Library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-Library General Public License for more details.
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
 
-You should have received a copy of the GNU Library General Public
-License along with the GNU C Library; see the file COPYING.LIB.  If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA.  */
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
 
 #include <ctype.h>
 #include <errno.h>
 #include <string.h>
 #include <stdlib.h>
 
+/* These symbols are defined by the including source file:
+
+   ENTNAME -- database name of the structure and functions (hostent, pwent).
+   STRUCTURE -- struct name, define only if not ENTNAME (passwd, group).
+   DATABASE -- string of the database file's name ("hosts", "passwd").
+
+   ENTDATA -- if defined, `struct ENTDATA' is used by the parser to store
+              things pointed to by the resultant `struct STRUCTURE'.
+
+   NEED_H_ERRNO - defined iff an arg `int *herrnop' is used.
+
+   Also see files-XXX.c.  */
 
 #define CONCAT(a,b) CONCAT1(a,b)
 #define CONCAT1(a,b) a##b
 
 #ifndef STRUCTURE
-#define STRUCTURE ENTNAME
+# define STRUCTURE ENTNAME
 #endif
 
 
@@ -35,9 +47,9 @@ struct parser_data
   {
 #ifdef ENTDATA
     struct ENTDATA entdata;
-#define ENTDATA_DECL(data) struct ENTDATA *const entdata = &data->entdata;
+# define ENTDATA_DECL(data) struct ENTDATA *const entdata = &data->entdata;
 #else
-#define ENTDATA_DECL(data)
+# define ENTDATA_DECL(data)
 #endif
     char linebuffer[0];
   };
@@ -45,11 +57,11 @@ struct parser_data
 #ifdef ENTDATA
 /* The function can't be exported, because the entdata structure
    is defined only in files-foo.c.  */
-#define parser_stclass static inline
+# define parser_stclass static inline
 #else
 /* Export the line parser function so it can be used in nss_db.  */
-#define parser_stclass /* Global */
-#define parse_line CONCAT(_nss_files_parse_,ENTNAME)
+# define parser_stclass /* Global */
+# define parse_line CONCAT(_nss_files_parse_,ENTNAME)
 #endif
 
 
@@ -57,22 +69,22 @@ struct parser_data
 
 /* The parser is defined in a different module.  */
 extern int parse_line (char *line, struct STRUCTURE *result,
-                      struct parser_data *data, int datalen);
+                      struct parser_data *data, size_t datalen, int *errnop);
 
-#define LINE_PARSER(EOLSET, BODY) /* Do nothing */
+# define LINE_PARSER(EOLSET, BODY) /* Do nothing */
 
 #else
 
 /* Define a line parsing function.  */
 
-#define LINE_PARSER(EOLSET, BODY)                                            \
+# define LINE_PARSER(EOLSET, BODY)                                           \
 parser_stclass int                                                           \
 parse_line (char *line, struct STRUCTURE *result,                            \
-           struct parser_data *data, int datalen)                            \
+           struct parser_data *data, size_t datalen, int *errnop)            \
 {                                                                            \
   ENTDATA_DECL (data)                                                        \
   char *p = strpbrk (line, EOLSET "\n");                                     \
-  if (p)                                                                     \
+  if (p != NULL)                                                             \
     *p = '\0';                                                               \
   BODY;                                                                              \
   TRAILING_LIST_PARSER;                                                              \
@@ -80,19 +92,21 @@ parse_line (char *line, struct STRUCTURE *result,                         \
 }
 
 
-#define STRING_FIELD(variable, terminator_p, swallow)                        \
+# define STRING_FIELD(variable, terminator_p, swallow)                       \
   {                                                                          \
     variable = line;                                                         \
-    while (!terminator_p (*line))                                            \
-      if (*++line == '\0')                                                   \
-       return 0;                                                             \
-    *line = '\0';                                                            \
-    do                                                                       \
+    while (*line != '\0' && !terminator_p (*line))                           \
       ++line;                                                                \
-    while (swallow && terminator_p (*line));                                 \
+    if (*line != '\0')                                                       \
+      {                                                                              \
+       *line = '\0';                                                         \
+       do                                                                    \
+         ++line;                                                             \
+       while (swallow && terminator_p (*line));                              \
+      }                                                                              \
   }
 
-#define INT_FIELD(variable, terminator_p, swallow, base, convert)            \
+# define INT_FIELD(variable, terminator_p, swallow, base, convert)           \
   {                                                                          \
     char *endp;                                                                      \
     variable = convert (strtol (line, &endp, base));                         \
@@ -107,24 +121,42 @@ parse_line (char *line, struct STRUCTURE *result,                       \
     line = endp;                                                             \
   }
 
-#define ISCOLON(c) ((c) == ':')
+# define INT_FIELD_MAYBE_NULL(variable, terminator_p, swallow, base, convert, default)       \
+  {                                                                          \
+    char *endp;                                                                      \
+    if (*line == '\0')                                                       \
+      /* We expect some more input, so don't allow the string to end here. */ \
+      return 0;                                                                      \
+    variable = convert (strtol (line, &endp, base));                         \
+    if (endp == line)                                                        \
+      variable = default;                                                    \
+    if (terminator_p (*endp))                                                \
+      do                                                                     \
+       ++endp;                                                               \
+      while (swallow && terminator_p (*endp));                               \
+    else if (*endp != '\0')                                                  \
+      return 0;                                                                      \
+    line = endp;                                                             \
+  }
+
+# define ISCOLON(c) ((c) == ':')
 
 
-#ifndef TRAILING_LIST_MEMBER
-#define TRAILING_LIST_PARSER /* Nothing to do.  */
-#else
+# ifndef TRAILING_LIST_MEMBER
+#  define TRAILING_LIST_PARSER /* Nothing to do.  */
+# else
 
-#define TRAILING_LIST_PARSER                                                 \
+#  define TRAILING_LIST_PARSER                                               \
 {                                                                            \
-  char **list = parse_list (line, data, datalen);                            \
+  char **list = parse_list (line, data, datalen, errnop);                    \
   if (list)                                                                  \
     result->TRAILING_LIST_MEMBER = list;                                     \
   else                                                                               \
-    return 0;                                                                \
+    return -1;         /* -1 indicates we ran out of space.  */              \
 }
 
 static inline char **
-parse_list (char *line, struct parser_data *data, int datalen)
+parse_list (char *line, struct parser_data *data, size_t datalen, int *errnop)
 {
   char *eol, **list, **p;
 
@@ -148,38 +180,35 @@ parse_list (char *line, struct parser_data *data, int datalen)
     {
       char *elt;
 
-      if ((char *) &p[1] - (char *) data > datalen)
+      if ((size_t) ((char *) &p[1] - (char *) data) > datalen)
        {
          /* We cannot fit another pointer in the buffer.  */
-         errno = ERANGE;
+         *errnop = ERANGE;
          return NULL;
        }
       if (*line == '\0')
        break;
 
+      /* Skip leading white space.  This might not be portable but useful.  */
+      while (isspace (*line))
+       ++line;
+
       elt = line;
       while (1)
        {
-         if (TRAILING_LIST_SEPARATOR_P (*line))
-           {
-             *p++ = elt;
-             *line = '\0';
-             do
-               ++line;
-             while (TRAILING_LIST_SEPARATOR_P (*line));
-             elt = line;
-           }
-         else if (*line == '\0' || *line == '\n')
+         if (*line == '\0' || TRAILING_LIST_SEPARATOR_P (*line))
            {
-             /* End of the line.  */
+             /* End of the next entry.  */
              if (line > elt)
-               /* Last element.  */
+               /* We really found some data.  */
                *p++ = elt;
-             *line = '\0';
+
+             /* Terminate string if necessary.  */
+             if (*line != '\0')
+               *line++ = '\0';
              break;
            }
-         else
-           ++line;
+         ++line;
        }
     }
   *p = NULL;
@@ -187,6 +216,7 @@ parse_list (char *line, struct parser_data *data, int datalen)
   return list;
 }
 
+# endif        /* TRAILING_LIST_MEMBER */
 #endif /* EXTERN_PARSER */
 
 
@@ -202,9 +232,20 @@ parse_list (char *line, struct parser_data *data, int datalen)
     break;                                                                   \
 }
 
-#endif
+#define LOOKUP_NAME_CASE(nameelt, aliaselt)                                  \
+{                                                                            \
+  char **ap;                                                                 \
+  if (! strcasecmp (name, result->nameelt))                                  \
+    break;                                                                   \
+  for (ap = result->aliaselt; *ap; ++ap)                                     \
+    if (! strcasecmp (name, *ap))                                            \
+      break;                                                                 \
+  if (*ap)                                                                   \
+    break;                                                                   \
+}
+
 
 /* This is defined by db-*.c to include "../nss_db/db-XXX.c" instead.  */
 #ifndef GENERIC
-#define GENERIC "files-XXX.c"
+# define GENERIC "files-XXX.c"
 #endif