1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00
cde/cde/lib/csa/connection.c
Peter Howkins 6f2a704bbd libcsa: Resolve 96 -Wunused-variable warnings.
This is not all of them, another ~90 exist in generated code.
2012-11-06 15:07:08 +00:00

927 lines
22 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these librararies and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/* $TOG: connection.c /main/4 1999/10/14 17:47:12 mgreess $ */
/*
* (c) Copyright 1993, 1994 Hewlett-Packard Company
* (c) Copyright 1993, 1994 International Business Machines Corp.
* (c) Copyright 1993, 1994 Novell, Inc.
* (c) Copyright 1993, 1994 Sun Microsystems, Inc.
*/
/*
* This file manages server connections.
*/
#include <EUSCompat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#ifdef HPUX
#include <sys/resource.h>
#endif
#include "connection.h"
#include "rtable2.h"
#include "rtable3.h"
#include "rtable4.h"
#include "cm.h"
#include "debug.h"
#include "agent.h"
#include "convert2-4.h"
#include "convert3-4.h"
#include "rpccalls.h"
#ifdef HPUX
#define MAX_COUNT 10
#else
#define MAX_COUNT 40
#endif
static struct timeval timeout_tv;
static struct timeval retry_tv;
static AUTH *unix_credential = NULL;
static tcp_count = 0;
static cl_count = 0;
static _DtCm_Client_Info *client_cache_head = NULL;
static _DtCm_Client_Info *client_cache_tail = NULL;
/*****************************************************************************
* forward declaration of static functions.
*****************************************************************************/
static void create_auth(CLIENT *cl);
static void destroy_auth(CLIENT *cl);
static _DtCm_Client_Info * get_client_info(char *host, int version);
static void destroy_target_list(_DtCm_Target_List *tlist);
static void destroy_client_info(_DtCm_Client_Info *ci);
static void insert_client_info(_DtCm_Client_Info *ci);
static void delete_client_info(_DtCm_Client_Info *oldci);
static void cleanup_some_connection(_DtCm_Client_Info *dontclose);
static void check_registration(_DtCm_Connection *conn);
static _DtCm_Client_Info * get_new_client_handle(_DtCm_Connection *conn);
#ifdef __osf__
static CSA_return_code get_client_handle(const char *host, const u_int prognum,
u_long *vers_outp, const u_long vers_low,
const u_long vers_high, char *nettype,
CLIENT **clnt);
#else
static CSA_return_code get_client_handle(const char *host, const u_long prognum,
u_long *vers_outp, const u_long vers_low,
const u_long vers_high, char *nettype,
CLIENT **clnt);
#endif
static CSA_return_code regstat4_to_dtcmstatus(Registration_Status_4 stat4);
extern CSA_return_code
_DtCm_create_udp_client(
char *host,
int version,
int timeout,
_DtCm_Client_Info **clnt)
{
CSA_return_code stat;
_DtCm_Client_Info *ci;
u_long vers_out;
CLIENT *cl=NULL;
if (host == NULL || clnt == NULL)
return (CSA_E_INVALID_PARAMETER);
/* if client info is found, we have at least the udp handle */
if (((*clnt) = get_client_info(host, version)) != NULL) {
return (CSA_SUCCESS);
}
#if defined(SunOS) || defined(USL) || defined(__uxp__)
cl = clnt_create_vers(host, TABLEPROG,
&vers_out, TABLEVERS_2, version, "udp");
if (cl==NULL) {
_DtCm_print_errmsg(clnt_spcreateerror(host));
return (_DtCm_clntstat_to_csastat(rpc_createerr.cf_stat));
}
#else
stat = get_client_handle(host, (u_int)TABLEPROG, &vers_out, TABLEVERS_2,
version, "udp", &cl);
if (stat != CSA_SUCCESS)
return (stat);
#endif
/* if version is lower than requested, check the list again */
if (vers_out < version) {
if ((ci = get_client_info(host, vers_out)) != NULL) {
clnt_destroy(cl);
*clnt = ci;
return (CSA_SUCCESS);
}
}
create_auth(cl);
/* Adjust Timeout */
if (timeout==0) timeout = _DtCM_DEFAULT_TIMEOUT;
timeout_tv.tv_sec = timeout;
timeout_tv.tv_usec = 0;
clnt_control(cl, CLSET_TIMEOUT, (char*)&timeout_tv);
/* UDP only!
time rpc waits for server to reply before retransmission =
'timeout'. since the retry timeout is set to timeout + 10;
this guarantees there won't
be any retransmisssions resulting in duplicate
transactions in the database.
*/
retry_tv.tv_sec = timeout + 10;
retry_tv.tv_usec = 0;
clnt_control(cl, CLSET_RETRY_TIMEOUT, (char*)&retry_tv);
if ((ci = (_DtCm_Client_Info *)calloc(1, sizeof(_DtCm_Client_Info))) == NULL) {
destroy_auth(cl);
clnt_destroy(cl);
return (CSA_E_INSUFFICIENT_MEMORY);
}
if ((ci->host = strdup(host)) == NULL) {
destroy_auth(cl);
clnt_destroy(cl);
free(ci);
return (CSA_E_INSUFFICIENT_MEMORY);
}
ci->udpcl = cl;
ci->vers_out = vers_out;
insert_client_info(ci);
*clnt = ci;
return (CSA_SUCCESS);
}
/*
* Creates tcp client handle. Used for calls that potentially return
* large amount of data. If it fails to create a tcp client handle,
* a udp client handle will be returned.
*/
extern CSA_return_code
_DtCm_create_tcp_client(
char *host,
int version,
int timeout,
_DtCm_Client_Info **clnt)
{
CSA_return_code stat;
_DtCm_Client_Info *ci;
u_long vers_out;
CLIENT *cl=NULL;
if (host == NULL || clnt == NULL)
return (CSA_E_INVALID_PARAMETER);
/* Get a udp client handle. This serves two purposes: */
/* - to get a udp handle for an old server which talks only udp */
/* - to invoke a server through inetd since only udp is registered.*/
if ((stat = _DtCm_create_udp_client(host, version, timeout, &ci))
!= CSA_SUCCESS) {
return (stat);
} else if (ci->tcpcl) {
*clnt = ci;
return (CSA_SUCCESS);
} else {
/* create tcp connection */
#if defined(SunOS) || defined(USL) || defined(__uxp__)
cl = clnt_create_vers(host, TABLEPROG, &vers_out,
TABLEVERS_2, version, "tcp");
#else
stat = get_client_handle(host, (u_int)TABLEPROG, &vers_out,
TABLEVERS_2, version, "tcp", &cl);
#endif
/* if can't create tcp connection, use udp */
if (cl==NULL) {
_DtCm_print_errmsg(clnt_spcreateerror(host));
*clnt = ci;
return (CSA_SUCCESS);
}
create_auth(cl);
/* Adjust Timeout */
if (timeout==0) timeout = _DtCM_DEFAULT_TIMEOUT;
timeout_tv.tv_sec = timeout;
timeout_tv.tv_usec = 0;
clnt_control(cl, CLSET_TIMEOUT, (char*)&timeout_tv);
/* dont need to set vers_out since it should
* be the same as that of the udp transport
*/
ci->tcpcl = cl;
if (++tcp_count > MAX_COUNT)
/* clean up tcp connections */
cleanup_some_connection(ci);
*clnt = ci;
return (CSA_SUCCESS);
}
}
/*
* Used instead of clnt_call by rtableX_clnt.c
*
* Might need locking for the client handle here since
* it might be purged if something's wrong
*/
extern enum clnt_stat
_DtCm_clnt_call(
_DtCm_Connection *conn,
u_long proc,
xdrproc_t inproc,
caddr_t in,
xdrproc_t outproc,
caddr_t out,
struct timeval tout)
{
_DtCm_Client_Info *ci;
_DtCm_Transport_Type ttype;
enum clnt_stat status = RPC_FAILED;
int retry = conn->retry;
while (B_TRUE) {
if (conn->ci == NULL)
break;
else {
ci = conn->ci;
ci->last_used = time(0);
}
if (conn->use == udp_transport || ci->tcpcl == NULL)
ttype = udp_transport;
else
ttype = tcp_transport;
status = clnt_call((ttype == tcp_transport ? ci->tcpcl :
ci->udpcl), proc, inproc, in,
outproc, out, tout);
if ((ttype == udp_transport && status == RPC_TIMEDOUT) ||
(status == RPC_CANTRECV)) {
if (retry) {
retry--;
/* don't retry when stat is RPC_TIMEDOUT
* and transpart is tcp since if the server
* is down, stat would be something else
* like RPC_CANTRECV
*/
/* get new client handle */
if (get_new_client_handle(conn) == NULL)
break;
} else {
/* purge the client handle */
delete_client_info(conn->ci);
conn->ci = NULL;
break;
}
} else
break;
}
if (status != RPC_SUCCESS && conn->ci != NULL) {
_DtCm_print_errmsg(clnt_sperror((ttype == tcp_transport ? ci->tcpcl :
ci->udpcl), ci->host));
}
conn->stat = status;
return status;
}
extern CSA_return_code
_DtCm_add_registration(
_DtCm_Client_Info *ci,
char *cal,
unsigned long update_type)
{
_DtCm_Target_List *listp, *prev;
_DtCm_Target_List *listitem;
int result;
if (ci == NULL || cal == NULL)
return (CSA_E_INVALID_PARAMETER);
for (listp = prev = ci->tlist; listp != NULL;
prev = listp, listp = listp->next) {
if ((result = strcmp(listp->cal, cal)) == 0) {
/* registered already */
return (CSA_SUCCESS);
} else if (result > 0)
break;
}
/* register the first time, insert in list in ascending order */
if ((listitem = (_DtCm_Target_List *)calloc(1, sizeof(_DtCm_Target_List))) == NULL)
return (CSA_E_INSUFFICIENT_MEMORY);
if ((listitem->cal = strdup(cal)) == NULL) {
free(listitem);
return (CSA_E_INSUFFICIENT_MEMORY);
}
listitem->update_type = update_type;
if (prev == NULL || listp == prev)
ci->tlist = listitem;
else
prev->next = listitem;
listitem->next = listp;
ci->nregistered++;
return (CSA_SUCCESS);
}
extern void
_DtCm_remove_registration(_DtCm_Client_Info *ci, char *cal)
{
_DtCm_Target_List *listp, *prev;
_DtCm_Client_Info *c;
int result;
if (cal == NULL) return;
/* if found, just increment the number of registration */
for (listp = prev = ci->tlist; listp != NULL;
prev = listp, listp = listp->next) {
if ((result = strcmp(listp->cal, cal)) == 0) {
if (listp == prev)
ci->tlist = listp->next;
else
prev->next = listp->next;
/* free target item */
free(listp->cal);
free(listp);
/*
* if no calendar is registered, close tcp connection
*/
if (--(ci->nregistered) == 0) {
if (ci->tcpcl) {
destroy_auth(ci->tcpcl);
clnt_destroy(ci->tcpcl);
ci->tcpcl = NULL;
tcp_count--;
}
/* find other tcp connection for the
* same host
*/
for (c = client_cache_head; c != NULL;
c = c->next) {
if ((result = strcmp(c->host,
ci->host)) == 0) {
if (c->nregistered == 0 &&
c->tcpcl) {
destroy_auth(c->tcpcl);
clnt_destroy(c->tcpcl);
c->tcpcl = NULL;
tcp_count--;
}
} else if (result > 0)
break;
}
}
return;
} else if (result > 0)
break;
}
/* not found; impossible */
}
extern CSA_return_code
_DtCm_get_server_rpc_version(char *host, int *version)
{
CSA_return_code stat;
_DtCm_Client_Info *ci;
if (host == NULL) {
return (CSA_E_INVALID_PARAMETER);
}
if ((stat = _DtCm_create_tcp_client(host, TABLEVERS,
_DtCM_INITIAL_TIMEOUT, &ci)) == CSA_SUCCESS)
*version = ci->vers_out;
return (stat);
}
extern CSA_return_code
_DtCm_clntstat_to_csastat(enum clnt_stat clntstat)
{
switch (clntstat) {
#if defined(SunOS) || defined(USL) || defined(__uxp__)
case RPC_N2AXLATEFAILURE:
#endif
case RPC_UNKNOWNHOST:
return (CSA_X_DT_E_INVALID_SERVER_LOCATION);
case RPC_PROGNOTREGISTERED:
return (CSA_X_DT_E_SERVICE_NOT_REGISTERED);
case RPC_TIMEDOUT:
return (CSA_X_DT_E_SERVER_TIMEOUT);
default:
return (CSA_E_SERVICE_UNAVAILABLE);
}
}
/*****************************************************************************
* static functions used within the file
*****************************************************************************/
static void
create_auth(CLIENT *cl)
{
/* Always cache the Unix style credentials. */
if (unix_credential == NULL)
#if defined(SunOS) || defined(USL) || defined(__uxp__)
unix_credential = authsys_create_default ();
#else
unix_credential = authunix_create_default ();
#endif
cl->cl_auth = unix_credential;
}
static void
destroy_auth(CLIENT *cl)
{
/* It is a no-op for unix-authentication because we always cache it.
* But we have to destroy it when secure RPC is used.
*/
}
/*
* Given a host name, find the _DtCm_Client_Info structure which contains
* both udp and tcp handle to the server running in the host.
*/
static _DtCm_Client_Info *
get_client_info(char *host, int version)
{
_DtCm_Client_Info *ci;
int result;
if (host==NULL) return(NULL);
for (ci = client_cache_head; ci != NULL; ci = ci->next) {
if ((result = strcmp(ci->host, host)) == 0) {
if (ci->vers_out <= version)
return(ci);
} else if (result > 0)
break;
}
return(NULL);
}
static void
destroy_target_list(_DtCm_Target_List *tlist)
{
_DtCm_Target_List *listp, *listitem;
for (listp = tlist; listp != NULL; ) {
listitem = listp;
listp = listp->next;
if (listitem->cal)
free(listitem->cal);
free(listitem);
}
}
static void
destroy_client_info(_DtCm_Client_Info *ci)
{
if (ci==NULL) return;
if (ci->host != NULL)
free(ci->host);
if (ci->tcpcl) {
destroy_auth(ci->tcpcl);
clnt_destroy(ci->tcpcl);
tcp_count--;
}
if (ci->udpcl) {
destroy_auth(ci->udpcl);
clnt_destroy(ci->udpcl);
}
destroy_target_list(ci->tlist);
free(ci);
cl_count--;
}
/*
* Dont limit the number of cached connections right now.
* Udp client handle does not use up file descriptor only space.
* Tcp client handle is kept open only when there's at least one
* calendar registered with the host and the user probably won't
* be browsing more than 50 calendar at the same time.
*/
static void
insert_client_info(_DtCm_Client_Info *ci)
{
_DtCm_Client_Info *citem;
if (++cl_count > MAX_COUNT)
cleanup_some_connection(ci);
/* insert new item alphabetically */
for (citem = client_cache_head; citem != NULL; citem = citem->next) {
/* there shouldn't be an entry with the same host name
* if there's, it would be picked up in get_client_info()
*/
if (strcmp(citem->host, ci->host) > 0)
break;
}
if (citem == NULL) {
if (client_cache_head == NULL)
client_cache_head = client_cache_tail = ci;
else {
ci->prev = client_cache_tail;
client_cache_tail->next = ci;
client_cache_tail = ci;
}
} else {
ci->next = citem;
ci->prev = citem->prev;
if (citem == client_cache_head)
client_cache_head = ci;
else
citem->prev->next = ci;
citem->prev = ci;
}
#ifdef CM_DEBUG
fprintf(stderr, "%s: head = %d, tail = %d, newitem = %d\n",
"insert_client_info", client_cache_head,
client_cache_tail, ci);
fprintf(stderr, "tcp_count = %d, cl_count = %d\n", tcp_count, cl_count);
#endif
}
/*
* remove the client info structure from the list
*/
static void
delete_client_info(_DtCm_Client_Info *oldci)
{
if (oldci == NULL) return;
if (oldci == client_cache_head) {
client_cache_head = oldci->next;
if (client_cache_head)
client_cache_head->prev = NULL;
} else if (oldci == client_cache_tail) {
client_cache_tail = oldci->prev;
if (client_cache_tail)
client_cache_tail->next = NULL;
} else {
oldci->prev->next = oldci->next;
oldci->next->prev = oldci->prev;
}
if (oldci == client_cache_tail)
client_cache_tail = NULL;
destroy_client_info(oldci);
#ifdef CM_DEBUG
fprintf(stderr, "%s: head = %d, tail = %d, olditem = %d\n",
"delete_client_info", client_cache_head,
client_cache_tail, oldci);
#endif
}
/*
* Number of open tcp connections reaches the maximum.
* This is very unlikely in the normal case since
* a tcp connection is kept open if at least one calendar
* is registered with the host and a user would not be
* browsing a large number of calendars at one time.
* However, when a calendar is deselected in the calendar
* list on the multi-browser window, a lookup call using
* the tcp connection is made after the calendar is
* deregistered. This keeps the tcp connection open
* even if that's the last calendar registered with the
* host. This routine is used to clean up such tcp connections.
* This is a good time to clean up connections that are not
* used for a long time.
*/
static void
cleanup_some_connection(_DtCm_Client_Info *dontclose)
{
_DtCm_Client_Info *ci, *oldci;
int total = 0, deleted = 0, done = 0;
for (ci = client_cache_head; ci != NULL; )
{
total++;
#ifdef HPUX
/* clean up whole list */
if (ci != dontclose && ci->nregistered == 0) {
#else
if (ci != dontclose && ci->nregistered == 0 &&
(ci->tcpcl || (!done && ci->tcpcl == NULL) ||
(ci->tcpcl==NULL && (time(NULL) - ci->last_used)>DAYSEC)))
{
if (!done) done = 1;
#endif
deleted++;
oldci = ci;
ci = ci->next;
delete_client_info(oldci);
} else
ci = ci->next;
}
#ifdef CM_DEBUG
fprintf(stderr, "%s: total = %d, deleted = %d\n",
"cleanup_tcp_connection", total, deleted);
#endif
}
/*
* check registration
* Deergister the first target:
* if it succeeded, the old server is still running, just re-register it;
* else assume that it's a new server so re-register the whole list again.
*/
static void
check_registration(_DtCm_Connection *conn)
{
_DtCm_Target_List *listp, *prev;
_DtCm_Transport_Type olduse;
CSA_return_code stat;
if (conn->ci->tlist == NULL)
return;
olduse = conn->use;
conn->use = udp_transport;
conn->retry = B_FALSE;
if ((stat = _DtCm_do_unregistration(conn, conn->ci->tlist->cal,
conn->ci->tlist->update_type)) == CSA_SUCCESS) {
if (_DtCm_do_registration(conn, conn->ci->tlist->cal,
conn->ci->tlist->update_type) != CSA_SUCCESS)
{
conn->ci->nregistered--;
listp = conn->ci->tlist;
conn->ci->tlist = listp->next;
free(listp->cal);
free(listp);
}
} else if (stat == CSA_E_CALLBACK_NOT_REGISTERED || stat == CSA_E_FAILURE) {
for (listp = prev = conn->ci->tlist; listp != NULL; ) {
if (_DtCm_do_registration(conn, listp->cal,
listp->update_type) != CSA_SUCCESS)
{
conn->ci->nregistered--;
if (listp == prev)
conn->ci->tlist = prev = listp->next;
else
prev->next = listp->next;
/* free target item */
free(listp->cal);
free(listp);
listp = (prev ? prev->next : NULL);
} else {
prev = listp;
listp = listp->next;
}
}
}
conn->use = olduse;
}
static _DtCm_Client_Info *
get_new_client_handle(_DtCm_Connection *conn)
{
CLIENT *cl;
int oldver;
if (conn == NULL) return(NULL);
oldver = conn->ci->vers_out;
/* always get a udp client handle first */
#if defined(SunOS) || defined(USL) || defined(__uxp__)
cl = clnt_create_vers(conn->ci->host, TABLEPROG, &(conn->ci->vers_out),
TABLEVERS_2, oldver, "udp");
if (cl == NULL) {
_DtCm_print_errmsg(clnt_spcreateerror(conn->ci->host));
}
#else
(void) get_client_handle(conn->ci->host, (u_int)TABLEPROG,
&(conn->ci->vers_out), TABLEVERS_2, oldver,
"udp", &cl);
#endif
if (cl == NULL) {
delete_client_info(conn->ci);
conn->ci = NULL;
return(NULL);
} else {
create_auth(cl);
/* adjust timeout */
timeout_tv.tv_sec = _DtCM_INITIAL_TIMEOUT;
timeout_tv.tv_usec = 0;
clnt_control(cl, CLSET_TIMEOUT, (char *)&timeout_tv);
retry_tv.tv_sec = _DtCM_INITIAL_TIMEOUT + 10;
retry_tv.tv_usec = 0;
clnt_control(cl, CLSET_RETRY_TIMEOUT, (char *)&retry_tv);
destroy_auth(conn->ci->udpcl);
clnt_destroy(conn->ci->udpcl);
conn->ci->udpcl = cl;
}
/* check registration */
/* if there's anything wrong, nregistered could be zero */
check_registration(conn);
/* ci might be set to NULL if an rpc call failed */
if (conn->ci == NULL)
return (NULL);
/* now deal with tcp handle */
/* get rid of old handle first */
if (conn->ci->tcpcl) {
destroy_auth(conn->ci->tcpcl);
clnt_destroy(conn->ci->tcpcl);
tcp_count--;
conn->ci->tcpcl = NULL;
}
if (conn->use == udp_transport) {
return(conn->ci);
} else {
/* get a tcp client handle */
oldver = conn->ci->vers_out;
#if defined(SunOS) || defined(USL) || defined(__uxp__)
cl = clnt_create_vers(conn->ci->host, TABLEPROG,
&(conn->ci->vers_out), TABLEVERS_2, oldver, "tcp");
if (cl == NULL)
_DtCm_print_errmsg(clnt_spcreateerror(conn->ci->host));
#else
(void) get_client_handle(conn->ci->host, (u_int)TABLEPROG,
&(conn->ci->vers_out), TABLEVERS_2, oldver, "tcp",
&cl);
#endif
if (cl == NULL) {
conn->ci->vers_out = oldver;
return(NULL);
} else {
create_auth(cl);
/* adjust timeout */
timeout_tv.tv_sec = _DtCM_INITIAL_TIMEOUT;
timeout_tv.tv_usec = 0;
clnt_control(cl, CLSET_TIMEOUT, (char *)&timeout_tv);
conn->ci->tcpcl = cl;
tcp_count++;
return(conn->ci);
}
}
}
/*
* Get a client handle to a server that supports the highest
* version between the given range.
*/
static CSA_return_code
get_client_handle(
const char *host,
#ifdef __osf__
const u_int prognum,
#else
const u_long prognum,
#endif
u_long *vers_outp,
const u_long vers_low,
const u_long vers_high,
char *nettype,
CLIENT **clnt)
{
CLIENT *cl;
u_int vers;
struct timeval tv;
enum clnt_stat status;
#ifdef HPUX
static int bumped = 0;
struct rlimit rl;
if (bumped == 0) {
bumped = 1;
/* raise the soft limit of number of file descriptor */
getrlimit(RLIMIT_NOFILE, &rl);
rl.rlim_cur = rl.rlim_max;
setrlimit(RLIMIT_NOFILE, &rl);
}
#endif
#ifdef __osf__
/*
* A longer timeout value may be necessay - for example if
* the system is bogged down and/or rpc.cmsd is not running.
*
* The value below is the same value used when a ToolTalk app connects
* to the ToolTalk database server (lib/tt/lib/db/tt_db_client.C).
*/
tv.tv_sec = 4;
#else
tv.tv_sec = 1;
#endif
tv.tv_usec = 0;
*clnt = NULL;
for (vers = vers_high; vers >= vers_low; vers--) {
#if defined(__osf__) || defined(__hpux)
if ((cl = clnt_create((char *)host, prognum, vers, nettype)) != NULL) {
#else
if ((cl = clnt_create(host, prognum, vers, nettype)) != NULL) {
#endif
clnt_control(cl, CLSET_TIMEOUT, (char *)&tv);
status = clnt_call(cl, 0, (xdrproc_t) xdr_void,
(char *)NULL, (xdrproc_t) xdr_void,
(char *)NULL, tv);
if (status == RPC_SUCCESS) {
*vers_outp = vers;
*clnt = cl;
#ifdef __osf__
/*
* Set the timeout back to the original.
*/
tv.tv_sec = 1;
clnt_control(cl, CLSET_TIMEOUT, (char *)&tv);
#endif
return (CSA_SUCCESS);
} else if (status != RPC_PROGVERSMISMATCH) {
return (_DtCm_clntstat_to_csastat(status));
}
} else {
_DtCm_print_errmsg(clnt_spcreateerror((char *) host));
return (_DtCm_clntstat_to_csastat(rpc_createerr.cf_stat));
}
}
/* cannot find a server that supports a version in the given range */
/* Probably will never get here */
return (CSA_E_SERVICE_UNAVAILABLE);
}
static CSA_return_code
regstat4_to_dtcmstatus(Registration_Status_4 stat4)
{
switch (stat4) {
case registered_4:
return (CSA_SUCCESS);
case deregistered_4:
return (CSA_SUCCESS);
case reg_notable_4:
return (CSA_E_CALENDAR_NOT_EXIST);
case failed_4:
case confused_4:
return (CSA_E_FAILURE);
}
}