/* $NetBSD: pmap_prot2.c,v 1.14 2000/07/06 03:10:34 christos Exp $ */12/*-3* SPDX-License-Identifier: BSD-3-Clause4*5* Copyright (c) 2009, Sun Microsystems, Inc.6* All rights reserved.7*8* Redistribution and use in source and binary forms, with or without9* modification, are permitted provided that the following conditions are met:10* - Redistributions of source code must retain the above copyright notice,11* this list of conditions and the following disclaimer.12* - Redistributions in binary form must reproduce the above copyright notice,13* this list of conditions and the following disclaimer in the documentation14* and/or other materials provided with the distribution.15* - Neither the name of Sun Microsystems, Inc. nor the names of its16* contributors may be used to endorse or promote products derived17* from this software without specific prior written permission.18*19* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"20* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE21* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE22* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE23* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR24* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF25* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS26* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN27* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)28* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE29* POSSIBILITY OF SUCH DAMAGE.30*/3132/*33* pmap_prot2.c34* Protocol for the local binder service, or pmap.35*36* Copyright (C) 1984, Sun Microsystems, Inc.37*/3839#include "namespace.h"40#include <assert.h>4142#include <rpc/types.h>43#include <rpc/xdr.h>44#include <rpc/pmap_prot.h>45#include "un-namespace.h"464748/*49* What is going on with linked lists? (!)50* First recall the link list declaration from pmap_prot.h:51*52* struct pmaplist {53* struct pmap pml_map;54* struct pmaplist *pml_map;55* };56*57* Compare that declaration with a corresponding xdr declaration that58* is (a) pointer-less, and (b) recursive:59*60* typedef union switch (bool_t) {61*62* case TRUE: struct {63* struct pmap;64* pmaplist_t foo;65* };66*67* case FALSE: struct {};68* } pmaplist_t;69*70* Notice that the xdr declaration has no nxt pointer while71* the C declaration has no bool_t variable. The bool_t can be72* interpreted as ``more data follows me''; if FALSE then nothing73* follows this bool_t; if TRUE then the bool_t is followed by74* an actual struct pmap, and then (recursively) by the75* xdr union, pamplist_t.76*77* This could be implemented via the xdr_union primitive, though this78* would cause a one recursive call per element in the list. Rather than do79* that we can ``unwind'' the recursion80* into a while loop and do the union arms in-place.81*82* The head of the list is what the C programmer wishes to past around83* the net, yet is the data that the pointer points to which is interesting;84* this sounds like a job for xdr_reference!85*/86bool_t87xdr_pmaplist(XDR *xdrs, struct pmaplist **rp)88{89/*90* more_elements is pre-computed in case the direction is91* XDR_ENCODE or XDR_FREE. more_elements is overwritten by92* xdr_bool when the direction is XDR_DECODE.93*/94bool_t more_elements;95int freeing;96struct pmaplist **next = NULL; /* pacify gcc */9798assert(xdrs != NULL);99assert(rp != NULL);100101freeing = (xdrs->x_op == XDR_FREE);102103for (;;) {104more_elements = (bool_t)(*rp != NULL);105if (! xdr_bool(xdrs, &more_elements))106return (FALSE);107if (! more_elements)108return (TRUE); /* we are done */109/*110* the unfortunate side effect of non-recursion is that in111* the case of freeing we must remember the next object112* before we free the current object ...113*/114if (freeing)115next = &((*rp)->pml_next);116if (! xdr_reference(xdrs, (caddr_t *)rp,117(u_int)sizeof(struct pmaplist), (xdrproc_t)xdr_pmap))118return (FALSE);119rp = (freeing) ? next : &((*rp)->pml_next);120}121}122123124/*125* xdr_pmaplist_ptr() is specified to take a PMAPLIST *, but is identical in126* functionality to xdr_pmaplist().127*/128bool_t129xdr_pmaplist_ptr(XDR *xdrs, struct pmaplist *rp)130{131return xdr_pmaplist(xdrs, (struct pmaplist **)(void *)rp);132}133134135