clnt_simple.c revision 75094
1314125Sdelphij/*	$NetBSD: clnt_simple.c,v 1.21 2000/07/06 03:10:34 christos Exp $	*/
2110010Smarkm
3110010Smarkm/*
4142429Snectar * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
5110010Smarkm * unrestricted use provided that this legend is included on all tape
6110010Smarkm * media and as a part of the software program in whole or part.  Users
7110010Smarkm * may copy or modify Sun RPC without charge, but are not authorized
8110010Smarkm * to license or distribute it to anyone else except as part of a product or
9110010Smarkm * program developed by the user.
10110010Smarkm *
11110010Smarkm * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
12110010Smarkm * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
13110010Smarkm * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
14110010Smarkm *
15110010Smarkm * Sun RPC is provided with no support and without any obligation on the
16110010Smarkm * part of Sun Microsystems, Inc. to assist in its use, correction,
17110010Smarkm * modification or enhancement.
18110010Smarkm *
19110010Smarkm * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
20215698Ssimon * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
21215698Ssimon * OR ANY PART THEREOF.
22215698Ssimon *
23215698Ssimon * In no event will Sun Microsystems, Inc. be liable for any lost revenue
24215698Ssimon * or profits or other special, indirect and consequential damages, even if
25110010Smarkm * Sun has been advised of the possibility of such damages.
26110010Smarkm *
27110010Smarkm * Sun Microsystems, Inc.
28110010Smarkm * 2550 Garcia Avenue
29110010Smarkm * Mountain View, California  94043
30110010Smarkm */
31110010Smarkm/*
32110010Smarkm * Copyright (c) 1986-1991 by Sun Microsystems Inc.
33110010Smarkm */
34110010Smarkm
35110010Smarkm#if defined(LIBC_SCCS) && !defined(lint)
36110010Smarkm/*static char *sccsid = "from: @(#)clnt_simple.c 1.35 87/08/11 Copyr 1984 Sun Micro";*/
37110010Smarkm/*static char *sccsid = "from: @(#)clnt_simple.c	2.2 88/08/01 4.0 RPCSRC";*/
38110010Smarkmstatic char *rcsid = "$FreeBSD: head/lib/libc/rpc/clnt_simple.c 75094 2001-04-02 21:41:44Z iedowse $";
39110010Smarkm#endif
40110010Smarkm
41276861Sjkim/*
42276861Sjkim * clnt_simple.c
43110010Smarkm * Simplified front end to client rpc.
44110010Smarkm *
45215698Ssimon */
46215698Ssimon
47215698Ssimon#include "namespace.h"
48215698Ssimon#include "reentrant.h"
49314125Sdelphij#include <sys/param.h>
50215698Ssimon#include <stdio.h>
51142429Snectar#include <errno.h>
52142429Snectar#include <rpc/rpc.h>
53276861Sjkim#include <string.h>
54276861Sjkim#include <stdlib.h>
55276861Sjkim#include <fcntl.h>
56110010Smarkm#include <unistd.h>
57314125Sdelphij#include "un-namespace.h"
58314125Sdelphij
59314125Sdelphij#ifndef MAXHOSTNAMELEN
60314125Sdelphij#define	MAXHOSTNAMELEN 64
61215698Ssimon#endif
62314125Sdelphij
63314125Sdelphij#ifndef NETIDLEN
64314125Sdelphij#define	NETIDLEN 32
65276861Sjkim#endif
66215698Ssimon
67110010Smarkmstruct rpc_call_private {
68110010Smarkm	int	valid;			/* Is this entry valid ? */
69110010Smarkm	CLIENT	*client;		/* Client handle */
70110010Smarkm	pid_t	pid;			/* process-id at moment of creation */
71110010Smarkm	rpcprog_t prognum;		/* Program */
72110010Smarkm	rpcvers_t versnum;		/* Version */
73110010Smarkm	char	host[MAXHOSTNAMELEN];	/* Servers host */
74110010Smarkm	char	nettype[NETIDLEN];	/* Network type */
75110010Smarkm};
76110010Smarkmstatic struct rpc_call_private *rpc_call_private_main;
77110010Smarkm
78110010Smarkmstatic void rpc_call_destroy __P((void *));
79110010Smarkm
80110010Smarkmstatic void
81110010Smarkmrpc_call_destroy(void *vp)
82110010Smarkm{
83110010Smarkm	struct rpc_call_private *rcp = (struct rpc_call_private *)vp;
84110010Smarkm
85110010Smarkm	if (rcp) {
86110010Smarkm		if (rcp->client)
87110010Smarkm			CLNT_DESTROY(rcp->client);
88110010Smarkm		free(rcp);
89110010Smarkm	}
90110010Smarkm}
91110010Smarkm
92110010Smarkm/*
93110010Smarkm * This is the simplified interface to the client rpc layer.
94110010Smarkm * The client handle is not destroyed here and is reused for
95110010Smarkm * the future calls to same prog, vers, host and nettype combination.
96110010Smarkm *
97110010Smarkm * The total time available is 25 seconds.
98110010Smarkm */
99110010Smarkmenum clnt_stat
100110010Smarkmrpc_call(host, prognum, versnum, procnum, inproc, in, outproc, out, nettype)
101110010Smarkm	const char *host;			/* host name */
102110010Smarkm	rpcprog_t prognum;			/* program number */
103110010Smarkm	rpcvers_t versnum;			/* version number */
104110010Smarkm	rpcproc_t procnum;			/* procedure number */
105110010Smarkm	xdrproc_t inproc, outproc;	/* in/out XDR procedures */
106110010Smarkm	const char *in;
107110010Smarkm	char  *out;			/* recv/send data */
108110010Smarkm	const char *nettype;			/* nettype */
109110010Smarkm{
110110010Smarkm	struct rpc_call_private *rcp = (struct rpc_call_private *) 0;
111110010Smarkm	enum clnt_stat clnt_stat;
112110010Smarkm	struct timeval timeout, tottimeout;
113110010Smarkm	static thread_key_t rpc_call_key;
114110010Smarkm	extern mutex_t tsd_lock;
115110010Smarkm	int main_thread = 1;
116110010Smarkm
117110010Smarkm	if ((main_thread = thr_main())) {
118110010Smarkm		rcp = rpc_call_private_main;
119110010Smarkm	} else {
120110010Smarkm		if (rpc_call_key == 0) {
121110010Smarkm			mutex_lock(&tsd_lock);
122110010Smarkm			if (rpc_call_key == 0)
123110010Smarkm				thr_keycreate(&rpc_call_key, rpc_call_destroy);
124110010Smarkm			mutex_unlock(&tsd_lock);
125110010Smarkm		}
126110010Smarkm		rcp = (struct rpc_call_private *)thr_getspecific(rpc_call_key);
127110010Smarkm	}
128110010Smarkm	if (rcp == NULL) {
129142429Snectar		rcp = malloc(sizeof (*rcp));
130110010Smarkm		if (rcp == NULL) {
131110010Smarkm			rpc_createerr.cf_stat = RPC_SYSTEMERROR;
132314125Sdelphij			rpc_createerr.cf_error.re_errno = errno;
133215698Ssimon			return (rpc_createerr.cf_stat);
134215698Ssimon		}
135215698Ssimon		if (main_thread)
136215698Ssimon			rpc_call_private_main = rcp;
137110010Smarkm		else
138110010Smarkm			thr_setspecific(rpc_call_key, (void *) rcp);
139110010Smarkm		rcp->valid = 0;
140110010Smarkm		rcp->client = NULL;
141110010Smarkm	}
142110010Smarkm	if ((nettype == NULL) || (nettype[0] == NULL))
143110010Smarkm		nettype = "netpath";
144110010Smarkm	if (!(rcp->valid && rcp->pid == getpid() &&
145215698Ssimon		(rcp->prognum == prognum) &&
146110010Smarkm		(rcp->versnum == versnum) &&
147110010Smarkm		(!strcmp(rcp->host, host)) &&
148215698Ssimon		(!strcmp(rcp->nettype, nettype)))) {
149110010Smarkm		int fd;
150110010Smarkm
151110010Smarkm		rcp->valid = 0;
152215698Ssimon		if (rcp->client)
153110010Smarkm			CLNT_DESTROY(rcp->client);
154110010Smarkm		/*
155110010Smarkm		 * Using the first successful transport for that type
156215698Ssimon		 */
157110010Smarkm		rcp->client = clnt_create(host, prognum, versnum, nettype);
158110010Smarkm		rcp->pid = getpid();
159110010Smarkm		if (rcp->client == NULL) {
160215698Ssimon			return (rpc_createerr.cf_stat);
161110010Smarkm		}
162110010Smarkm		/*
163110010Smarkm		 * Set time outs for connectionless case.  Do it
164110010Smarkm		 * unconditionally.  Faster than doing a t_getinfo()
165110010Smarkm		 * and then doing the right thing.
166110010Smarkm		 */
167110010Smarkm		timeout.tv_usec = 0;
168110010Smarkm		timeout.tv_sec = 5;
169110010Smarkm		(void) CLNT_CONTROL(rcp->client,
170110010Smarkm				CLSET_RETRY_TIMEOUT, (char *)(void *)&timeout);
171142429Snectar		if (CLNT_CONTROL(rcp->client, CLGET_FD, (char *)(void *)&fd))
172110010Smarkm			_fcntl(fd, F_SETFD, 1);	/* make it "close on exec" */
173110010Smarkm		rcp->prognum = prognum;
174142429Snectar		rcp->versnum = versnum;
175110010Smarkm		if ((strlen(host) < (size_t)MAXHOSTNAMELEN) &&
176215698Ssimon		    (strlen(nettype) < (size_t)NETIDLEN)) {
177110010Smarkm			(void) strcpy(rcp->host, host);
178110010Smarkm			(void) strcpy(rcp->nettype, nettype);
179110010Smarkm			rcp->valid = 1;
180110010Smarkm		} else {
181110010Smarkm			rcp->valid = 0;
182142429Snectar		}
183110010Smarkm	} /* else reuse old client */
184110010Smarkm	tottimeout.tv_sec = 25;
185142429Snectar	tottimeout.tv_usec = 0;
186	/*LINTED const castaway*/
187	clnt_stat = CLNT_CALL(rcp->client, procnum, inproc, (char *) in,
188	    outproc, out, tottimeout);
189	/*
190	 * if call failed, empty cache
191	 */
192	if (clnt_stat != RPC_SUCCESS)
193		rcp->valid = 0;
194	return (clnt_stat);
195}
196