1 /* $NetBSD: clnt_simple.c,v 1.30 2010/12/08 02:06:38 joerg Exp $ */
4 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
5 * unrestricted use provided that this legend is included on all tape
6 * media and as a part of the software program in whole or part. Users
7 * may copy or modify Sun RPC without charge, but are not authorized
8 * to license or distribute it to anyone else except as part of a product or
9 * program developed by the user.
11 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
12 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
13 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
15 * Sun RPC is provided with no support and without any obligation on the
16 * part of Sun Microsystems, Inc. to assist in its use, correction,
17 * modification or enhancement.
19 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
20 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
21 * OR ANY PART THEREOF.
23 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
24 * or profits or other special, indirect and consequential damages, even if
25 * Sun has been advised of the possibility of such damages.
27 * Sun Microsystems, Inc.
29 * Mountain View, California 94043
32 * Copyright (c) 1986-1991 by Sun Microsystems Inc.
35 /* #ident "@(#)clnt_simple.c 1.17 94/04/24 SMI" */
37 #include <sys/cdefs.h>
38 #if defined(LIBC_SCCS) && !defined(lint)
40 static char sccsid
[] = "@(#)clnt_simple.c 1.49 89/01/31 Copyr 1984 Sun Micro";
42 __RCSID("$NetBSD: clnt_simple.c,v 1.30 2010/12/08 02:06:38 joerg Exp $");
48 * Simplified front end to client rpc.
52 #include "namespace.h"
53 #include "reentrant.h"
54 #include <sys/param.h>
65 __weak_alias(rpc_call
,_rpc_call
)
68 #ifndef MAXHOSTNAMELEN
69 #define MAXHOSTNAMELEN 64
76 struct rpc_call_private
{
77 int valid
; /* Is this entry valid ? */
78 CLIENT
*client
; /* Client handle */
79 pid_t pid
; /* process-id at moment of creation */
80 rpcprog_t prognum
; /* Program */
81 rpcvers_t versnum
; /* Version */
82 char host
[MAXHOSTNAMELEN
]; /* Servers host */
83 char nettype
[NETIDLEN
]; /* Network type */
85 static struct rpc_call_private
*rpc_call_private_main
;
88 static void rpc_call_destroy
__P((void *));
91 rpc_call_destroy(void *vp
)
93 struct rpc_call_private
*rcp
= (struct rpc_call_private
*)vp
;
97 CLNT_DESTROY(rcp
->client
);
101 static thread_key_t rpc_call_key
;
102 static once_t rpc_call_once
= ONCE_INITIALIZER
;
108 thr_keycreate(&rpc_call_key
, rpc_call_destroy
);
114 * This is the simplified interface to the client rpc layer.
115 * The client handle is not destroyed here and is reused for
116 * the future calls to same prog, vers, host and nettype combination.
118 * The total time available is 25 seconds.
121 rpc_call(host
, prognum
, versnum
, procnum
, inproc
, in
, outproc
, out
, nettype
)
122 const char *host
; /* host name */
123 rpcprog_t prognum
; /* program number */
124 rpcvers_t versnum
; /* version number */
125 rpcproc_t procnum
; /* procedure number */
126 xdrproc_t inproc
, outproc
; /* in/out XDR procedures */
128 char *out
; /* recv/send data */
129 const char *nettype
; /* nettype */
131 struct rpc_call_private
*rcp
= (struct rpc_call_private
*) 0;
132 enum clnt_stat clnt_stat
;
133 struct timeval timeout
, tottimeout
;
135 _DIAGASSERT(host
!= NULL
);
136 /* XXX: in may be NULL ??? */
137 /* XXX: out may be NULL ??? */
138 /* XXX: nettype may be NULL ??? */
141 if (__isthreaded
== 0) {
142 rcp
= rpc_call_private_main
;
144 thr_once(&rpc_call_once
, rpc_call_setup
);
145 rcp
= thr_getspecific(rpc_call_key
);
148 rcp
= rpc_call_private_main
;
151 rcp
= malloc(sizeof (*rcp
));
153 rpc_createerr
.cf_stat
= RPC_SYSTEMERROR
;
154 rpc_createerr
.cf_error
.re_errno
= errno
;
155 return (rpc_createerr
.cf_stat
);
157 if (__isthreaded
== 0)
158 rpc_call_private_main
= rcp
;
160 thr_setspecific(rpc_call_key
, (void *) rcp
);
164 if ((nettype
== NULL
) || (nettype
[0] == 0))
166 if (!(rcp
->valid
&& rcp
->pid
== getpid() &&
167 (rcp
->prognum
== prognum
) &&
168 (rcp
->versnum
== versnum
) &&
169 (!strcmp(rcp
->host
, host
)) &&
170 (!strcmp(rcp
->nettype
, nettype
)))) {
175 CLNT_DESTROY(rcp
->client
);
177 * Using the first successful transport for that type
179 rcp
->client
= clnt_create(host
, prognum
, versnum
, nettype
);
181 if (rcp
->client
== NULL
) {
182 return (rpc_createerr
.cf_stat
);
185 * Set time outs for connectionless case. Do it
186 * unconditionally. Faster than doing a t_getinfo()
187 * and then doing the right thing.
191 (void) CLNT_CONTROL(rcp
->client
,
192 CLSET_RETRY_TIMEOUT
, (char *)(void *)&timeout
);
193 if (CLNT_CONTROL(rcp
->client
, CLGET_FD
, (char *)(void *)&fd
))
194 (void)fcntl(fd
, F_SETFD
, FD_CLOEXEC
);
195 rcp
->prognum
= prognum
;
196 rcp
->versnum
= versnum
;
197 if ((strlen(host
) < (size_t)MAXHOSTNAMELEN
) &&
198 (strlen(nettype
) < (size_t)NETIDLEN
)) {
199 (void) strcpy(rcp
->host
, host
);
200 (void) strcpy(rcp
->nettype
, nettype
);
205 } /* else reuse old client */
206 tottimeout
.tv_sec
= 25;
207 tottimeout
.tv_usec
= 0;
208 clnt_stat
= CLNT_CALL(rcp
->client
, procnum
, inproc
, in
,
209 outproc
, out
, tottimeout
);
211 * if call failed, empty cache
213 if (clnt_stat
!= RPC_SUCCESS
)