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