diff options
Diffstat (limited to 'lib/libc/rpc/clnt_simple.c')
-rw-r--r-- | lib/libc/rpc/clnt_simple.c | 189 |
1 files changed, 130 insertions, 59 deletions
diff --git a/lib/libc/rpc/clnt_simple.c b/lib/libc/rpc/clnt_simple.c index 46d959b..09b65fc 100644 --- a/lib/libc/rpc/clnt_simple.c +++ b/lib/libc/rpc/clnt_simple.c @@ -1,3 +1,5 @@ +/* $NetBSD: clnt_simple.c,v 1.21 2000/07/06 03:10:34 christos Exp $ */ + /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape @@ -26,6 +28,9 @@ * 2550 Garcia Avenue * Mountain View, California 94043 */ +/* + * Copyright (c) 1986-1991 by Sun Microsystems Inc. + */ #if defined(LIBC_SCCS) && !defined(lint) /*static char *sccsid = "from: @(#)clnt_simple.c 1.35 87/08/11 Copyr 1984 Sun Micro";*/ @@ -35,90 +40,156 @@ static char *rcsid = "$FreeBSD$"; /* * clnt_simple.c - * Simplified front end to rpc. + * Simplified front end to client rpc. * - * Copyright (C) 1984, Sun Microsystems, Inc. */ +#include "reentrant.h" #include "namespace.h" #include <sys/param.h> #include <stdio.h> +#include <errno.h> +#include <rpc/rpc.h> +#include <string.h> #include <stdlib.h> +#include <fcntl.h> #include <unistd.h> -#include <string.h> -#include <rpc/rpc.h> -#include <sys/socket.h> -#include <netdb.h> #include "un-namespace.h" -static struct callrpc_private { - CLIENT *client; - int socket; - int oldprognum, oldversnum, valid; - char *oldhost; -} *callrpc_private; +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + +#ifndef NETIDLEN +#define NETIDLEN 32 +#endif + +struct rpc_call_private { + int valid; /* Is this entry valid ? */ + CLIENT *client; /* Client handle */ + pid_t pid; /* process-id at moment of creation */ + rpcprog_t prognum; /* Program */ + rpcvers_t versnum; /* Version */ + char host[MAXHOSTNAMELEN]; /* Servers host */ + char nettype[NETIDLEN]; /* Network type */ +}; +static struct rpc_call_private *rpc_call_private_main; -int -callrpc(host, prognum, versnum, procnum, inproc, in, outproc, out) - char *host; - int prognum, versnum, procnum; - xdrproc_t inproc, outproc; - char *in, *out; +static void rpc_call_destroy __P((void *)); + +static void +rpc_call_destroy(void *vp) { - register struct callrpc_private *crp = callrpc_private; - struct sockaddr_in server_addr; + struct rpc_call_private *rcp = (struct rpc_call_private *)vp; + + if (rcp) { + if (rcp->client) + CLNT_DESTROY(rcp->client); + free(rcp); + } +} + +/* + * This is the simplified interface to the client rpc layer. + * The client handle is not destroyed here and is reused for + * the future calls to same prog, vers, host and nettype combination. + * + * The total time available is 25 seconds. + */ +enum clnt_stat +rpc_call(host, prognum, versnum, procnum, inproc, in, outproc, out, nettype) + const char *host; /* host name */ + rpcprog_t prognum; /* program number */ + rpcvers_t versnum; /* version number */ + rpcproc_t procnum; /* procedure number */ + xdrproc_t inproc, outproc; /* in/out XDR procedures */ + const char *in; + char *out; /* recv/send data */ + const char *nettype; /* nettype */ +{ + struct rpc_call_private *rcp = (struct rpc_call_private *) 0; enum clnt_stat clnt_stat; - struct hostent *hp; struct timeval timeout, tottimeout; + static thread_key_t rpc_call_key; + extern mutex_t tsd_lock; + int main_thread = 1; - if (crp == 0) { - crp = (struct callrpc_private *)calloc(1, sizeof (*crp)); - if (crp == 0) - return (0); - callrpc_private = crp; + if ((main_thread = thr_main())) { + rcp = rpc_call_private_main; + } else { + if (rpc_call_key == 0) { + mutex_lock(&tsd_lock); + if (rpc_call_key == 0) + thr_keycreate(&rpc_call_key, rpc_call_destroy); + mutex_unlock(&tsd_lock); + } + rcp = (struct rpc_call_private *)thr_getspecific(rpc_call_key); } - if (crp->oldhost == NULL) { - crp->oldhost = malloc(MAXHOSTNAMELEN); - crp->oldhost[0] = 0; - crp->socket = RPC_ANYSOCK; + if (rcp == NULL) { + rcp = malloc(sizeof (*rcp)); + if (rcp == NULL) { + rpc_createerr.cf_stat = RPC_SYSTEMERROR; + rpc_createerr.cf_error.re_errno = errno; + return (rpc_createerr.cf_stat); + } + if (main_thread) + rpc_call_private_main = rcp; + else + thr_setspecific(rpc_call_key, (void *) rcp); + rcp->valid = 0; + rcp->client = NULL; } - if (crp->valid && crp->oldprognum == prognum && crp->oldversnum == versnum - && strcmp(crp->oldhost, host) == 0) { - /* reuse old client */ - } else { - crp->valid = 0; - if (crp->socket != -1) - (void)_close(crp->socket); - crp->socket = RPC_ANYSOCK; - if (crp->client) { - clnt_destroy(crp->client); - crp->client = NULL; + if ((nettype == NULL) || (nettype[0] == NULL)) + nettype = "netpath"; + if (!(rcp->valid && rcp->pid == getpid() && + (rcp->prognum == prognum) && + (rcp->versnum == versnum) && + (!strcmp(rcp->host, host)) && + (!strcmp(rcp->nettype, nettype)))) { + int fd; + + rcp->valid = 0; + if (rcp->client) + CLNT_DESTROY(rcp->client); + /* + * Using the first successful transport for that type + */ + rcp->client = clnt_create(host, prognum, versnum, nettype); + rcp->pid = getpid(); + if (rcp->client == NULL) { + return (rpc_createerr.cf_stat); } - if ((hp = gethostbyname(host)) == NULL) - return ((int) RPC_UNKNOWNHOST); + /* + * Set time outs for connectionless case. Do it + * unconditionally. Faster than doing a t_getinfo() + * and then doing the right thing. + */ timeout.tv_usec = 0; timeout.tv_sec = 5; - memset(&server_addr, 0, sizeof(server_addr)); - memcpy((char *)&server_addr.sin_addr, hp->h_addr, hp->h_length); - server_addr.sin_len = sizeof(struct sockaddr_in); - server_addr.sin_family = AF_INET; - server_addr.sin_port = 0; - if ((crp->client = clntudp_create(&server_addr, (u_long)prognum, - (u_long)versnum, timeout, &crp->socket)) == NULL) - return ((int) rpc_createerr.cf_stat); - crp->valid = 1; - crp->oldprognum = prognum; - crp->oldversnum = versnum; - (void) strcpy(crp->oldhost, host); - } + (void) CLNT_CONTROL(rcp->client, + CLSET_RETRY_TIMEOUT, (char *)(void *)&timeout); + if (CLNT_CONTROL(rcp->client, CLGET_FD, (char *)(void *)&fd)) + _fcntl(fd, F_SETFD, 1); /* make it "close on exec" */ + rcp->prognum = prognum; + rcp->versnum = versnum; + if ((strlen(host) < (size_t)MAXHOSTNAMELEN) && + (strlen(nettype) < (size_t)NETIDLEN)) { + (void) strcpy(rcp->host, host); + (void) strcpy(rcp->nettype, nettype); + rcp->valid = 1; + } else { + rcp->valid = 0; + } + } /* else reuse old client */ tottimeout.tv_sec = 25; tottimeout.tv_usec = 0; - clnt_stat = clnt_call(crp->client, procnum, inproc, in, + /*LINTED const castaway*/ + clnt_stat = CLNT_CALL(rcp->client, procnum, inproc, (char *) in, outproc, out, tottimeout); /* * if call failed, empty cache */ if (clnt_stat != RPC_SUCCESS) - crp->valid = 0; - return ((int) clnt_stat); + rcp->valid = 0; + return (clnt_stat); } |