aboutsummaryrefslogtreecommitdiff
path: root/nss
diff options
context:
space:
mode:
Diffstat (limited to 'nss')
-rw-r--r--nss/Makefile8
-rw-r--r--nss/alias-lookup.c22
-rw-r--r--nss/databases.def32
-rw-r--r--nss/getXXbyYY.c72
-rw-r--r--nss/getXXbyYY_r.c2
-rw-r--r--nss/getXXent.c71
-rw-r--r--nss/getXXent_r.c2
-rw-r--r--nss/nss_db/db-XXX.c32
-rw-r--r--nss/nss_db/db-alias.c235
-rw-r--r--nss/nss_files/files-XXX.c120
-rw-r--r--nss/nss_files/files-alias.c424
-rw-r--r--nss/nss_files/files-parse.c42
12 files changed, 914 insertions, 148 deletions
diff --git a/nss/Makefile b/nss/Makefile
index 93ffbaee34..9193cf2214 100644
--- a/nss/Makefile
+++ b/nss/Makefile
@@ -12,9 +12,9 @@
# Library General Public License for more details.
# You should have received a copy of the GNU Library General Public
-# License along with the GNU C Library; see the file COPYING.LIB. If
-# not, write to the Free Software Foundation, Inc.,
-# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# 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.
#
# Makefile for name service switch.
@@ -33,7 +33,7 @@ routines = nsswitch $(addsuffix -lookup,$(databases))
# Caution: if you add a database here, you must add its real name
# in databases.def, too.
databases = proto service hosts network grp pwd rpc ethers \
- spwd netgrp key
+ spwd netgrp key alias
# Specify rules for the nss_* modules. We have some services.
services := files dns db
diff --git a/nss/alias-lookup.c b/nss/alias-lookup.c
new file mode 100644
index 0000000000..6a1244eea7
--- /dev/null
+++ b/nss/alias-lookup.c
@@ -0,0 +1,22 @@
+/* Copyright (C) 1996 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 Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#define DATABASE_NAME aliases
+
+#include "XXX-lookup.c"
diff --git a/nss/databases.def b/nss/databases.def
index 8a5ede2a58..2ab892258d 100644
--- a/nss/databases.def
+++ b/nss/databases.def
@@ -1,25 +1,26 @@
/* List of all databases defined for the NSS in GNU C Library.
-Copyright (C) 1996 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
-Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+ Copyright (C) 1996 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 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., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, 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. */
/* This list must be kept sorted!!! */
+DEFINE_DATABASE (aliases)
DEFINE_DATABASE (ethers)
DEFINE_DATABASE (group)
DEFINE_DATABASE (hosts)
@@ -27,6 +28,7 @@ DEFINE_DATABASE (netgroup)
DEFINE_DATABASE (networks)
DEFINE_DATABASE (passwd)
DEFINE_DATABASE (protocols)
+DEFINE_DATABASE (publickey)
DEFINE_DATABASE (rpc)
DEFINE_DATABASE (services)
DEFINE_DATABASE (shadow)
diff --git a/nss/getXXbyYY.c b/nss/getXXbyYY.c
index c300117b8c..2a84db974a 100644
--- a/nss/getXXbyYY.c
+++ b/nss/getXXbyYY.c
@@ -1,22 +1,26 @@
/* Copyright (C) 1996 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
+ 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., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, 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 "../nss/nsswitch.h"
+#include <errno.h>
+#include <libc-lock.h>
+#include <stdlib.h>
+
+#include "nsswitch.h"
/*******************************************************************\
|* Here we assume several symbols to be defined: *|
@@ -64,17 +68,47 @@ extern int INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf,
char *buffer, size_t buflen,
LOOKUP_TYPE **result H_ERRNO_PARM);
+/* We need to protect the dynamic buffer handling. */
+__libc_lock_define_initialized (static, lock);
+
+
LOOKUP_TYPE *
FUNCTION_NAME (ADD_PARAMS)
{
- static char buffer[BUFLEN];
+ static char *buffer;
+ static size_t buffer_size;
static LOOKUP_TYPE resbuf;
LOOKUP_TYPE *result;
+ int save;
+
+ /* Get lock. */
+ __libc_lock_lock (lock);
+
+ if (buffer == NULL)
+ {
+ buffer_size = BUFLEN;
+ buffer = malloc (buffer_size);
+ }
+
+ while (buffer != NULL
+ && INTERNAL (REENTRANT_NAME) (ADD_VARIABLES, &resbuf, buffer,
+ buffer_size, &result H_ERRNO_VAR) != 0
+ && errno == ERANGE)
+ {
+ char *new_buf;
+ buffer_size += BUFLEN;
+ 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. */
+ free (buffer);
+ buffer = new_buf;
+ }
- if (INTERNAL (REENTRANT_NAME) (ADD_VARIABLES, &resbuf, buffer,
- BUFLEN, &result H_ERRNO_VAR) != 0)
- /* Error occured. */
- return NULL;
+ /* Release lock. Preserve error value. */
+ save = errno;
+ __libc_lock_unlock (lock);
+ __set_errno (save);
return result;
}
diff --git a/nss/getXXbyYY_r.c b/nss/getXXbyYY_r.c
index 1295772819..f12907c244 100644
--- a/nss/getXXbyYY_r.c
+++ b/nss/getXXbyYY_r.c
@@ -71,7 +71,7 @@
/* Type of the lookup function we need here. */
-typedef int (*lookup_function) (ADD_PARAMS, LOOKUP_TYPE *, char *, int
+typedef int (*lookup_function) (ADD_PARAMS, LOOKUP_TYPE *, char *, size_t
H_ERRNO_PARM);
/* Some usages of this file might use this variable. */
diff --git a/nss/getXXent.c b/nss/getXXent.c
index 7e291e6298..2d6d1c32e6 100644
--- a/nss/getXXent.c
+++ b/nss/getXXent.c
@@ -1,20 +1,24 @@
/* Copyright (C) 1996 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
+ 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., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, 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 <errno.h>
+#include <libc-lock.h>
+#include <stdlib.h>
#include "nsswitch.h"
@@ -55,18 +59,47 @@ extern int INTERNAL (REENTRANT_GETNAME) (LOOKUP_TYPE *resbuf, char *buffer,
size_t buflen, LOOKUP_TYPE **result
H_ERRNO_PARM);
+/* We need to protect the dynamic buffer handling. */
+__libc_lock_define_initialized (static, lock);
+
LOOKUP_TYPE *
GETFUNC_NAME (void)
{
- static char buffer[BUFLEN];
+ static char *buffer;
+ static size_t buffer_size;
static LOOKUP_TYPE resbuf;
- LOOKUP_TYPE *result;
+ LOOKUP_TYPE *result = NULL;
+ int save;
+
+ /* Get lock. */
+ __libc_lock_lock (lock);
+
+ if (buffer == NULL)
+ {
+ buffer_size = BUFLEN;
+ buffer = malloc (buffer_size);
+ }
+
+ while (buffer != NULL
+ && INTERNAL (REENTRANT_GETNAME) (&resbuf, buffer, buffer_size, &result
+ H_ERRNO_VAR) != 0
+ && errno == ERANGE)
+ {
+ char *new_buf;
+ buffer_size += BUFLEN;
+ 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. */
+ free (buffer);
+ buffer = new_buf;
+ }
- if (INTERNAL (REENTRANT_GETNAME) (&resbuf, buffer, BUFLEN, &result
- H_ERRNO_VAR) != 0)
- /* Errors occured. */
- return NULL;
+ /* Release lock. Preserve error value. */
+ save = errno;
+ __libc_lock_unlock (lock);
+ __set_errno (save);
return result;
}
diff --git a/nss/getXXent_r.c b/nss/getXXent_r.c
index 0db0a8bf28..cc47537129 100644
--- a/nss/getXXent_r.c
+++ b/nss/getXXent_r.c
@@ -90,7 +90,7 @@ typedef int (*set_function) (STAYOPEN);
typedef int (*end_function) (void);
/* Prototype for the setXXXent functions we use here. */
-typedef int (*get_function) (LOOKUP_TYPE *, char *, int H_ERRNO_PARM);
+typedef int (*get_function) (LOOKUP_TYPE *, char *, size_t H_ERRNO_PARM);
/* This handle for the NSS data base is shared between all
diff --git a/nss/nss_db/db-XXX.c b/nss/nss_db/db-XXX.c
index 0c41761d67..1596be560a 100644
--- a/nss/nss_db/db-XXX.c
+++ b/nss/nss_db/db-XXX.c
@@ -1,21 +1,21 @@
/* Common code for DB-based databases in nss_db module.
-Copyright (C) 1996 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
+ Copyright (C) 1996 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 <db.h>
#include <fcntl.h>
@@ -168,7 +168,7 @@ lookup (const DBT *key, struct STRUCTURE *result,
enum nss_status \
_nss_db_get##name##_r (proto, \
struct STRUCTURE *result, \
- char *buffer, int buflen H_ERRNO_PROTO) \
+ char *buffer, size_t buflen H_ERRNO_PROTO) \
{ \
DBT key; \
enum nss_status status; \
@@ -189,7 +189,7 @@ _nss_db_get##name##_r (proto, \
/* Return the next entry from the database file, doing locking. */
enum nss_status
CONCAT(_nss_db_get,ENTNAME_r) (struct STRUCTURE *result,
- char *buffer, int buflen H_ERRNO_PROTO)
+ char *buffer, size_t buflen H_ERRNO_PROTO)
{
/* Return next entry in host file. */
enum nss_status status;
diff --git a/nss/nss_db/db-alias.c b/nss/nss_db/db-alias.c
new file mode 100644
index 0000000000..2c44f4df79
--- /dev/null
+++ b/nss/nss_db/db-alias.c
@@ -0,0 +1,235 @@
+/* Mail alias file parser in nss_db module.
+ Copyright (C) 1996 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 Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <aliases.h>
+#include <alloca.h>
+#include <ctype.h>
+#include <db.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <libc-lock.h>
+#include <paths.h>
+#include <string.h>
+
+#include "nsswitch.h"
+
+/* Locks the static variables in this file. */
+__libc_lock_define_initialized (static, lock)
+
+/* Maintenance of the shared handle open on the database. */
+
+static DB *db;
+static int keep_db;
+static unsigned int entidx; /* Index for `getaliasent_r'. */
+
+/* Open database file if not already opened. */
+static enum nss_status
+internal_setent (int stayopen)
+{
+ enum nss_status status = NSS_STATUS_SUCCESS;
+
+ if (db == NULL)
+ {
+ db = dbopen (_PATH_VARDB "aliases.db", O_RDONLY, 0, DB_BTREE, NULL);
+
+ if (db == NULL)
+ status = NSS_STATUS_UNAVAIL;
+ }
+
+ /* Remember STAYOPEN flag. */
+ if (db != NULL)
+ keep_db |= stayopen;
+
+ return status;
+}
+
+
+/* Thread-safe, exported version of that. */
+enum nss_status
+_nss_db_setaliasent (int stayopen)
+{
+ enum nss_status status;
+
+ __libc_lock_lock (lock);
+
+ status = internal_setent (stayopen);
+
+ /* Reset the sequential index. */
+ entidx = 0;
+
+ __libc_lock_unlock (lock);
+
+ return status;
+}
+
+
+/* Close the database file. */
+static void
+internal_endent (void)
+{
+ if (db != NULL)
+ {
+ (*db->close) (db);
+ db = NULL;
+ }
+}
+
+
+/* Thread-safe, exported version of that. */
+enum nss_status
+_nss_db_endaliasent (void)
+{
+ __libc_lock_lock (lock);
+
+ internal_endent ();
+
+ /* Reset STAYOPEN flag. */
+ keep_db = 0;
+
+ __libc_lock_unlock (lock);
+
+ return NSS_STATUS_SUCCESS;
+}
+
+/* We provide the parse function here. The parser in libnss_files
+ cannot be used. The generation of the db file already resolved all
+ :include: statements so we simply have to parse the list and store
+ the result. */
+static enum nss_status
+lookup (const DBT *key, struct aliasent *result, char *buffer,
+ size_t buflen)
+{
+ enum nss_status status;
+ DBT value;
+
+ /* Open the database. */
+ status = internal_setent (keep_db);
+ if (status != NSS_STATUS_SUCCESS)
+ return status;
+
+ if ((*db->get) (db, key, &value, 0) == 0)
+ {
+ const char *src = value.data;
+
+ result->alias_members_len = 0;
+
+ /* We now have to fill the BUFFER with all the information. */
+ if (buflen < key->size + 1)
+ {
+ no_more_room:
+ __set_errno (ERANGE);
+ return NSS_STATUS_TRYAGAIN;
+ }
+
+ if (status == NSS_STATUS_SUCCESS)
+ {
+ char *cp;
+ size_t cnt;
+
+ buffer = stpncpy (buffer, key->data, key->size) + 1;
+ buflen -= key->size + 1;
+
+ while (*src != '\0')
+ {
+ const char *end, *upto;
+ while (isspace (*src))
+ ++src;
+
+ end = strchr (src, ',');
+ if (end == NULL)
+ end = strchr (src, '\0');
+ for (upto = end; upto > src && isspace (upto[-1]); --upto);
+
+ if (upto != src)
+ {
+ if ((upto - src) + __alignof__ (char *) > buflen)
+ goto no_more_room;
+ buffer = stpncpy (buffer, src, upto - src) + 1;
+ buflen -= (upto - src) + __alignof (char *);
+ ++result->alias_members_len;
+ }
+ src = end + (*end != '\0');
+ }
+
+ /* Now prepare the return. Provide string pointers for the
+ currently selected aliases. */
+
+ /* Adjust the pointer so it is aligned for storing pointers. */
+ buffer += __alignof__ (char *) - 1;
+ buffer -= ((buffer - (char *) 0) % __alignof__ (char *));
+ result->alias_members = (char **) buffer;
+
+ /* Compute addresses of alias entry strings. */
+ cp = result->alias_name;
+ for (cnt = 0; cnt < result->alias_members_len; ++cnt)
+ {
+ cp = strchr (cp, '\0') + 1;
+ result->alias_members[cnt] = cp;
+ }
+
+ status = (result->alias_members_len == 0
+ ? NSS_STATUS_RETURN : NSS_STATUS_SUCCESS);
+ }
+ }
+ else
+ status = NSS_STATUS_NOTFOUND;
+
+ if (! keep_db)
+ internal_endent ();
+
+ return status;
+}
+
+enum nss_status
+_nss_db_getaliasent_r (struct aliasent *result, char *buffer, size_t buflen)
+{
+ /* Return next entry in host file. */
+ enum nss_status status;
+ char buf[20];
+ DBT key;
+
+ __libc_lock_lock (lock);
+ key.size = 1 + snprintf (key.data = buf, sizeof buf, "0%u", entidx++);
+ status = lookup (&key, result, buffer, buflen);
+ __libc_lock_unlock (lock);
+
+ return status;
+}
+
+
+enum nss_status
+_nss_db_getaliasbyname_r (const char *name, struct aliasent *result,
+ char *buffer, size_t buflen)
+{
+ DBT key;
+ enum nss_status status;
+
+ key.size = 1 + strlen (name);
+
+ key.data = __alloca (key.size);
+ ((char *) key.data)[0] = '.';
+ memcpy (&((char *) key.data)[1], name, key.size - 1);
+
+ __libc_lock_lock (lock);
+ status = lookup (&key, result, buffer, buflen);
+ __libc_lock_unlock (lock);
+
+ return status;
+}
diff --git a/nss/nss_files/files-XXX.c b/nss/nss_files/files-XXX.c
index b6702b0366..c741ab6f48 100644
--- a/nss/nss_files/files-XXX.c
+++ b/nss/nss_files/files-XXX.c
@@ -20,6 +20,7 @@
#include <stdio.h>
#include <ctype.h>
#include <assert.h>
+#include <errno.h>
#include <libc-lock.h>
#include "nsswitch.h"
@@ -39,13 +40,13 @@
#define DATAFILE "/etc/" DATABASE
#ifdef NEED_H_ERRNO
-#define H_ERRNO_PROTO , int *herrnop
-#define H_ERRNO_ARG , herrnop
-#define H_ERRNO_SET(val) (*herrnop = (val))
+# define H_ERRNO_PROTO , int *herrnop
+# define H_ERRNO_ARG , herrnop
+# define H_ERRNO_SET(val) (*herrnop = (val))
#else
-#define H_ERRNO_PROTO
-#define H_ERRNO_ARG
-#define H_ERRNO_SET(val) ((void) 0)
+# define H_ERRNO_PROTO
+# define H_ERRNO_ARG
+# define H_ERRNO_SET(val) ((void) 0)
#endif
/* Locks the static variables in this file. */
@@ -59,10 +60,10 @@ static enum { none, getent, getby } last_use;
static int keep_stream;
/* Open database file if not already opened. */
-static int
+static enum nss_status
internal_setent (int stayopen)
{
- int status = NSS_STATUS_SUCCESS;
+ enum nss_status status = NSS_STATUS_SUCCESS;
if (stream == NULL)
{
@@ -83,10 +84,10 @@ internal_setent (int stayopen)
/* Thread-safe, exported version of that. */
-int
+enum nss_status
CONCAT(_nss_files_set,ENTNAME) (int stayopen)
{
- int status;
+ enum nss_status status;
__libc_lock_lock (lock);
@@ -120,7 +121,7 @@ internal_endent (void)
/* Thread-safe, exported version of that. */
-int
+enum nss_status
CONCAT(_nss_files_end,ENTNAME) (void)
{
__libc_lock_lock (lock);
@@ -145,16 +146,6 @@ internal_getent (struct STRUCTURE *result,
struct parser_data *data = (void *) buffer;
int linebuflen = buffer + buflen - data->linebuffer;
- /* Be prepared that the set*ent function was not called before. */
- if (stream == NULL)
- {
- enum nss_status status;
-
- status = internal_setent (0);
- if (status != NSS_STATUS_SUCCESS)
- return status;
- }
-
if (buflen < (int) sizeof *data + 1)
{
__set_errno (ERANGE);
@@ -163,6 +154,9 @@ internal_getent (struct STRUCTURE *result,
do
{
+ /* Terminate the line so that we can test for overflow. */
+ data->linebuffer[linebuflen - 1] = '\0';
+
p = fgets (data->linebuffer, linebuflen, stream);
if (p == NULL)
{
@@ -170,17 +164,23 @@ internal_getent (struct STRUCTURE *result,
H_ERRNO_SET (HOST_NOT_FOUND);
return NSS_STATUS_NOTFOUND;
}
-
- /* Terminate the line for any case. */
- data->linebuffer[linebuflen - 1] = '\0';
+ else if (data->linebuffer[linebuflen - 1] != '\0')
+ {
+ /* The line is too long. Give the user the opportunity to
+ enlarge the buffer. */
+ __set_errno (ERANGE);
+ H_ERRNO_SET (NETDB_INTERNAL);
+ return NSS_STATUS_TRYAGAIN;
+ }
/* 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, result, data, buflen));
+ }
+ 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, result, data, buflen));
/* Filled in RESULT with the next entry from the database file. */
return NSS_STATUS_SUCCESS;
@@ -188,29 +188,42 @@ internal_getent (struct STRUCTURE *result,
/* Return the next entry from the database file, doing locking. */
-int
+enum nss_status
CONCAT(_nss_files_get,ENTNAME_r) (struct STRUCTURE *result,
- char *buffer, int buflen H_ERRNO_PROTO)
+ char *buffer, size_t buflen H_ERRNO_PROTO)
{
/* Return next entry in host file. */
- int status = NSS_STATUS_SUCCESS;
+ enum nss_status status = NSS_STATUS_SUCCESS;
__libc_lock_lock (lock);
- /* If the last use was not by the getent function we need the
- position the stream. */
- if (last_use != getent)
- if (fsetpos (stream, &position) < 0)
- status = NSS_STATUS_UNAVAIL;
- else
- last_use = getent;
+ /* Be prepared that the set*ent function was not called before. */
+ if (stream == NULL)
+ status = internal_setent (0);
- if (status == NSS_STATUS_SUCCESS)
+ if (status != NSS_STATUS_SUCCESS)
{
- status = internal_getent (result, buffer, buflen H_ERRNO_ARG);
-
- /* Remember this position. */
- fgetpos (stream, &position);
+ /* If the last use was not by the getent function we need the
+ position the stream. */
+ if (last_use != getent)
+ if (fsetpos (stream, &position) < 0)
+ status = NSS_STATUS_UNAVAIL;
+ else
+ last_use = getent;
+
+ if (status == NSS_STATUS_SUCCESS)
+ {
+ status = internal_getent (result, buffer, buflen H_ERRNO_ARG);
+
+ /* Remember this position if we were successful. If the
+ operation failed we give the user a chance to repeat the
+ operation (perhaps the buffer was too small). */
+ if (status == NSS_STATUS_SUCCESS)
+ fgetpos (stream, &position);
+ else
+ /* We must make sure we reposition the stream the next call. */
+ last_use = none;
+ }
}
__libc_lock_unlock (lock);
@@ -234,24 +247,27 @@ CONCAT(_nss_files_get,ENTNAME_r) (struct STRUCTURE *result,
enum nss_status \
_nss_files_get##name##_r (proto, \
struct STRUCTURE *result, \
- char *buffer, int buflen H_ERRNO_PROTO) \
+ char *buffer, size_t buflen H_ERRNO_PROTO) \
{ \
enum nss_status status; \
\
__libc_lock_lock (lock); \
\
/* Reset file pointer to beginning or open file. */ \
- internal_setent (keep_stream); \
+ status = internal_setent (keep_stream); \
\
- /* Tell getent function that we have repositioned the file pointer. */ \
- last_use = getby; \
+ if (status == NSS_STATUS_SUCCESS) \
+ { \
+ /* Tell getent function that we have repositioned the file pointer. */ \
+ last_use = getby; \
\
- while ((status = internal_getent (result, buffer, buflen H_ERRNO_ARG)) \
- == NSS_STATUS_SUCCESS) \
- { break_if_match } \
+ while ((status = internal_getent (result, buffer, buflen H_ERRNO_ARG)) \
+ == NSS_STATUS_SUCCESS) \
+ { break_if_match } \
\
- if (! keep_stream) \
- internal_endent (); \
+ if (! keep_stream) \
+ internal_endent (); \
+ } \
\
__libc_lock_unlock (lock); \
\
diff --git a/nss/nss_files/files-alias.c b/nss/nss_files/files-alias.c
new file mode 100644
index 0000000000..c6ef49c621
--- /dev/null
+++ b/nss/nss_files/files-alias.c
@@ -0,0 +1,424 @@
+/* Mail alias file parser in nss_files module.
+ Copyright (C) 1996 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 Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <aliases.h>
+#include <ctype.h>
+#include <libc-lock.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "nsswitch.h"
+
+/* Locks the static variables in this file. */
+__libc_lock_define_initialized (static, lock)
+
+/* Maintenance of the shared stream open on the database file. */
+
+static FILE *stream;
+static fpos_t position;
+static enum { none, getent, getby } last_use;
+
+
+static enum nss_status
+internal_setent (void)
+{
+ enum nss_status status = NSS_STATUS_SUCCESS;
+
+ if (stream == NULL)
+ {
+ stream = fopen ("/etc/aliases", "r");
+
+ if (stream == NULL)
+ status = NSS_STATUS_UNAVAIL;
+ }
+ else
+ rewind (stream);
+
+ return status;
+}
+
+
+/* Thread-safe, exported version of that. */
+enum nss_status
+_nss_files_setaliasent (void)
+{
+ enum nss_status status;
+
+ __libc_lock_lock (lock);
+
+ status = internal_setent ();
+
+ if (status == NSS_STATUS_SUCCESS && fgetpos (stream, &position) < 0)
+ {
+ fclose (stream);
+ stream = NULL;
+ status = NSS_STATUS_UNAVAIL;
+ }
+
+ last_use = getent;
+
+ __libc_lock_unlock (lock);
+
+ return status;
+}
+
+
+/* Close the database file. */
+static void
+internal_endent (void)
+{
+ if (stream != NULL)
+ {
+ fclose (stream);
+ stream = NULL;
+ }
+}
+
+
+/* Thread-safe, exported version of that. */
+enum nss_status
+_nss_files_endaliasent (void)
+{
+ __libc_lock_lock (lock);
+
+ internal_endent ();
+
+ __libc_lock_unlock (lock);
+
+ return NSS_STATUS_SUCCESS;
+}
+
+/* Parsing the database file into `struct aliasent' data structures. */
+static enum nss_status
+get_next_alias (const char *match, struct aliasent *result,
+ char *buffer, size_t buflen)
+{
+ enum nss_status status = NSS_STATUS_NOTFOUND;
+ int ignore = 0;
+
+ result->alias_members_len = 0;
+
+ while (1)
+ {
+ /* Now we are ready to process the input. We have to read a
+ line and all its continuations and construct the array of
+ string pointers. This pointers and the names itself have to
+ be placed in BUFFER. */
+ char *first_unused = buffer;
+ size_t room_left = buflen - (buflen % __alignof__ (char *));
+ char *line;
+
+ /* Read the first line. It must contain the alias name and
+ possibly some alias names. */
+ first_unused[room_left - 1] = '\0';
+ line = fgets (first_unused, room_left, stream);
+ if (line == NULL)
+ /* Nothing to read. */
+ break;
+ else if (first_unused[room_left - 1] != '\0')
+ {
+ /* The line is too long for our buffer. */
+ no_more_room:
+ __set_errno (ERANGE);
+ status = NSS_STATUS_TRYAGAIN;
+ break;
+ }
+ else
+ {
+ char *cp;
+
+ /* If we are in IGNORE mode and the first character in the
+ line is a white space we ignore the line and start
+ reading the next. */
+ if (ignore && isspace (first_unused))
+ continue;
+
+ /* Terminate the line for any case. */
+ cp = strpbrk (first_unused, "#\n");
+ if (cp != NULL)
+ *cp = '\0';
+
+ /* Skip leading blanks. */
+ while (isspace (*line))
+ ++line;
+
+ result->alias_name = first_unused;
+ while (*line != '\0' && *line != ':')
+ *first_unused++ = *line++;
+ if (*line == '\0' || result->alias_name == first_unused)
+ /* No valid name. Ignore the line. */
+ continue;
+
+ *first_unused++ = '\0';
+ if (room_left < (size_t) (first_unused - result->alias_name))
+ goto no_more_room;
+ room_left -= first_unused - result->alias_name;
+ ++line;
+
+ /* When we search for a specific alias we can avoid all the
+ difficult parts and compare now with the name we are
+ looking for. If it does not match we simply ignore all
+ lines until the next line containing the start of a new
+ alias is found. */
+ ignore = match != NULL && strcmp (result->alias_name, match) == 0;
+
+ while (! ignore)
+ {
+ while (isspace (*line))
+ ++line;
+
+ cp = first_unused;
+ while (*line != '\0' && *line != ',')
+ *first_unused++ = *line++;
+
+ if (first_unused != cp)
+ {
+ if (*line != '\0')
+ {
+ /* OK, we can have a regular entry or an include
+ request. */
+ *first_unused++ = '\0';
+ ++line;
+ }
+ else
+ ++first_unused;
+
+
+ if (strncmp (cp, ":include:", 9) != 0)
+ {
+ if (room_left < (first_unused - cp) + sizeof (char *))
+ goto no_more_room;
+ room_left -= (first_unused - cp) + sizeof (char *);
+
+ ++result->alias_members_len;
+ }
+ else
+ {
+ /* Oh well, we have to read the addressed file. */
+ FILE *listfile;
+ char *old_line = NULL;
+
+ first_unused = cp;
+
+ listfile = fopen (&cp[9], "r");
+ /* If the file does not exist we simply ignore
+ the statement. */
+ if (listfile != NULL
+ && (old_line = strdup (line)) != NULL)
+ {
+ while (! feof (listfile))
+ {
+ first_unused[room_left - 1] = '\0';
+ line = fgets (first_unused, room_left, listfile);
+ if (line == NULL)
+ break;
+ if (first_unused[room_left - 1] != '\0')
+ {
+ free (old_line);
+ goto no_more_room;
+ }
+
+ /* Parse the line. */
+ cp = strpbrk (line, "#\n");
+ if (cp != NULL)
+ *cp = '\0';
+
+ do
+ {
+ while (isspace (*line))
+ ++line;
+
+ cp = first_unused;
+ while (*line != '\0' && *line != ',')
+ *first_unused++ = *line++;
+
+ if (*line != '\0')
+ ++line;
+
+ if (first_unused != cp)
+ {
+ *first_unused++ = '\0';
+ if (room_left < ((first_unused - cp)
+ + __alignof__ (char *)))
+ {
+ free (old_line);
+ goto no_more_room;
+ }
+ room_left -= ((first_unused - cp)
+ + __alignof__ (char *));
+ ++result->alias_members_len;
+ }
+ }
+ while (*line != '\0');
+ }
+ fclose (listfile);
+
+ first_unused[room_left - 1] = '\0';
+ strncpy (first_unused, old_line, room_left);
+
+ if (old_line != NULL)
+ free (old_line);
+
+ if (first_unused[room_left - 1] != '\0')
+ goto no_more_room;
+ }
+ }
+ }
+
+ if (*line == '\0')
+ {
+ /* Get the next line. But we must be careful. We
+ must not read the whole line at once since it
+ might belong to the current alias. Simply read
+ the first character. If it is a white space we
+ have a continuation line. Otherwise it is the
+ beginning of a new alias and we can push back the
+ just read character. */
+ int ch;
+
+ first_unused[room_left - 1] = '\0';
+ line = first_unused;
+ ch = fgetc (stream);
+ if (ch == EOF || !isspace (ch))
+ {
+ size_t cnt;
+
+ /* Now prepare the return. Provide string
+ pointers for the currently selected aliases. */
+ if (ch != EOF)
+ ungetc (ch, stream);
+
+ /* 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;
+
+ /* Compute addresses of alias entry strings. */
+ cp = result->alias_name;
+ for (cnt = 0; cnt < result->alias_members_len; ++cnt)
+ {
+ cp = strchr (cp, '\0') + 1;
+ result->alias_members[cnt] = cp;
+ }
+
+ status = (result->alias_members_len == 0
+ ? NSS_STATUS_RETURN : NSS_STATUS_SUCCESS);
+ break;
+ }
+
+ /* The just read character is a white space and so
+ can be ignored. */
+ cp = strpbrk (line, "#\n");
+ if (cp != NULL)
+ *cp = '\0';
+ }
+ }
+ }
+
+ if (status != NSS_STATUS_NOTFOUND)
+ /* We read something. In any case break here. */
+ break;
+ }
+
+ return status;
+}
+
+
+enum nss_status
+_nss_files_getaliasent_r (struct aliasent *result, char *buffer, size_t buflen)
+{
+ /* Return next entry in host file. */
+ enum nss_status status = NSS_STATUS_SUCCESS;
+
+ __libc_lock_lock (lock);
+
+ /* Be prepared that the set*ent function was not called before. */
+ if (stream == NULL)
+ status = internal_setent ();
+
+ if (status == NSS_STATUS_SUCCESS)
+ {
+ /* If the last use was not by the getent function we need the
+ position the stream. */
+ if (last_use != getent)
+ if (fsetpos (stream, &position) < 0)
+ status = NSS_STATUS_UNAVAIL;
+ else
+ last_use = getent;
+
+ if (status == NSS_STATUS_SUCCESS)
+ {
+ result->alias_local = 1;
+
+ /* Read lines until we get a definite result. */
+ do
+ status = get_next_alias (NULL, result, buffer, buflen);
+ while (status == NSS_STATUS_RETURN);
+
+ /* If we successfully read an entry remember this position. */
+ if (status == NSS_STATUS_SUCCESS)
+ fgetpos (stream, &position);
+ else
+ last_use = none;
+ }
+ }
+
+ __libc_lock_unlock (lock);
+
+ return status;
+}
+
+
+enum nss_status
+_nss_files_getaliasbyname_r (const char *name, struct aliasent *result,
+ char *buffer, size_t buflen)
+{
+ /* Return next entry in host file. */
+ enum nss_status status = NSS_STATUS_SUCCESS;
+
+ if (name == NULL)
+ {
+ __set_errno (EINVAL);
+ return NSS_STATUS_UNAVAIL;
+ }
+
+ __libc_lock_lock (lock);
+
+ /* Open the stream or rest it. */
+ status = internal_setent ();
+ last_use = getby;
+
+ if (status == NSS_STATUS_SUCCESS)
+ {
+ result->alias_local = 1;
+
+ /* Read lines until we get a definite result. */
+ do
+ status = get_next_alias (name, result, buffer, buflen);
+ while (status == NSS_STATUS_RETURN);
+ }
+
+ __libc_lock_unlock (lock);
+
+ return status;
+}
diff --git a/nss/nss_files/files-parse.c b/nss/nss_files/files-parse.c
index 1250bb9572..83a80f35c0 100644
--- a/nss/nss_files/files-parse.c
+++ b/nss/nss_files/files-parse.c
@@ -39,7 +39,7 @@
#define CONCAT1(a,b) a##b
#ifndef STRUCTURE
-#define STRUCTURE ENTNAME
+# define STRUCTURE ENTNAME
#endif
@@ -47,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];
};
@@ -57,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
@@ -71,20 +71,20 @@ struct parser_data
extern int parse_line (char *line, struct STRUCTURE *result,
struct parser_data *data, int datalen);
-#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) \
{ \
ENTDATA_DECL (data) \
char *p = strpbrk (line, EOLSET "\n"); \
- if (p) \
+ if (p != NULL) \
*p = '\0'; \
BODY; \
TRAILING_LIST_PARSER; \
@@ -92,7 +92,7 @@ parse_line (char *line, struct STRUCTURE *result, \
}
-#define STRING_FIELD(variable, terminator_p, swallow) \
+# define STRING_FIELD(variable, terminator_p, swallow) \
{ \
variable = line; \
while (*line != '\0' && !terminator_p (*line)) \
@@ -106,7 +106,7 @@ parse_line (char *line, struct STRUCTURE *result, \
} \
}
-#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)); \
@@ -121,7 +121,7 @@ parse_line (char *line, struct STRUCTURE *result, \
line = endp; \
}
-#define INT_FIELD_MAYBE_NULL(variable, terminator_p, swallow, base, convert, default) \
+# define INT_FIELD_MAYBE_NULL(variable, terminator_p, swallow, base, convert, default) \
{ \
char *endp; \
if (*line == '\0') \
@@ -139,14 +139,14 @@ parse_line (char *line, struct STRUCTURE *result, \
line = endp; \
}
-#define ISCOLON(c) ((c) == ':')
+# 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); \
if (list) \
@@ -198,10 +198,10 @@ parse_list (char *line, struct parser_data *data, int datalen)
*line = '\0';
do
++line;
- while (TRAILING_LIST_SEPARATOR_P (*line));
+ while (isspace (*line));
elt = line;
}
- else if (*line == '\0' || *line == '\n')
+ else if (*line == '\0')
{
/* End of the line. */
if (line > elt)
@@ -219,7 +219,7 @@ parse_list (char *line, struct parser_data *data, int datalen)
return list;
}
-#endif /* TRAILING_LIST_MEMBER */
+# endif /* TRAILING_LIST_MEMBER */
#endif /* EXTERN_PARSER */
@@ -238,5 +238,5 @@ parse_list (char *line, struct parser_data *data, int datalen)
/* 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