174462Salfred/* $NetBSD: clnt_simple.c,v 1.21 2000/07/06 03:10:34 christos Exp $ */ 274462Salfred 31901Swollman/* 41901Swollman * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 51901Swollman * unrestricted use provided that this legend is included on all tape 61901Swollman * media and as a part of the software program in whole or part. Users 71901Swollman * may copy or modify Sun RPC without charge, but are not authorized 81901Swollman * to license or distribute it to anyone else except as part of a product or 91901Swollman * program developed by the user. 108870Srgrimes * 111901Swollman * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 121901Swollman * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 131901Swollman * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 148870Srgrimes * 151901Swollman * Sun RPC is provided with no support and without any obligation on the 161901Swollman * part of Sun Microsystems, Inc. to assist in its use, correction, 171901Swollman * modification or enhancement. 188870Srgrimes * 191901Swollman * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 201901Swollman * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 211901Swollman * OR ANY PART THEREOF. 228870Srgrimes * 231901Swollman * In no event will Sun Microsystems, Inc. be liable for any lost revenue 241901Swollman * or profits or other special, indirect and consequential damages, even if 251901Swollman * Sun has been advised of the possibility of such damages. 268870Srgrimes * 271901Swollman * Sun Microsystems, Inc. 281901Swollman * 2550 Garcia Avenue 291901Swollman * Mountain View, California 94043 301901Swollman */ 3174462Salfred/* 3274462Salfred * Copyright (c) 1986-1991 by Sun Microsystems Inc. 3374462Salfred */ 341901Swollman 351901Swollman#if defined(LIBC_SCCS) && !defined(lint) 36136581Sobrienstatic char *sccsid2 = "from: @(#)clnt_simple.c 1.35 87/08/11 Copyr 1984 Sun Micro"; 3792990Sobrienstatic char *sccsid = "from: @(#)clnt_simple.c 2.2 88/08/01 4.0 RPCSRC"; 381901Swollman#endif 3992990Sobrien#include <sys/cdefs.h> 4092990Sobrien__FBSDID("$FreeBSD$"); 411901Swollman 428870Srgrimes/* 431901Swollman * clnt_simple.c 4474462Salfred * Simplified front end to client rpc. 451901Swollman * 461901Swollman */ 471901Swollman 4875094Siedowse#include "namespace.h" 4974462Salfred#include "reentrant.h" 5021070Speter#include <sys/param.h> 511901Swollman#include <stdio.h> 5274462Salfred#include <errno.h> 5374462Salfred#include <rpc/rpc.h> 5474462Salfred#include <string.h> 551901Swollman#include <stdlib.h> 5674462Salfred#include <fcntl.h> 5711666Sphk#include <unistd.h> 5871579Sdeischen#include "un-namespace.h" 59156090Sdeischen#include "mt_misc.h" 601901Swollman 6174462Salfred#ifndef MAXHOSTNAMELEN 6274462Salfred#define MAXHOSTNAMELEN 64 6374462Salfred#endif 641901Swollman 6574462Salfred#ifndef NETIDLEN 6674462Salfred#define NETIDLEN 32 6774462Salfred#endif 6874462Salfred 6974462Salfredstruct rpc_call_private { 7074462Salfred int valid; /* Is this entry valid ? */ 7174462Salfred CLIENT *client; /* Client handle */ 7274462Salfred pid_t pid; /* process-id at moment of creation */ 7374462Salfred rpcprog_t prognum; /* Program */ 7474462Salfred rpcvers_t versnum; /* Version */ 7574462Salfred char host[MAXHOSTNAMELEN]; /* Servers host */ 7674462Salfred char nettype[NETIDLEN]; /* Network type */ 7774462Salfred}; 7874462Salfredstatic struct rpc_call_private *rpc_call_private_main; 79204950Sjhbstatic thread_key_t rpc_call_key; 80204950Sjhbstatic once_t rpc_call_once = ONCE_INITIALIZER; 81204950Sjhbstatic int rpc_call_key_error; 8274462Salfred 83204950Sjhbstatic void rpc_call_key_init(void); 8492905Sobrienstatic void rpc_call_destroy(void *); 8574462Salfred 8674462Salfredstatic void 8774462Salfredrpc_call_destroy(void *vp) 881901Swollman{ 8974462Salfred struct rpc_call_private *rcp = (struct rpc_call_private *)vp; 9074462Salfred 9174462Salfred if (rcp) { 9274462Salfred if (rcp->client) 9374462Salfred CLNT_DESTROY(rcp->client); 9474462Salfred free(rcp); 9574462Salfred } 9674462Salfred} 9774462Salfred 98204950Sjhbstatic void 99204950Sjhbrpc_call_key_init(void) 100204950Sjhb{ 101204950Sjhb 102204950Sjhb rpc_call_key_error = thr_keycreate(&rpc_call_key, rpc_call_destroy); 103204950Sjhb} 104204950Sjhb 10574462Salfred/* 10674462Salfred * This is the simplified interface to the client rpc layer. 10774462Salfred * The client handle is not destroyed here and is reused for 10874462Salfred * the future calls to same prog, vers, host and nettype combination. 10974462Salfred * 11074462Salfred * The total time available is 25 seconds. 11174462Salfred */ 11274462Salfredenum clnt_stat 11374462Salfredrpc_call(host, prognum, versnum, procnum, inproc, in, outproc, out, nettype) 11474462Salfred const char *host; /* host name */ 11574462Salfred rpcprog_t prognum; /* program number */ 11674462Salfred rpcvers_t versnum; /* version number */ 11774462Salfred rpcproc_t procnum; /* procedure number */ 11874462Salfred xdrproc_t inproc, outproc; /* in/out XDR procedures */ 11974462Salfred const char *in; 12074462Salfred char *out; /* recv/send data */ 12174462Salfred const char *nettype; /* nettype */ 12274462Salfred{ 12374462Salfred struct rpc_call_private *rcp = (struct rpc_call_private *) 0; 1241901Swollman enum clnt_stat clnt_stat; 1251901Swollman struct timeval timeout, tottimeout; 12674462Salfred int main_thread = 1; 1271901Swollman 12874462Salfred if ((main_thread = thr_main())) { 12974462Salfred rcp = rpc_call_private_main; 13074462Salfred } else { 131204950Sjhb if (thr_once(&rpc_call_once, rpc_call_key_init) != 0 || 132204950Sjhb rpc_call_key_error != 0) { 133204950Sjhb rpc_createerr.cf_stat = RPC_SYSTEMERROR; 134204950Sjhb rpc_createerr.cf_error.re_errno = rpc_call_key_error; 135204950Sjhb return (rpc_createerr.cf_stat); 13674462Salfred } 13774462Salfred rcp = (struct rpc_call_private *)thr_getspecific(rpc_call_key); 1381901Swollman } 13974462Salfred if (rcp == NULL) { 14074462Salfred rcp = malloc(sizeof (*rcp)); 14174462Salfred if (rcp == NULL) { 14274462Salfred rpc_createerr.cf_stat = RPC_SYSTEMERROR; 14374462Salfred rpc_createerr.cf_error.re_errno = errno; 14474462Salfred return (rpc_createerr.cf_stat); 14574462Salfred } 14674462Salfred if (main_thread) 14774462Salfred rpc_call_private_main = rcp; 14874462Salfred else 14974462Salfred thr_setspecific(rpc_call_key, (void *) rcp); 15074462Salfred rcp->valid = 0; 15174462Salfred rcp->client = NULL; 1521901Swollman } 153121651Smbr if ((nettype == NULL) || (nettype[0] == 0)) 15474462Salfred nettype = "netpath"; 15574462Salfred if (!(rcp->valid && rcp->pid == getpid() && 15674462Salfred (rcp->prognum == prognum) && 15774462Salfred (rcp->versnum == versnum) && 15874462Salfred (!strcmp(rcp->host, host)) && 15974462Salfred (!strcmp(rcp->nettype, nettype)))) { 16074462Salfred int fd; 16174462Salfred 16274462Salfred rcp->valid = 0; 16374462Salfred if (rcp->client) 16474462Salfred CLNT_DESTROY(rcp->client); 16574462Salfred /* 16674462Salfred * Using the first successful transport for that type 16774462Salfred */ 16874462Salfred rcp->client = clnt_create(host, prognum, versnum, nettype); 16974462Salfred rcp->pid = getpid(); 17074462Salfred if (rcp->client == NULL) { 17174462Salfred return (rpc_createerr.cf_stat); 1721901Swollman } 17374462Salfred /* 17474462Salfred * Set time outs for connectionless case. Do it 17574462Salfred * unconditionally. Faster than doing a t_getinfo() 17674462Salfred * and then doing the right thing. 17774462Salfred */ 1781901Swollman timeout.tv_usec = 0; 1791901Swollman timeout.tv_sec = 5; 18074462Salfred (void) CLNT_CONTROL(rcp->client, 18174462Salfred CLSET_RETRY_TIMEOUT, (char *)(void *)&timeout); 18274462Salfred if (CLNT_CONTROL(rcp->client, CLGET_FD, (char *)(void *)&fd)) 18374462Salfred _fcntl(fd, F_SETFD, 1); /* make it "close on exec" */ 18474462Salfred rcp->prognum = prognum; 18574462Salfred rcp->versnum = versnum; 18674462Salfred if ((strlen(host) < (size_t)MAXHOSTNAMELEN) && 18774462Salfred (strlen(nettype) < (size_t)NETIDLEN)) { 18874462Salfred (void) strcpy(rcp->host, host); 18974462Salfred (void) strcpy(rcp->nettype, nettype); 19074462Salfred rcp->valid = 1; 19174462Salfred } else { 19274462Salfred rcp->valid = 0; 19374462Salfred } 19474462Salfred } /* else reuse old client */ 1951901Swollman tottimeout.tv_sec = 25; 1961901Swollman tottimeout.tv_usec = 0; 19774462Salfred /*LINTED const castaway*/ 19874462Salfred clnt_stat = CLNT_CALL(rcp->client, procnum, inproc, (char *) in, 1991901Swollman outproc, out, tottimeout); 2008870Srgrimes /* 2011901Swollman * if call failed, empty cache 2021901Swollman */ 2031901Swollman if (clnt_stat != RPC_SUCCESS) 20474462Salfred rcp->valid = 0; 20574462Salfred return (clnt_stat); 2061901Swollman} 207