summaryrefslogtreecommitdiffstats
path: root/lib/libc/rpc/clnt_simple.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc/rpc/clnt_simple.c')
-rw-r--r--lib/libc/rpc/clnt_simple.c189
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);
}
OpenPOWER on IntegriCloud