bin/165710: RPC: getnetconfig() and other netconfig's functions
correct implementation.
Andrey Simonenko
simon at comsys.ntu-kpi.kiev.ua
Mon Oct 1 10:00:17 UTC 2012
The following reply was made to PR kern/165710; it has been noted by GNATS.
From: Andrey Simonenko <simon at comsys.ntu-kpi.kiev.ua>
To: bug-followup at FreeBSD.org
Cc:
Subject: bin/165710: RPC: getnetconfig() and other netconfig's functions
correct implementation.
Date: Mon, 1 Oct 2012 12:50:43 +0300
Slightly optimized netconfig.c:nc_parse().
diff -ruNp libc.orig/include/reentrant.h libc/include/reentrant.h
--- libc.orig/include/reentrant.h 2010-03-12 14:56:49.000000000 +0200
+++ libc/include/reentrant.h 2012-09-27 13:39:20.000000000 +0300
@@ -95,27 +95,19 @@
#define ONCE_INITIALIZER PTHREAD_ONCE_INIT
#define mutex_init(m, a) _pthread_mutex_init(m, a)
-#define mutex_lock(m) if (__isthreaded) \
- _pthread_mutex_lock(m)
-#define mutex_unlock(m) if (__isthreaded) \
- _pthread_mutex_unlock(m)
-#define mutex_trylock(m) (__isthreaded ? 0 : _pthread_mutex_trylock(m))
+#define mutex_lock(m) (__isthreaded ? _pthread_mutex_lock(m) : 0)
+#define mutex_unlock(m) (__isthreaded ? _pthread_mutex_unlock(m) : 0)
+#define mutex_trylock(m) (__isthreaded ? _pthread_mutex_trylock(m) : 0)
#define cond_init(c, a, p) _pthread_cond_init(c, a)
-#define cond_signal(m) if (__isthreaded) \
- _pthread_cond_signal(m)
-#define cond_broadcast(m) if (__isthreaded) \
- _pthread_cond_broadcast(m)
-#define cond_wait(c, m) if (__isthreaded) \
- _pthread_cond_wait(c, m)
+#define cond_signal(m) (__isthreaded ? _pthread_cond_signal(m) : 0)
+#define cond_broadcast(m) (__isthreaded ? _pthread_cond_broadcast(m) : 0)
+#define cond_wait(c, m) (__isthreaded ? _pthread_cond_wait(c, m) : 0)
#define rwlock_init(l, a) _pthread_rwlock_init(l, a)
-#define rwlock_rdlock(l) if (__isthreaded) \
- _pthread_rwlock_rdlock(l)
-#define rwlock_wrlock(l) if (__isthreaded) \
- _pthread_rwlock_wrlock(l)
-#define rwlock_unlock(l) if (__isthreaded) \
- _pthread_rwlock_unlock(l)
+#define rwlock_rdlock(l) (__isthreaded ? _pthread_rwlock_rdlock(l) : 0)
+#define rwlock_wrlock(l) (__isthreaded ? _pthread_rwlock_wrlock(l) : 0)
+#define rwlock_unlock(l) (__isthreaded ? _pthread_rwlock_unlock(l) : 0)
#define thr_keycreate(k, d) _pthread_key_create(k, d)
#define thr_setspecific(k, p) _pthread_setspecific(k, p)
diff -ruNp libc.orig/rpc/Makefile.inc libc/rpc/Makefile.inc
--- libc.orig/rpc/Makefile.inc 2012-02-08 11:58:52.000000000 +0200
+++ libc/rpc/Makefile.inc 2012-09-27 13:39:20.000000000 +0300
@@ -4,7 +4,7 @@
.PATH: ${.CURDIR}/rpc ${.CURDIR}/.
SRCS+= auth_none.c auth_unix.c authunix_prot.c bindresvport.c clnt_bcast.c \
clnt_dg.c clnt_generic.c clnt_perror.c clnt_raw.c clnt_simple.c \
- clnt_vc.c rpc_dtablesize.c getnetconfig.c getnetpath.c getrpcent.c \
+ clnt_vc.c rpc_dtablesize.c netconfig.c getrpcent.c \
getrpcport.c mt_misc.c pmap_clnt.c pmap_getmaps.c pmap_getport.c \
pmap_prot.c pmap_prot2.c pmap_rmt.c rpc_prot.c rpc_commondata.c \
rpc_callmsg.c rpc_generic.c rpc_soc.c rpcb_clnt.c rpcb_prot.c \
diff -ruNp libc.orig/rpc/getnetconfig.3 libc/rpc/getnetconfig.3
--- libc.orig/rpc/getnetconfig.3 2002-12-19 11:40:23.000000000 +0200
+++ libc/rpc/getnetconfig.3 2012-09-27 13:39:20.000000000 +0300
@@ -169,12 +169,7 @@ returns a unique handle to be used by
In the case of an error,
.Fn setnetconfig
returns
-.Dv NULL
-and
-.Fn nc_perror
-or
-.Fn nc_sperror
-can be used to print the reason for failure.
+.Dv NULL .
.Pp
The
.Fn getnetconfig
diff -ruNp libc.orig/rpc/getnetpath.3 libc/rpc/getnetpath.3
--- libc.orig/rpc/getnetpath.3 2002-12-18 14:45:10.000000000 +0200
+++ libc/rpc/getnetpath.3 2012-09-27 13:39:20.000000000 +0300
@@ -40,7 +40,10 @@ for other routines that also access the
network configuration database directly.
The
.Ev NETPATH
-variable is a list of colon-separated network identifiers.
+variable is a list of colon-separated network identifiers,
+any character in a network identifier can be escaped by the
+.Ql \e
+character.
.Pp
The
.Fn getnetpath
@@ -103,14 +106,12 @@ variable is unset,
.Fn getnetpath
behaves as if
.Ev NETPATH
-were set to the sequence of
+was set to the sequence of
.Dq default
or
.Dq visible
networks in the netconfig database, in the
order in which they are listed.
-.\"This proviso holds also for this
-.\"whole manpage.
.Pp
The
.Fn endnetpath
@@ -143,14 +144,6 @@ returns 0 on success and \-1 on failure
(for example, if
.Fn setnetpath
was not called previously).
-The
-.Fn nc_perror
-or
-.Fn nc_sperror
-function
-can be used to print out the reason for failure.
-See
-.Xr getnetconfig 3 .
.Pp
When first called,
.Fn getnetpath
@@ -164,6 +157,14 @@ has been exhausted,
.Fn getnetpath
returns
.Dv NULL .
+.Pp
+If any of these functions failed, then the
+.Fn nc_perror
+and
+.Fn nc_sperror
+functions can be used to print out the reason for failure.
+See
+.Xr getnetconfig 3 .
.Sh SEE ALSO
.Xr getnetconfig 3 ,
.Xr netconfig 5 ,
diff -ruNp libc.orig/rpc/netconfig.c libc/rpc/netconfig.c
--- libc.orig/rpc/netconfig.c 1970-01-01 03:00:00.000000000 +0300
+++ libc/rpc/netconfig.c 2012-09-30 21:53:42.000000000 +0300
@@ -0,0 +1,723 @@
+/*-
+ * Copyright (c) 2012 Andrey Simonenko
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/queue.h>
+#include <sys/types.h>
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <netconfig.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "un-namespace.h"
+
+/*
+ * Table of semantics.
+ */
+static const struct {
+ const char *name;
+ u_long code;
+} nc_semantics_tbl[] = {
+ { .name = "tpi_cots_ord", .code = NC_TPI_COTS_ORD },
+ { .name = "tpi_clts", .code = NC_TPI_CLTS },
+ { .name = "tpi_raw", .code = NC_TPI_RAW },
+ { .name = "tpi_cots", .code = NC_TPI_COTS }
+};
+
+#define NC_SEMANTICS_TBL_SIZE \
+ (sizeof(nc_semantics_tbl) / sizeof(nc_semantics_tbl[0]))
+
+/*
+ * Errors codes.
+ */
+#define NC_NOERROR 0
+#define NC_EFILE 1
+#define NC_ENOMEM 2
+#define NC_EINIT 3
+#define NC_EFORMAT 4
+#define NC_ELBIG 5
+#define NC_ENOENT 6
+#define NC_EEOF 7
+#define NC_EIO 8
+
+static const char *const nc_errlist[] = {
+ [NC_NOERROR] = "No error",
+ [NC_EFILE] = "Netconfig database cannot be opened",
+ [NC_ENOMEM] = "Not enough memory",
+ [NC_EINIT] = "Netconfig database was not initialized",
+ [NC_EFORMAT] = "Netconfig database has wrong format",
+ [NC_ELBIG] = "Line in netconfig database is too large",
+ [NC_ENOENT] = "Netid not found in netconfig database",
+ [NC_EEOF] = "Reached end of netconfig database",
+ [NC_EIO] = "Netconfig database input/output error"
+};
+
+/*
+ * One entry from the NETCONFIG database.
+ */
+struct nc_entry {
+ STAILQ_ENTRY(nc_entry) link; /* For list building. */
+ struct netconfig nc; /* One entry data. */
+};
+
+/*
+ * Handle for the getnetconfig() and endnetconfig() functions.
+ */
+struct nc_handle {
+ u_int error; /* Current state of session. */
+ struct nc_entry *nc_entry; /* Current entry in session. */
+};
+
+/*
+ * Handle for the getnetpath() and endnetpath() functions.
+ */
+struct np_handle {
+ void *nc_handle; /* Open nc_handle. */
+ char *np_cur; /* Current list in np_env. */
+ char *np_env; /* Copy of NETPATH variable. */
+};
+
+/*
+ * This mutex synchronizes access to all np_handles that were created
+ * when the NETPATH environment variable was defined.
+ */
+static mutex_t np_handle_lock = MUTEX_INITIALIZER;
+
+/*
+ * The NETCONFIG database file.
+ */
+static FILE *nc_file;
+
+/*
+ * Cache of already read entries from the NETCONFIG database.
+ */
+static struct {
+ STAILQ_HEAD(, nc_entry) list; /* List of cached entries. */
+ u_int error; /* Current state of cache data. */
+ u_int ref; /* Number of references. */
+} nc_cache = {
+ .list = STAILQ_HEAD_INITIALIZER(nc_cache.list),
+ .error = NC_EINIT,
+ .ref = 0
+};
+
+/*
+ * This mutex synchronizes access to nc_cache, nc_file and all nc_handles.
+ */
+static mutex_t nc_cache_lock = MUTEX_INITIALIZER;
+
+static thread_key_t nc_key;
+static once_t nc_once = ONCE_INITIALIZER;
+static int nc_key_error;
+
+/*
+ * Maximum allowed line length in the NETCONFIG database.
+ */
+#define NC_LINE_MAX 1024
+
+/*
+ * Rules of memory allocation for (char *) fields in struct netconfig{}:
+ * - memory for all strings is allocated in one block;
+ * - address of allocated block is saved in the nc_netid field;
+ * - other (char *) fields point to appropriate positions in this block;
+ * - end of each string (data) is NUL terminated.
+ */
+
+static void
+nc_key_init(void)
+{
+ nc_key_error = thr_keycreate(&nc_key, free);
+}
+
+static u_int *
+__nc_error(void)
+{
+ static u_int nc_error = NC_NOERROR;
+
+ u_int *value;
+
+ if (thr_main())
+ goto one_value;
+ if (thr_once(&nc_once, nc_key_init) != 0 || nc_key_error != 0)
+ goto one_value;
+ value = thr_getspecific(nc_key);
+ if (value == NULL) {
+ value = malloc(sizeof(*value));
+ if (value == NULL)
+ goto one_value;
+ if (thr_setspecific(nc_key, value) != 0) {
+ free(value);
+ goto one_value;
+ }
+ *value = NC_NOERROR;
+ }
+ return (value);
+
+one_value:
+ return (&nc_error);
+}
+
+#define nc_error (*__nc_error())
+
+/*
+ * Rewind NETCONFIG database session.
+ */
+static __inline void
+nc_session_rewind(struct nc_handle *nc_handle)
+{
+ nc_handle->error = NC_NOERROR;
+ nc_handle->nc_entry = NULL;
+}
+
+/*
+ * Return address of the first non white space character in the given string.
+ */
+static char *
+nc_skip_spaces(char *str)
+{
+ for (;; ++str)
+ if (*str != ' ' && *str != '\t')
+ break;
+ return (str);
+}
+
+/*
+ * Select next field from the line. On enter *begp is a start for search.
+ * On exit *begp is the next after the next character after a new field
+ * if EOL is not reached, else *begp will point to the NUL character right
+ * after selected field. The address of successfully selected field (which
+ * is finished by a NUL character) is saved in *fieldp.
+ */
+static int
+nc_select_field(char **begp, char **fieldp)
+{
+ char *beg, *ptr;
+
+ beg = nc_skip_spaces(*begp);
+ for (ptr = beg;; ++ptr) {
+ if (*ptr == ' ' || *ptr == '\t') {
+ *ptr = '\0';
+ if (*(ptr + 1) != '\0')
+ ++ptr;
+ break;
+ }
+ if (*ptr == '\0')
+ break;
+ }
+ if (ptr == beg)
+ return (-1);
+ *begp = ptr;
+ *fieldp = beg;
+ return (0);
+}
+
+/*
+ * This function NUL terminates the first token from the given string,
+ * the end of the token is marked by the given delimiter. Return value
+ * is the address of the rest of the string or NULL if there is no more
+ * tokens. Any character can be represented by \-sequence. On return
+ * str will point to just selected token. Selected token can be empty
+ * string, so this case must be checked in the calling function.
+ */
+static char *
+nc_next_token(char *str, char delim)
+{
+ char *p, *q;
+ bool esc;
+
+ for (p = q = str, esc = false;; ++p) {
+ if (esc)
+ esc = false;
+ else if (*p == '\\') {
+ esc = true;
+ continue;
+ } else if (*p == delim) {
+ *p++ = *q = '\0';
+ break;
+ }
+ *q = *p;
+ if (*p == '\0')
+ break;
+ ++q;
+ }
+ return (*p != '\0' ? p : NULL);
+}
+
+/*
+ * Parse the given line with the given length according to the netconfig(5)
+ * format. The given line is started with some non-space data, does not have
+ * new-line character at the end.
+ */
+static int
+nc_parse(char *line, size_t len, struct netconfig *nc)
+{
+ char **nc_lookups;
+ char *s, *buf, *str, *token;
+ u_int i;
+
+ buf = str = malloc(len + 1);
+ if (buf == NULL) {
+ nc_error = NC_ENOMEM;
+ return (-1);
+ }
+ memcpy(buf, line, len + 1);
+
+ if (nc_select_field(&str, &nc->nc_netid) < 0)
+ goto failed_format;
+
+ if (nc_select_field(&str, &token) < 0)
+ goto failed_format;
+ for (i = 0;;) {
+ if (strcmp(token, nc_semantics_tbl[i].name) == 0) {
+ nc->nc_semantics = nc_semantics_tbl[i].code;
+ break;
+ }
+ if (++i == NC_SEMANTICS_TBL_SIZE)
+ goto failed_format;
+ }
+
+ if (nc_select_field(&str, &token) < 0)
+ goto failed_format;
+ nc->nc_flag = NC_NOFLAG;
+ if (token[0] == '-') {
+ if (token[1] != '\0')
+ goto failed_format;
+ } else {
+ do {
+ switch (*token) {
+ case 'v':
+ nc->nc_flag |= NC_VISIBLE;
+ break;
+ case 'b':
+ nc->nc_flag |= NC_BROADCAST;
+ break;
+ default:
+ goto failed_format;
+ }
+ } while (*++token != '\0');
+ }
+
+ if (nc_select_field(&str, &nc->nc_protofmly) < 0)
+ goto failed_format;
+
+ if (nc_select_field(&str, &nc->nc_proto) < 0)
+ goto failed_format;
+
+ if (nc_select_field(&str, &nc->nc_device) < 0)
+ goto failed_format;
+
+ if (nc_select_field(&str, &token) < 0)
+ goto failed_format;
+ nc->nc_nlookups = 0;
+ nc->nc_lookups = NULL;
+ if (token[0] == '-') {
+ if (token[1] != '\0')
+ goto failed_format;
+ } else {
+ while ((s = token) != NULL) {
+ token = nc_next_token(s, ',');
+ if (*s != '\0') {
+ nc->nc_nlookups++;
+ nc_lookups = realloc(nc->nc_lookups,
+ nc->nc_nlookups * sizeof(*nc->nc_lookups));
+ if (nc_lookups == NULL) {
+ free(nc->nc_lookups);
+ nc_error = NC_ENOMEM;
+ goto failed;
+ }
+ nc->nc_lookups = nc_lookups;
+ nc->nc_lookups[nc->nc_nlookups - 1] = s;
+ }
+ }
+ }
+
+ if (*str != '\0') {
+ free(nc->nc_lookups);
+ goto failed_format;
+ }
+ return (0);
+
+failed_format:
+ nc_error = NC_EFORMAT;
+failed:
+ free(buf);
+ return (-1);
+}
+
+/*
+ * Duplicate the given netconfig structure.
+ */
+static struct netconfig *
+nc_dup(const struct netconfig *nc_src)
+{
+ struct netconfig *nc_dst;
+ size_t line_size;
+ u_long i;
+
+ nc_dst = malloc(sizeof(*nc_dst));
+ if (nc_dst == NULL)
+ goto failed;
+ if (nc_src->nc_nlookups != 0) {
+ i = nc_src->nc_nlookups - 1;
+ line_size = nc_src->nc_lookups[i] +
+ strlen(nc_src->nc_lookups[i]) - nc_src->nc_netid;
+ } else
+ line_size = nc_src->nc_device +
+ strlen(nc_src->nc_device) - nc_src->nc_netid;
+ ++line_size;
+
+ nc_dst->nc_netid = malloc(line_size);
+ if (nc_dst->nc_netid == NULL)
+ goto failed;
+ memcpy(nc_dst->nc_netid, nc_src->nc_netid, line_size);
+
+ nc_dst->nc_nlookups = nc_src->nc_nlookups;
+ if (nc_dst->nc_nlookups != 0) {
+ nc_dst->nc_lookups = malloc(nc_dst->nc_nlookups *
+ sizeof(*nc_dst->nc_lookups));
+ if (nc_dst->nc_lookups == NULL) {
+ free(nc_dst->nc_netid);
+ goto failed;
+ }
+ for (i = 0; i < nc_dst->nc_nlookups; i++)
+ nc_dst->nc_lookups[i] = nc_dst->nc_netid +
+ (nc_src->nc_lookups[i] - nc_src->nc_netid);
+ } else
+ nc_dst->nc_lookups = NULL;
+
+ nc_dst->nc_semantics = nc_src->nc_semantics;
+ nc_dst->nc_flag = nc_src->nc_flag;
+ nc_dst->nc_protofmly = nc_dst->nc_netid +
+ (nc_src->nc_protofmly - nc_src->nc_netid);
+ nc_dst->nc_proto = nc_dst->nc_netid +
+ (nc_src->nc_proto - nc_src->nc_netid);
+ nc_dst->nc_device = nc_dst->nc_netid +
+ (nc_src->nc_device - nc_src->nc_netid);
+
+ return (nc_dst);
+
+failed:
+ nc_error = NC_ENOMEM;
+ free(nc_dst);
+ return (NULL);
+}
+
+void *
+setnetconfig(void)
+{
+ struct nc_handle *nc_handle;
+
+ nc_handle = malloc(sizeof(*nc_handle));
+ if (nc_handle == NULL) {
+ nc_error = NC_ENOMEM;
+ return (NULL);
+ }
+
+ mutex_lock(&nc_cache_lock);
+ if (nc_cache.error == NC_EINIT) {
+ nc_file = fopen(NETCONFIG, "r");
+ if (nc_file == NULL) {
+ nc_error = NC_EFILE;
+ mutex_unlock(&nc_cache_lock);
+ free(nc_handle);
+ return (NULL);
+ }
+ nc_cache.error = NC_NOERROR;
+ }
+ nc_cache.ref++;
+ mutex_unlock(&nc_cache_lock);
+
+ nc_session_rewind(nc_handle);
+ return (nc_handle);
+}
+
+struct netconfig *
+getnetconfig(void *handle)
+{
+ struct nc_handle *nc_handle;
+ struct nc_entry *nc_entry;
+ char *line, *line_data;
+ size_t line_len;
+
+ if (handle == NULL) {
+ nc_error = NC_EINIT;
+ return (NULL);
+ }
+ nc_handle = handle;
+
+ mutex_lock(&nc_cache_lock);
+
+ if (nc_handle->error != NC_NOERROR) {
+ nc_error = nc_handle->error;
+ mutex_unlock(&nc_cache_lock);
+ return (NULL);
+ }
+
+ nc_entry = nc_handle->nc_entry == NULL ?
+ STAILQ_FIRST(&nc_cache.list) :
+ STAILQ_NEXT(nc_handle->nc_entry, link);
+ if (nc_entry != NULL)
+ goto done;
+
+ if (nc_cache.error != NC_NOERROR) {
+ nc_error = nc_handle->error = nc_cache.error;
+ goto done;
+ }
+
+ line = malloc(NC_LINE_MAX);
+ nc_entry = malloc(sizeof(*nc_entry));
+ if (line == NULL || nc_entry == NULL) {
+ nc_error = NC_ENOMEM;
+ goto failed;
+ }
+
+ do {
+ if (fgets(line, NC_LINE_MAX, nc_file) == NULL) {
+ nc_error = feof(nc_file) ? NC_EEOF : NC_EIO;
+ goto failed;
+ }
+ line_len = strlen(line);
+ if (line[line_len - 1] != '\n' && !feof(nc_file)) {
+ nc_error = NC_ELBIG;
+ goto failed;
+ }
+ if (line[line_len - 1] == '\n') {
+ --line_len;
+ line[line_len] = '\0';
+ }
+ line_data = nc_skip_spaces(line);
+ line_len -= line_data - line;
+ } while (*line_data == '#' || *line_data == '\0');
+
+ if (nc_parse(line_data, line_len, &nc_entry->nc) < 0)
+ goto failed;
+
+ STAILQ_INSERT_TAIL(&nc_cache.list, nc_entry, link);
+ free(line);
+done:
+ nc_handle->nc_entry = nc_entry;
+ mutex_unlock(&nc_cache_lock);
+ return (nc_entry != NULL ? &nc_entry->nc : NULL);
+
+failed:
+ (void)fclose(nc_file);
+ nc_file = NULL;
+ nc_cache.error = nc_handle->error = nc_error;
+ mutex_unlock(&nc_cache_lock);
+ free(line);
+ free(nc_entry);
+ return (NULL);
+}
+
+void
+freenetconfigent(struct netconfig *nc)
+{
+ if (nc != NULL) {
+ free(nc->nc_netid);
+ free(nc->nc_lookups);
+ free(nc);
+ }
+}
+
+int
+endnetconfig(void *handle)
+{
+ struct nc_entry *nc_entry, *nc_entry_next;
+ int rv;
+
+ if (handle == NULL) {
+ nc_error = NC_EINIT;
+ return (-1);
+ }
+ free(handle);
+
+ rv = 0;
+ mutex_lock(&nc_cache_lock);
+ if (--nc_cache.ref == 0) {
+ nc_entry = STAILQ_FIRST(&nc_cache.list);
+ STAILQ_INIT(&nc_cache.list);
+ nc_cache.error = NC_EINIT;
+ if (nc_file != NULL) {
+ if (fclose(nc_file) != 0) {
+ nc_error = NC_EIO;
+ rv = -1;
+ }
+ nc_file = NULL;
+ }
+ } else
+ nc_entry = NULL;
+ mutex_unlock(&nc_cache_lock);
+
+ for (; nc_entry != NULL; nc_entry = nc_entry_next) {
+ nc_entry_next = STAILQ_NEXT(nc_entry, link);
+ free(nc_entry->nc.nc_netid);
+ free(nc_entry->nc.nc_lookups);
+ free(nc_entry);
+ }
+
+ return (rv);
+}
+
+struct netconfig *
+getnetconfigent(const char *netid)
+{
+ struct netconfig *nc;
+ void *handle;
+
+ if (netid == NULL) {
+ nc_error = NC_ENOENT;
+ return (NULL);
+ }
+
+ handle = setnetconfig();
+ if (handle == NULL)
+ return (NULL);
+
+ while ((nc = getnetconfig(handle)) != NULL)
+ if (strcmp(nc->nc_netid, netid) == 0) {
+ nc = nc_dup(nc);
+ break;
+ }
+ if (nc == NULL && nc_error == NC_EEOF)
+ nc_error = NC_ENOENT;
+
+ if (endnetconfig(handle) < 0) {
+ freenetconfigent(nc);
+ nc = NULL;
+ }
+
+ return (nc);
+}
+
+char *
+nc_sperror(void)
+{
+ return ((char *)nc_errlist[nc_error]);
+}
+
+void
+nc_perror(const char *s)
+{
+ fprintf(stderr, "%s: %s\n", s, nc_sperror());
+}
+
+void *
+setnetpath(void)
+{
+ const char *env;
+ struct np_handle *np_handle;
+
+ np_handle = malloc(sizeof(*np_handle));
+ if (np_handle == NULL) {
+ nc_error = NC_ENOMEM;
+ return (NULL);
+ }
+
+ env = getenv(NETPATH);
+ if (env != NULL) {
+ np_handle->np_env = strdup(env);
+ if (np_handle->np_env == NULL) {
+ nc_error = NC_ENOMEM;
+ goto failed;
+ }
+ } else
+ np_handle->np_env = NULL;
+ np_handle->np_cur = np_handle->np_env;
+
+ np_handle->nc_handle = setnetconfig();
+ if (np_handle->nc_handle == NULL)
+ goto failed;
+
+ return (np_handle);
+
+failed:
+ free(np_handle);
+ return (NULL);
+}
+
+struct netconfig *
+getnetpath(void *handle)
+{
+ struct np_handle *np_handle;
+ struct netconfig *nc;
+ void *nc_handle;
+ char *netid;
+
+ if (handle == NULL) {
+ nc_error = NC_EINIT;
+ return (NULL);
+ }
+ np_handle = handle;
+
+ nc_handle = np_handle->nc_handle;
+ if (np_handle->np_env == NULL) {
+ while ((nc = getnetconfig(nc_handle)) != NULL)
+ if (nc->nc_flag & NC_VISIBLE)
+ break;
+ } else {
+ nc = NULL;
+ nc_error = NC_EEOF;
+ mutex_lock(&np_handle_lock);
+ while ((netid = np_handle->np_cur) != NULL) {
+ np_handle->np_cur = nc_next_token(netid, ':');
+ if (*netid != '\0') {
+ nc_session_rewind(nc_handle);
+ nc_error = NC_NOERROR;
+ while ((nc = getnetconfig(nc_handle)) != NULL)
+ if (strcmp(nc->nc_netid, netid) == 0)
+ break;
+ if (nc != NULL || nc_error != NC_EEOF)
+ break;
+ }
+ }
+ mutex_unlock(&np_handle_lock);
+ }
+ return (nc);
+}
+
+int
+endnetpath(void *handle)
+{
+ struct np_handle *np_handle;
+ void *nc_handle;
+
+ if (handle == NULL) {
+ nc_error = NC_EINIT;
+ return (-1);
+ }
+ np_handle = handle;
+
+ nc_handle = np_handle->nc_handle;
+ free(np_handle->np_env);
+ free(np_handle);
+
+ return (endnetconfig(nc_handle));
+}
diff -ruNp libc.orig/rpc/rpc_com.h libc/rpc/rpc_com.h
--- libc.orig/rpc/rpc_com.h 2006-02-28 00:10:59.000000000 +0200
+++ libc/rpc/rpc_com.h 2012-09-27 13:39:20.000000000 +0300
@@ -80,8 +80,6 @@ struct netbuf *__rpcb_findaddr_timed(rpc
bool_t __rpc_control(int,void *);
-char *_get_next_token(char *, int);
-
bool_t __svc_clean_idle(fd_set *, int, bool_t);
bool_t __xdrrec_setnonblock(XDR *, int);
bool_t __xdrrec_getrec(XDR *, enum xprt_stat *, bool_t);
More information about the freebsd-bugs
mailing list