1/*	$NetBSD: getrpcent.c,v 1.22 2011/10/15 23:00:02 christos Exp $	*/
2
3/*
4 * Copyright (c) 2010, Oracle America, Inc.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 *     * Redistributions of source code must retain the above copyright
11 *       notice, this list of conditions and the following disclaimer.
12 *     * Redistributions in binary form must reproduce the above
13 *       copyright notice, this list of conditions and the following
14 *       disclaimer in the documentation and/or other materials
15 *       provided with the distribution.
16 *     * Neither the name of the "Oracle America, Inc." nor the names of its
17 *       contributors may be used to endorse or promote products derived
18 *       from this software without specific prior written permission.
19 *
20 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25 *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27 *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34#include <sys/cdefs.h>
35#if defined(LIBC_SCCS) && !defined(lint)
36#if 0
37static char *sccsid = "@(#)getrpcent.c 1.14 91/03/11 Copyr 1984 Sun Micro";
38#else
39__RCSID("$NetBSD: getrpcent.c,v 1.22 2011/10/15 23:00:02 christos Exp $");
40#endif
41#endif
42
43/*
44 * Copyright (c) 1984 by Sun Microsystems, Inc.
45 */
46
47#include "namespace.h"
48
49#include <sys/types.h>
50
51#include <netinet/in.h>
52#include <arpa/inet.h>
53
54#include <assert.h>
55#include <netdb.h>
56#include <stdio.h>
57#include <stdlib.h>
58#include <string.h>
59
60#include <rpc/rpc.h>
61
62#ifdef __weak_alias
63__weak_alias(endrpcent,_endrpcent)
64__weak_alias(getrpcbyname,_getrpcbyname)
65__weak_alias(getrpcbynumber,_getrpcbynumber)
66__weak_alias(getrpcent,_getrpcent)
67__weak_alias(setrpcent,_setrpcent)
68#endif
69
70/*
71 * Internet version.
72 */
73static struct rpcdata {
74	FILE	*rpcf;
75	int	stayopen;
76#define	MAXALIASES	35
77	char	*rpc_aliases[MAXALIASES];
78	struct	rpcent rpc;
79	char	line[BUFSIZ+1];
80} *rpcdata;
81
82static	struct rpcent *interpret(char *val, size_t len);
83
84#define	RPCDB	"/etc/rpc"
85
86static struct rpcdata *_rpcdata(void);
87
88static struct rpcdata *
89_rpcdata(void)
90{
91	struct rpcdata *d = rpcdata;
92
93	if (d == 0) {
94		d = (struct rpcdata *)calloc(1, sizeof (struct rpcdata));
95		rpcdata = d;
96	}
97	return (d);
98}
99
100struct rpcent *
101getrpcbynumber(int number)
102{
103	struct rpcent *rpc;
104
105	setrpcent(0);
106	while ((rpc = getrpcent()) != NULL) {
107		if (rpc->r_number == number)
108			break;
109	}
110	endrpcent();
111	return (rpc);
112}
113
114struct rpcent *
115getrpcbyname(const char *name)
116{
117	struct rpcent *rpc;
118	char **rp;
119
120	_DIAGASSERT(name != NULL);
121
122	setrpcent(0);
123	while ((rpc = getrpcent()) != NULL) {
124		if (strcmp(rpc->r_name, name) == 0)
125			break;
126		for (rp = rpc->r_aliases; *rp != NULL; rp++) {
127			if (strcmp(*rp, name) == 0)
128				goto found;
129		}
130	}
131found:
132	endrpcent();
133	return (rpc);
134}
135
136void
137setrpcent(int f)
138{
139	struct rpcdata *d = _rpcdata();
140
141	if (d == 0)
142		return;
143	if (d->rpcf == NULL)
144		d->rpcf = fopen(RPCDB, "re");
145	else
146		rewind(d->rpcf);
147	d->stayopen |= f;
148}
149
150void
151endrpcent(void)
152{
153	struct rpcdata *d = _rpcdata();
154
155	if (d == 0)
156		return;
157	if (d->rpcf && !d->stayopen) {
158		fclose(d->rpcf);
159		d->rpcf = NULL;
160	}
161}
162
163struct rpcent *
164getrpcent(void)
165{
166	struct rpcdata *d = _rpcdata();
167
168	if (d == 0)
169		return(NULL);
170	if (d->rpcf == NULL && (d->rpcf = fopen(RPCDB, "re")) == NULL)
171		return (NULL);
172	if (fgets(d->line, BUFSIZ, d->rpcf) == NULL)
173		return (NULL);
174	return (interpret(d->line, strlen(d->line)));
175}
176
177static struct rpcent *
178interpret(char *val, size_t len)
179{
180	struct rpcdata *d = _rpcdata();
181	char *p;
182	char *cp, **q;
183
184	_DIAGASSERT(val != NULL);
185
186	if (d == 0)
187		return (0);
188	(void) strncpy(d->line, val, len);
189	p = d->line;
190	d->line[len] = '\n';
191	if (*p == '#')
192		return (getrpcent());
193	cp = strpbrk(p, "#\n");
194	if (cp == NULL)
195		return (getrpcent());
196	*cp = '\0';
197	cp = strpbrk(p, " \t");
198	if (cp == NULL)
199		return (getrpcent());
200	*cp++ = '\0';
201	/* THIS STUFF IS INTERNET SPECIFIC */
202	d->rpc.r_name = d->line;
203	while (*cp == ' ' || *cp == '\t')
204		cp++;
205	d->rpc.r_number = atoi(cp);
206	q = d->rpc.r_aliases = d->rpc_aliases;
207	cp = strpbrk(cp, " \t");
208	if (cp != NULL)
209		*cp++ = '\0';
210	while (cp && *cp) {
211		if (*cp == ' ' || *cp == '\t') {
212			cp++;
213			continue;
214		}
215		if (q < &(d->rpc_aliases[MAXALIASES - 1]))
216			*q++ = cp;
217		cp = strpbrk(cp, " \t");
218		if (cp != NULL)
219			*cp++ = '\0';
220	}
221	*q = NULL;
222	return (&d->rpc);
223}
224