174462Salfred/*	$NetBSD: pmap_prot2.c,v 1.14 2000/07/06 03:10:34 christos Exp $	*/
274462Salfred
3261057Smav/*-
4261057Smav * Copyright (c) 2009, Sun Microsystems, Inc.
5261057Smav * All rights reserved.
68870Srgrimes *
7261057Smav * Redistribution and use in source and binary forms, with or without
8261057Smav * modification, are permitted provided that the following conditions are met:
9261057Smav * - Redistributions of source code must retain the above copyright notice,
10261057Smav *   this list of conditions and the following disclaimer.
11261057Smav * - Redistributions in binary form must reproduce the above copyright notice,
12261057Smav *   this list of conditions and the following disclaimer in the documentation
13261057Smav *   and/or other materials provided with the distribution.
14261057Smav * - Neither the name of Sun Microsystems, Inc. nor the names of its
15261057Smav *   contributors may be used to endorse or promote products derived
16261057Smav *   from this software without specific prior written permission.
17261057Smav *
18261057Smav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19261057Smav * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20261057Smav * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21261057Smav * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22261057Smav * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23261057Smav * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24261057Smav * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25261057Smav * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26261057Smav * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27261057Smav * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28261057Smav * POSSIBILITY OF SUCH DAMAGE.
291901Swollman */
301901Swollman
311901Swollman#if defined(LIBC_SCCS) && !defined(lint)
32136581Sobrienstatic char *sccsid2 = "@(#)pmap_prot2.c 1.3 87/08/11 Copyr 1984 Sun Micro";
3374462Salfredstatic char *sccsid = "@(#)pmap_prot2.c	2.1 88/07/29 4.0 RPCSRC";
341901Swollman#endif
3592990Sobrien#include <sys/cdefs.h>
3692990Sobrien__FBSDID("$FreeBSD$");
371901Swollman
381901Swollman/*
391901Swollman * pmap_prot2.c
401901Swollman * Protocol for the local binder service, or pmap.
411901Swollman *
421901Swollman * Copyright (C) 1984, Sun Microsystems, Inc.
431901Swollman */
441901Swollman
4574462Salfred#include "namespace.h"
4674462Salfred#include <assert.h>
4774462Salfred
481901Swollman#include <rpc/types.h>
491901Swollman#include <rpc/xdr.h>
501901Swollman#include <rpc/pmap_prot.h>
5174462Salfred#include "un-namespace.h"
521901Swollman
531901Swollman
548870Srgrimes/*
551901Swollman * What is going on with linked lists? (!)
561901Swollman * First recall the link list declaration from pmap_prot.h:
571901Swollman *
581901Swollman * struct pmaplist {
591901Swollman *	struct pmap pml_map;
601901Swollman *	struct pmaplist *pml_map;
611901Swollman * };
621901Swollman *
638870Srgrimes * Compare that declaration with a corresponding xdr declaration that
641901Swollman * is (a) pointer-less, and (b) recursive:
651901Swollman *
661901Swollman * typedef union switch (bool_t) {
678870Srgrimes *
681901Swollman *	case TRUE: struct {
691901Swollman *		struct pmap;
701901Swollman * 		pmaplist_t foo;
711901Swollman *	};
721901Swollman *
731901Swollman *	case FALSE: struct {};
741901Swollman * } pmaplist_t;
751901Swollman *
761901Swollman * Notice that the xdr declaration has no nxt pointer while
771901Swollman * the C declaration has no bool_t variable.  The bool_t can be
781901Swollman * interpreted as ``more data follows me''; if FALSE then nothing
791901Swollman * follows this bool_t; if TRUE then the bool_t is followed by
808870Srgrimes * an actual struct pmap, and then (recursively) by the
818870Srgrimes * xdr union, pamplist_t.
821901Swollman *
831901Swollman * This could be implemented via the xdr_union primitive, though this
841901Swollman * would cause a one recursive call per element in the list.  Rather than do
851901Swollman * that we can ``unwind'' the recursion
861901Swollman * into a while loop and do the union arms in-place.
871901Swollman *
881901Swollman * The head of the list is what the C programmer wishes to past around
891901Swollman * the net, yet is the data that the pointer points to which is interesting;
901901Swollman * this sounds like a job for xdr_reference!
911901Swollman */
921901Swollmanbool_t
931901Swollmanxdr_pmaplist(xdrs, rp)
9474462Salfred	XDR *xdrs;
9574462Salfred	struct pmaplist **rp;
961901Swollman{
971901Swollman	/*
981901Swollman	 * more_elements is pre-computed in case the direction is
991901Swollman	 * XDR_ENCODE or XDR_FREE.  more_elements is overwritten by
1001901Swollman	 * xdr_bool when the direction is XDR_DECODE.
1011901Swollman	 */
1021901Swollman	bool_t more_elements;
10374462Salfred	int freeing;
10474462Salfred	struct pmaplist **next	= NULL; /* pacify gcc */
1051901Swollman
10674462Salfred	assert(xdrs != NULL);
10774462Salfred	assert(rp != NULL);
10874462Salfred
10974462Salfred	freeing = (xdrs->x_op == XDR_FREE);
11074462Salfred
11174462Salfred	for (;;) {
1121901Swollman		more_elements = (bool_t)(*rp != NULL);
1131901Swollman		if (! xdr_bool(xdrs, &more_elements))
1141901Swollman			return (FALSE);
1151901Swollman		if (! more_elements)
1161901Swollman			return (TRUE);  /* we are done */
1171901Swollman		/*
1181901Swollman		 * the unfortunate side effect of non-recursion is that in
1191901Swollman		 * the case of freeing we must remember the next object
1201901Swollman		 * before we free the current object ...
1211901Swollman		 */
1221901Swollman		if (freeing)
12374462Salfred			next = &((*rp)->pml_next);
1241901Swollman		if (! xdr_reference(xdrs, (caddr_t *)rp,
12574462Salfred		    (u_int)sizeof(struct pmaplist), (xdrproc_t)xdr_pmap))
1261901Swollman			return (FALSE);
1271901Swollman		rp = (freeing) ? next : &((*rp)->pml_next);
1281901Swollman	}
1291901Swollman}
13074462Salfred
13174462Salfred
13274462Salfred/*
13374462Salfred * xdr_pmaplist_ptr() is specified to take a PMAPLIST *, but is identical in
13474462Salfred * functionality to xdr_pmaplist().
13574462Salfred */
13674462Salfredbool_t
13774462Salfredxdr_pmaplist_ptr(xdrs, rp)
13874462Salfred	XDR *xdrs;
13974462Salfred	struct pmaplist *rp;
14074462Salfred{
14174462Salfred	return xdr_pmaplist(xdrs, (struct pmaplist **)(void *)rp);
14274462Salfred}
143