yp_enum.c revision 1219:f89f56c2d9ac
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22
23/*
24 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
25 * Use is subject to license terms.
26 */
27
28/*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
29/*	  All Rights Reserved   */
30
31/*
32 * Portions of this source code were derived from Berkeley
33 * under license from the Regents of the University of
34 * California.
35 */
36
37#pragma ident	"%Z%%M%	%I%	%E% SMI"
38
39#include "mt.h"
40#include <stdlib.h>
41#include <unistd.h>
42#include <rpc/rpc.h>
43#include <sys/types.h>
44#include "yp_b.h"
45#include <rpcsvc/yp_prot.h>
46#include <rpcsvc/ypclnt.h>
47#include <string.h>
48
49extern int __yp_dobind_cflookup(char *, struct dom_binding **, int);
50
51static int dofirst(char *, char *, struct dom_binding *, struct timeval,
52    char **, int  *, char **, int  *);
53
54static int donext(char *, char *, char *, int, struct dom_binding *,
55    struct timeval, char **, int *, char **val, int *);
56
57/*
58 * This requests the yp server associated with a given domain to return the
59 * first key/value pair from the map data base.  The returned key should be
60 * used as an input to the call to ypclnt_next.  This part does the parameter
61 * checking, and the do-until-success loop if 'hardlookup' is set.
62 */
63int
64__yp_first_cflookup(
65	char *domain,
66	char *map,
67	char **key,		/* return: key array */
68	int  *keylen,		/* return: bytes in key */
69	char **val,		/* return: value array */
70	int  *vallen,		/* return: bytes in val */
71	int  hardlookup)
72{
73	size_t domlen;
74	size_t maplen;
75	struct dom_binding *pdomb;
76	int reason;
77
78	if ((map == NULL) || (domain == NULL))
79		return (YPERR_BADARGS);
80
81	domlen =  strlen(domain);
82	maplen =  strlen(map);
83
84	if ((domlen == 0) || (domlen > YPMAXDOMAIN) ||
85	    (maplen == 0) || (maplen > YPMAXMAP))
86		return (YPERR_BADARGS);
87
88	for (;;) {
89
90		if (reason = __yp_dobind_cflookup(domain, &pdomb, hardlookup))
91			return (reason);
92
93		if (pdomb->dom_binding->ypbind_hi_vers == YPVERS) {
94
95			reason = dofirst(domain, map, pdomb, _ypserv_timeout,
96			    key, keylen, val, vallen);
97
98			__yp_rel_binding(pdomb);
99			if (reason == YPERR_RPC || reason == YPERR_YPSERV ||
100			    reason == YPERR_BUSY /* as if */) {
101				yp_unbind(domain);
102				if (hardlookup)
103					(void) sleep(_ypsleeptime); /* retry */
104				else
105					return (reason);
106			} else
107				break;
108		} else {
109			__yp_rel_binding(pdomb);
110			return (YPERR_VERS);
111		}
112	}
113	return (reason);
114}
115
116int
117yp_first(
118	char *domain,
119	char *map,
120	char **key,		/* return: key array */
121	int  *keylen,		/* return: bytes in key */
122	char **val,		/* return: value array */
123	int  *vallen)		/* return: bytes in val */
124{
125	/* traditional yp_firs loops forever until success */
126	return (__yp_first_cflookup(domain, map, key, keylen, val, vallen, 1));
127}
128
129/*
130 * This part of the "get first" interface talks to ypserv.
131 */
132
133static int
134dofirst(domain, map, pdomb, timeout, key, keylen, val, vallen)
135	char *domain;
136	char *map;
137	struct dom_binding *pdomb;
138	struct timeval timeout;
139	char **key;
140	int  *keylen;
141	char **val;
142	int  *vallen;
143
144{
145	struct ypreq_nokey req;
146	struct ypresp_key_val resp;
147	unsigned int retval = 0;
148
149	req.domain = domain;
150	req.map = map;
151	resp.keydat.dptr = resp.valdat.dptr = NULL;
152	resp.keydat.dsize = resp.valdat.dsize = 0;
153
154	/*
155	 * Do the get first request.  If the rpc call failed, return with status
156	 * from this point.
157	 */
158
159	(void) memset((char *)&resp, 0, sizeof (struct ypresp_key_val));
160
161	switch (clnt_call(pdomb->dom_client, YPPROC_FIRST,
162			(xdrproc_t)xdr_ypreq_nokey,
163			(char *)&req, (xdrproc_t)xdr_ypresp_key_val,
164			(char *)&resp, timeout)) {
165	case RPC_SUCCESS:
166		break;
167	case RPC_TIMEDOUT:
168		return (YPERR_YPSERV);
169	default:
170		return (YPERR_RPC);
171	}
172
173	/* See if the request succeeded */
174
175	if (resp.status != YP_TRUE) {
176		retval = ypprot_err(resp.status);
177	}
178
179	/* Get some memory which the user can get rid of as he likes */
180
181	if (!retval) {
182
183		if ((*key = malloc((size_t)resp.keydat.dsize + 2)) != NULL) {
184
185			if ((*val = malloc(
186			    (size_t)resp.valdat.dsize + 2)) == NULL) {
187				free(*key);
188				retval = YPERR_RESRC;
189			}
190
191		} else {
192			retval = YPERR_RESRC;
193		}
194	}
195
196	/* Copy the returned key and value byte strings into the new memory */
197
198	if (!retval) {
199		*keylen = (int)resp.keydat.dsize;
200		(void) memcpy(*key, resp.keydat.dptr,
201		    (size_t)resp.keydat.dsize);
202		(*key)[resp.keydat.dsize] = '\n';
203		(*key)[resp.keydat.dsize + 1] = '\0';
204
205		*vallen = (int)resp.valdat.dsize;
206		(void) memcpy(*val, resp.valdat.dptr,
207		    (size_t)resp.valdat.dsize);
208		(*val)[resp.valdat.dsize] = '\n';
209		(*val)[resp.valdat.dsize + 1] = '\0';
210	}
211
212	CLNT_FREERES(pdomb->dom_client,
213		(xdrproc_t)xdr_ypresp_key_val, (char *)&resp);
214	return (retval);
215}
216
217/*
218 * This requests the yp server associated with a given domain to return the
219 * "next" key/value pair from the map data base.  The input key should be
220 * one returned by ypclnt_first or a previous call to ypclnt_next.  The
221 * returned key should be used as an input to the next call to ypclnt_next.
222 * This part does the parameter checking, and the do-until-success loop.
223 * if 'hardlookup' is set.
224 */
225int
226__yp_next_cflookup(
227	char *domain,
228	char *map,
229	char *inkey,
230	int  inkeylen,
231	char **outkey,		/* return: key array associated with val */
232	int  *outkeylen,	/* return: bytes in key */
233	char **val,		/* return: value array associated with outkey */
234	int  *vallen,		/* return: bytes in val */
235	int  hardlookup)
236{
237	size_t domlen;
238	size_t maplen;
239	struct dom_binding *pdomb;
240	int reason;
241
242
243	if ((map == NULL) || (domain == NULL) || (inkey == NULL))
244		return (YPERR_BADARGS);
245
246	domlen =  strlen(domain);
247	maplen =  strlen(map);
248
249	if ((domlen == 0) || (domlen > YPMAXDOMAIN) ||
250	    (maplen == 0) || (maplen > YPMAXMAP))
251		return (YPERR_BADARGS);
252
253	for (;;) {
254		if (reason = __yp_dobind_cflookup(domain, &pdomb, hardlookup))
255			return (reason);
256
257		if (pdomb->dom_binding->ypbind_hi_vers == YPVERS) {
258
259			reason = donext(domain, map, inkey, inkeylen, pdomb,
260			    _ypserv_timeout, outkey, outkeylen, val, vallen);
261
262			__yp_rel_binding(pdomb);
263
264			if (reason == YPERR_RPC || reason == YPERR_YPSERV ||
265			    reason == YPERR_BUSY /* as if */) {
266				yp_unbind(domain);
267				if (hardlookup)
268					(void) sleep(_ypsleeptime); /* retry */
269				else
270					return (reason);
271			} else
272				break;
273		} else {
274			__yp_rel_binding(pdomb);
275			return (YPERR_VERS);
276		}
277	}
278
279	return (reason);
280}
281
282int
283yp_next(
284	char *domain,
285	char *map,
286	char *inkey,
287	int  inkeylen,
288	char **outkey,		/* return: key array associated with val */
289	int  *outkeylen,	/* return: bytes in key */
290	char **val,		/* return: value array associated with outkey */
291	int  *vallen)		/* return: bytes in val */
292{
293	/* traditional yp_next loops forever until success */
294	return (__yp_next_cflookup(domain, map, inkey, inkeylen, outkey,
295				outkeylen, val, vallen, 1));
296}
297
298
299/*
300 * This part of the "get next" interface talks to ypserv.
301 */
302static int
303donext(domain, map, inkey, inkeylen, pdomb, timeout, outkey, outkeylen,
304    val, vallen)
305	char *domain;
306	char *map;
307	char *inkey;
308	int  inkeylen;
309	struct dom_binding *pdomb;
310	struct timeval timeout;
311	char **outkey;		/* return: key array associated with val */
312	int  *outkeylen;	/* return: bytes in key */
313	char **val;		/* return: value array associated with outkey */
314	int  *vallen;		/* return: bytes in val */
315
316{
317	struct ypreq_key req;
318	struct ypresp_key_val resp;
319	unsigned int retval = 0;
320
321	req.domain = domain;
322	req.map = map;
323	req.keydat.dptr = inkey;
324	req.keydat.dsize = inkeylen;
325
326	resp.keydat.dptr = resp.valdat.dptr = NULL;
327	resp.keydat.dsize = resp.valdat.dsize = 0;
328
329	/*
330	 * Do the get next request.  If the rpc call failed, return with status
331	 * from this point.
332	 */
333
334	switch (clnt_call(pdomb->dom_client,
335			YPPROC_NEXT, (xdrproc_t)xdr_ypreq_key, (char *)&req,
336			(xdrproc_t)xdr_ypresp_key_val, (char *)&resp,
337			timeout)) {
338	case RPC_SUCCESS:
339		break;
340	case RPC_TIMEDOUT:
341		return (YPERR_YPSERV);
342	default:
343		return (YPERR_RPC);
344	}
345
346	/* See if the request succeeded */
347
348	if (resp.status != YP_TRUE) {
349		retval = ypprot_err(resp.status);
350	}
351
352	/* Get some memory which the user can get rid of as he likes */
353
354	if (!retval) {
355		if ((*outkey = malloc((size_t)
356		    resp.keydat.dsize + 2)) != NULL) {
357
358			if ((*val = malloc((size_t)
359			    resp.valdat.dsize + 2)) == NULL) {
360				free(*outkey);
361				retval = YPERR_RESRC;
362			}
363
364		} else {
365			retval = YPERR_RESRC;
366		}
367	}
368
369	/* Copy the returned key and value byte strings into the new memory */
370
371	if (!retval) {
372		*outkeylen = (int)resp.keydat.dsize;
373		(void) memcpy(*outkey, resp.keydat.dptr,
374		    (size_t)resp.keydat.dsize);
375		(*outkey)[resp.keydat.dsize] = '\n';
376		(*outkey)[resp.keydat.dsize + 1] = '\0';
377
378		*vallen = (int)resp.valdat.dsize;
379		(void) memcpy(*val, resp.valdat.dptr,
380		    (size_t)resp.valdat.dsize);
381		(*val)[resp.valdat.dsize] = '\n';
382		(*val)[resp.valdat.dsize + 1] = '\0';
383	}
384
385	CLNT_FREERES(pdomb->dom_client, (xdrproc_t)xdr_ypresp_key_val,
386		    (char *)&resp);
387	return (retval);
388}
389