Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/lib/libc/rpc/clnt_simple.c
39530 views
1
/* $NetBSD: clnt_simple.c,v 1.21 2000/07/06 03:10:34 christos Exp $ */
2
3
/*-
4
* SPDX-License-Identifier: BSD-3-Clause
5
*
6
* Copyright (c) 2009, Sun Microsystems, Inc.
7
* All rights reserved.
8
*
9
* Redistribution and use in source and binary forms, with or without
10
* modification, are permitted provided that the following conditions are met:
11
* - Redistributions of source code must retain the above copyright notice,
12
* this list of conditions and the following disclaimer.
13
* - Redistributions in binary form must reproduce the above copyright notice,
14
* this list of conditions and the following disclaimer in the documentation
15
* and/or other materials provided with the distribution.
16
* - Neither the name of Sun Microsystems, Inc. nor the names of its
17
* contributors may be used to endorse or promote products derived
18
* from this software without specific prior written permission.
19
*
20
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
* POSSIBILITY OF SUCH DAMAGE.
31
*/
32
/*
33
* Copyright (c) 1986-1991 by Sun Microsystems Inc.
34
*/
35
36
/*
37
* clnt_simple.c
38
* Simplified front end to client rpc.
39
*
40
*/
41
42
#include "namespace.h"
43
#include "reentrant.h"
44
#include <sys/param.h>
45
#include <stdio.h>
46
#include <errno.h>
47
#include <rpc/rpc.h>
48
#include <string.h>
49
#include <stdlib.h>
50
#include <fcntl.h>
51
#include <unistd.h>
52
#include "un-namespace.h"
53
#include "mt_misc.h"
54
55
#ifndef MAXHOSTNAMELEN
56
#define MAXHOSTNAMELEN 64
57
#endif
58
59
#ifndef NETIDLEN
60
#define NETIDLEN 32
61
#endif
62
63
struct rpc_call_private {
64
int valid; /* Is this entry valid ? */
65
CLIENT *client; /* Client handle */
66
pid_t pid; /* process-id at moment of creation */
67
rpcprog_t prognum; /* Program */
68
rpcvers_t versnum; /* Version */
69
char host[MAXHOSTNAMELEN]; /* Servers host */
70
char nettype[NETIDLEN]; /* Network type */
71
};
72
static struct rpc_call_private *rpc_call_private_main;
73
static thread_key_t rpc_call_key;
74
static once_t rpc_call_once = ONCE_INITIALIZER;
75
static int rpc_call_key_error;
76
77
static void rpc_call_key_init(void);
78
static void rpc_call_destroy(void *);
79
80
static void
81
rpc_call_destroy(void *vp)
82
{
83
struct rpc_call_private *rcp = (struct rpc_call_private *)vp;
84
85
if (rcp) {
86
if (rcp->client)
87
CLNT_DESTROY(rcp->client);
88
free(rcp);
89
}
90
}
91
92
static void
93
rpc_call_key_init(void)
94
{
95
96
rpc_call_key_error = thr_keycreate(&rpc_call_key, rpc_call_destroy);
97
}
98
99
/*
100
* This is the simplified interface to the client rpc layer.
101
* The client handle is not destroyed here and is reused for
102
* the future calls to same prog, vers, host and nettype combination.
103
*
104
* The total time available is 25 seconds.
105
*
106
* host - host name
107
* prognum - program number
108
* versnum - version number
109
* procnum - procedure number
110
* inproc, outproc - in/out XDR procedures
111
* in, out - recv/send data
112
* nettype - nettype
113
*/
114
enum clnt_stat
115
rpc_call(const char *host, const rpcprog_t prognum, const rpcvers_t versnum,
116
const rpcproc_t procnum, const xdrproc_t inproc, const char *in,
117
const xdrproc_t outproc, char *out, const char *nettype)
118
{
119
struct rpc_call_private *rcp = (struct rpc_call_private *) 0;
120
enum clnt_stat clnt_stat;
121
struct timeval timeout, tottimeout;
122
int main_thread = 1;
123
124
if ((main_thread = thr_main())) {
125
rcp = rpc_call_private_main;
126
} else {
127
if (thr_once(&rpc_call_once, rpc_call_key_init) != 0 ||
128
rpc_call_key_error != 0) {
129
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
130
rpc_createerr.cf_error.re_errno = rpc_call_key_error;
131
return (rpc_createerr.cf_stat);
132
}
133
rcp = (struct rpc_call_private *)thr_getspecific(rpc_call_key);
134
}
135
if (rcp == NULL) {
136
rcp = malloc(sizeof (*rcp));
137
if (rcp == NULL) {
138
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
139
rpc_createerr.cf_error.re_errno = errno;
140
return (rpc_createerr.cf_stat);
141
}
142
if (main_thread)
143
rpc_call_private_main = rcp;
144
else
145
thr_setspecific(rpc_call_key, (void *) rcp);
146
rcp->valid = 0;
147
rcp->client = NULL;
148
}
149
if ((nettype == NULL) || (nettype[0] == 0))
150
nettype = "netpath";
151
if (!(rcp->valid && rcp->pid == getpid() &&
152
(rcp->prognum == prognum) &&
153
(rcp->versnum == versnum) &&
154
(!strcmp(rcp->host, host)) &&
155
(!strcmp(rcp->nettype, nettype)))) {
156
int fd;
157
158
rcp->valid = 0;
159
if (rcp->client)
160
CLNT_DESTROY(rcp->client);
161
/*
162
* Using the first successful transport for that type
163
*/
164
rcp->client = clnt_create(host, prognum, versnum, nettype);
165
rcp->pid = getpid();
166
if (rcp->client == NULL) {
167
return (rpc_createerr.cf_stat);
168
}
169
/*
170
* Set time outs for connectionless case. Do it
171
* unconditionally. Faster than doing a t_getinfo()
172
* and then doing the right thing.
173
*/
174
timeout.tv_usec = 0;
175
timeout.tv_sec = 5;
176
(void) CLNT_CONTROL(rcp->client,
177
CLSET_RETRY_TIMEOUT, (char *)(void *)&timeout);
178
if (CLNT_CONTROL(rcp->client, CLGET_FD, (char *)(void *)&fd))
179
_fcntl(fd, F_SETFD, 1); /* make it "close on exec" */
180
rcp->prognum = prognum;
181
rcp->versnum = versnum;
182
if ((strlen(host) < (size_t)MAXHOSTNAMELEN) &&
183
(strlen(nettype) < (size_t)NETIDLEN)) {
184
(void) strcpy(rcp->host, host);
185
(void) strcpy(rcp->nettype, nettype);
186
rcp->valid = 1;
187
} else {
188
rcp->valid = 0;
189
}
190
} /* else reuse old client */
191
tottimeout.tv_sec = 25;
192
tottimeout.tv_usec = 0;
193
/*LINTED const castaway*/
194
clnt_stat = CLNT_CALL(rcp->client, procnum, inproc, (char *) in,
195
outproc, out, tottimeout);
196
/*
197
* if call failed, empty cache
198
*/
199
if (clnt_stat != RPC_SUCCESS)
200
rcp->valid = 0;
201
return (clnt_stat);
202
}
203
204