xenocara/app/proxymngr/main.c
2006-11-25 20:07:29 +00:00

1146 lines
27 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* $Xorg: main.c,v 1.6 2001/02/09 02:05:34 xorgcvs Exp $ */
/*
Copyright 1996, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from The Open Group.
*/
/* $XFree86: xc/programs/proxymngr/main.c,v 1.8tsi Exp $ */
#include <stdlib.h>
#include "pmint.h"
#include <X11/StringDefs.h>
#include <X11/Intrinsic.h>
#include <X11/ICE/ICEmsg.h>
#include <X11/ICE/ICEproto.h>
#include <X11/PM/PMproto.h>
#include <X11/PM/PM.h>
#include "pmdb.h"
#include "config.h"
#include <assert.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
static int PMprotocolSetupProc ( IceConn iceConn, int majorVersion,
int minorVersion, char *vendor,
char *release, IcePointer *clientDataRet,
char **failureReasonRet );
static void SendGetProxyAddr ( PMconn *pmConn, char *serviceName,
char *serverAddress, char *hostAddress,
char *startOptions, int authLen,
char *authName, char *authData );
static int PMAcceptorOpcode;
static int PMOriginatorOpcode;
int PMversionCount = 1;
IcePaVersionRec PMReplyVersions[] = {{PM_MAJOR_VERSION, PM_MINOR_VERSION,
PMReplyProcessMessages}};
IcePoVersionRec PMSetupVersions[] = {{PM_MAJOR_VERSION, PM_MINOR_VERSION,
PMSetupProcessMessages}};
char *PM_VENDOR_STRING = XVENDORNAME;
char *PM_VENDOR_RELEASE = XORG_RELEASE;
int verbose = 0;
XtAppContext appContext;
#define PM_PORT "6500"
char *configFile = NULL;
void
Usage ()
{
fprintf (stderr, "Usage: proxymngr [-config file] [-verbose]\n");
exit (1);
}
void
SetCloseOnExec (fd)
int fd;
{
#ifdef F_SETFD
#ifdef FD_CLOEXEC
(void) fcntl (fd, F_SETFD, FD_CLOEXEC);
#else
(void) fcntl (fd, F_SETFD, 1);
#endif /* FD_CLOEXEC */
#endif /* F_SETFD */
}
/*
* Main program
*/
int
main (int argc, char *argv[])
{
IceListenObj *listenObjs;
int numTransports, i;
char errormsg[256];
char *networkIds, *p;
for (i = 1; i < argc; i++)
{
if (strcmp (argv[i], "-config") == 0)
{
if (++i < argc)
configFile = argv[i];
else
Usage ();
}
else if (strcmp(argv[i], "-verbose") == 0)
{
verbose = 1;
}
else
Usage ();
}
if (!configFile)
configFile = CONFIG_FILE;
if (verbose)
fprintf (stderr, "config file = %s\n", configFile);
/*
* Install an IO error handler.
*/
InstallIOErrorHandler ();
/*
* Register support for PROXY_MANAGEMENT.
*/
/* For Managed proxies, the proxy does the Setup */
if ((PMAcceptorOpcode = IceRegisterForProtocolReply (
PM_PROTOCOL_NAME, PM_VENDOR_STRING, PM_VENDOR_RELEASE,
PMversionCount, PMReplyVersions,
0, /* authcount */
NULL, /* authnames */
NULL, /* authprocs */
HostBasedAuthProc,
PMprotocolSetupProc,
NULL, /* protocolActivateProc */
NULL /* IceIOErrorProc */ )) < 0)
{
fprintf (stderr,
"Could not register PROXY_MANAGEMENT protocol reply with ICE");
exit (1);
}
/* For Unmanaged proxies, we do the Setup
* ICElib doesn't specify that the same opCode will be returned
* so don't bet on it.
*/
if ((PMOriginatorOpcode = IceRegisterForProtocolSetup (
PM_PROTOCOL_NAME, PM_VENDOR_STRING, PM_VENDOR_RELEASE,
PMversionCount, PMSetupVersions,
0, /* authcount */
NULL, /* authnames */
NULL, /* authprocs */
NULL /* IceIOErrorProc */ )) < 0)
{
fprintf (stderr,
"Could not register PROXY_MANAGEMENT protocol setup with ICE");
exit (1);
}
if (!IceListenForWellKnownConnections (
PM_PORT, &numTransports, &listenObjs, 256, errormsg))
{
fprintf (stderr, "%s\n", errormsg);
exit (1);
}
networkIds = IceComposeNetworkIdList (numTransports, listenObjs);
p = (char *) malloc(sizeof ("PROXY_MANAGER") + strlen(networkIds) + 2);
sprintf (p, "PROXY_MANAGER=%s", networkIds);
putenv (p);
printf ("%s\n", p);
free (networkIds);
appContext = XtCreateApplicationContext ();
InitWatchProcs (appContext);
for (i = 0; i < numTransports; i++)
{
XtAppAddInput (appContext,
IceGetListenConnectionNumber (listenObjs[i]),
(XtPointer) XtInputReadMask,
NewConnectionXtProc, (XtPointer) listenObjs[i]);
IceSetHostBasedAuthProc (listenObjs[i], HostBasedAuthProc);
SetCloseOnExec (IceGetListenConnectionNumber (listenObjs[i]));
}
/*
* Main loop
*/
XtAppMainLoop (appContext);
exit (0);
}
/*
* Xt callback invoked when a client attempts to connect.
*/
/* ARGSUSED */
void
NewConnectionXtProc (client_data, source, id)
XtPointer client_data;
int *source;
XtInputId *id;
{
IceConn ice_conn;
char *connstr;
IceAcceptStatus status;
ice_conn = IceAcceptConnection((IceListenObj) client_data, &status);
if (! ice_conn) {
if (verbose)
printf ("IceAcceptConnection failed\n");
} else {
IceConnectStatus cstatus;
/*
* Mark this fd to be closed upon exec
*/
SetCloseOnExec (IceConnectionNumber (ice_conn));
while ((cstatus = IceConnectionStatus (ice_conn))==IceConnectPending) {
XtAppProcessEvent (appContext, XtIMAll);
}
if (cstatus == IceConnectAccepted) {
if (verbose) {
printf ("ICE Connection opened by client, IceConn fd = %d, ",
IceConnectionNumber (ice_conn));
connstr = IceConnectionString (ice_conn);
printf ("Accept at networkId %s\n", connstr);
free (connstr);
printf ("\n");
}
} else {
if (verbose)
{
if (cstatus == IceConnectIOError)
printf ("IO error opening ICE Connection!\n");
else
printf ("ICE Connection rejected!\n");
}
IceCloseConnection (ice_conn);
}
}
}
/*
* See ConnectToProxy() if you change any of the pmConn structure
*/
static Status
PMprotocolSetupProc (iceConn,
majorVersion, minorVersion, vendor, release,
clientDataRet, failureReasonRet)
IceConn iceConn;
int majorVersion;
int minorVersion;
char *vendor;
char *release;
IcePointer *clientDataRet;
char **failureReasonRet;
{
/*
* Allocate new pmConn.
*/
static char standardError[] = "Could not allocate memory for new client";
PMconn *pmConn;
if ((pmConn = (PMconn *) malloc (sizeof (PMconn))) == NULL)
{
if (verbose)
fprintf (stderr, "%s\n", standardError);
*failureReasonRet = standardError;
return (0);
}
pmConn->iceConn = iceConn;
pmConn->pmOpcode = PMAcceptorOpcode;
pmConn->proto_major_version = majorVersion;
pmConn->proto_minor_version = minorVersion;
pmConn->vendor = vendor;
pmConn->release = release;
*clientDataRet = (IcePointer) pmConn;
return (1);
}
static void
SendGetProxyAddr (
PMconn *pmConn,
char *serviceName,
char *serverAddress,
char *hostAddress,
char *startOptions,
int authLen,
char *authName,
char *authData)
{
IceConn iceConn = pmConn->iceConn;
pmGetProxyAddrMsg *pMsg;
char *pData;
int len;
if (verbose) {
printf ("Sending GetProxyAddr to proxy %d, serviceName = %s, serverAddr = %s\n",
IceConnectionNumber(iceConn), serviceName, serverAddress);
printf (" hostAddr = %s, options = %s, authLen = %d\n",
hostAddress ? hostAddress : "",
startOptions ? startOptions : "",
authLen);
if (authLen > 0)
printf (" authName = %s\n", authName);
}
len = STRING_BYTES (serviceName) +
STRING_BYTES (serverAddress) +
STRING_BYTES (hostAddress) +
STRING_BYTES (startOptions) +
(authLen > 0 ? (STRING_BYTES (authName) + authLen) : 0);
IceGetHeaderExtra (iceConn, pmConn->pmOpcode, PM_GetProxyAddr,
SIZEOF (pmGetProxyAddrMsg), WORD64COUNT (len),
pmGetProxyAddrMsg, pMsg, pData);
pMsg->authLen = authLen;
STORE_STRING (pData, serviceName);
STORE_STRING (pData, serverAddress);
STORE_STRING (pData, hostAddress);
STORE_STRING (pData, startOptions);
if (authLen > 0)
{
STORE_STRING (pData, authName);
memcpy (pData, authData, authLen);
}
IceFlush (iceConn);
}
void
SendGetProxyAddrReply (
PMconn *requestor,
int status,
char *addr,
char *error)
{
int len = STRING_BYTES (addr) + STRING_BYTES (error);
pmGetProxyAddrReplyMsg *pReply;
char *pData;
if (verbose) {
fputs ("Replying with ", stderr);
fputs (status == PM_Success ? "Success: " :
status == PM_Failure ? "Failure: " :
status == PM_Unable ? "Unable: " :
"?unknown status", stderr);
fputs (status == PM_Success ? addr : error, stderr);
fputc ('\n', stderr);
}
IceGetHeaderExtra (requestor->iceConn,
requestor->pmOpcode, PM_GetProxyAddrReply,
SIZEOF (pmGetProxyAddrReplyMsg), WORD64COUNT (len),
pmGetProxyAddrReplyMsg, pReply, pData);
pReply->status = status;
STORE_STRING (pData, addr);
STORE_STRING (pData, error);
IceFlush (requestor->iceConn);
}
void
PMReplyProcessMessages (iceConn, clientData, opcode, length, swap)
IceConn iceConn;
IcePointer clientData;
int opcode;
unsigned long length;
Bool swap;
{
PMconn *pmConn = (PMconn *) clientData;
assert(pmConn->iceConn == iceConn);
switch (opcode)
{
case PM_GetProxyAddr:
{
pmGetProxyAddrMsg *pMsg;
char *pData, *pStart;
char *serviceName = NULL, *serverAddress = NULL;
char *hostAddress = NULL, *startOptions = NULL;
char *authName = NULL, *authData = NULL;
int authLen;
#if 0 /* No-op */
CHECK_AT_LEAST_SIZE (iceConn, pmConn->pmOpcode, opcode,
length, SIZEOF (pmGetProxyAddrMsg), IceFatalToProtocol);
#endif
IceReadCompleteMessage (iceConn, SIZEOF (pmGetProxyAddrMsg),
pmGetProxyAddrMsg, pMsg, pStart);
if (!IceValidIO (iceConn))
{
IceDisposeCompleteMessage (iceConn, pStart);
return;
}
authLen = swap ? lswaps (pMsg->authLen) : pMsg->authLen;
pData = pStart;
SKIP_STRING (pData, swap); /* proxy-service */
SKIP_STRING (pData, swap); /* server-address */
SKIP_STRING (pData, swap); /* host-address */
SKIP_STRING (pData, swap); /* start-options */
if (authLen > 0)
{
SKIP_STRING (pData, swap); /* auth-name */
pData += (authLen + PAD64 (authLen)); /* auth-data */
}
CHECK_COMPLETE_SIZE (iceConn, pmConn->pmOpcode, opcode,
length, pData - pStart + SIZEOF (pmGetProxyAddrMsg),
pStart, IceFatalToProtocol);
pData = pStart;
EXTRACT_STRING (pData, swap, serviceName);
EXTRACT_STRING (pData, swap, serverAddress);
EXTRACT_STRING (pData, swap, hostAddress);
EXTRACT_STRING (pData, swap, startOptions);
if (authLen > 0)
{
EXTRACT_STRING (pData, swap, authName);
authData = (char *) malloc (authLen);
memcpy (authData, pData, authLen);
}
if (serverAddress)
{
/*
* Assume that if serverAddress is something like :0 or :0.0
* then the request is for a server on the client's host.
*
* However, the proxy handling this request may be on a
* different host than the client or the client host,
* proxy host and the server host may all be different,
* thus a serverAddress of :0 or :0.0 is not useful.
* Therefore, change serverAddress to use the client's
* hostname.
*/
char *tmpName;
tmpName = strrchr (serverAddress, ':');
if (tmpName && ((tmpName == serverAddress) ||
(!strncmp (serverAddress, "unix:", 5))))
{
#if defined(IPv6) && defined(AF_INET6)
struct sockaddr_storage serverSock;
#else
struct sockaddr_in serverSock;
#endif
int retVal;
int addrLen = sizeof(serverSock);
retVal = getpeername(IceConnectionNumber(iceConn),
(struct sockaddr *) &serverSock,
(void *) &addrLen);
if (!retVal)
{
char *canonname = NULL;
#if defined(IPv6) && defined(AF_INET6)
char hostname[NI_MAXHOST];
struct addrinfo *ai = NULL, hints;
if (getnameinfo((struct sockaddr *) &serverSock,
addrLen, hostname, sizeof(hostname), NULL, 0, 0) == 0) {
(void)memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_CANONNAME;
if (getaddrinfo(hostname, NULL, &hints, &ai) == 0) {
canonname = ai->ai_canonname;
} else {
ai = NULL;
}
}
#else
struct hostent *hostent;
hostent = gethostbyname (inet_ntoa(serverSock.sin_addr));
if (hostent && hostent->h_name)
canonname = hostent->h_name;
#endif
if (canonname)
{
int len;
char * pch = strdup (tmpName);
len = strlen(canonname) + strlen(tmpName) + 1;
serverAddress = (char *) realloc (serverAddress, len);
sprintf (serverAddress, "%s%s", canonname, pch);
free (pch);
}
#if defined(IPv6) && defined(AF_INET6)
if (ai != NULL)
freeaddrinfo(ai);
#endif
}
}
}
if (verbose) {
printf ("Got GetProxyAddr, serviceName = %s, serverAddr = %s\n",
serviceName, serverAddress);
printf (" hostAddr = %s, options = %s, authLen = %d\n",
hostAddress, startOptions, authLen);
if (authLen > 0)
printf (" authName = %s\n", authName);
}
IceDisposeCompleteMessage (iceConn, pStart);
ForwardRequest (pmConn, serviceName, serverAddress, hostAddress,
startOptions, authLen, authName, authData);
if (serviceName)
free (serviceName);
if (serverAddress)
free (serverAddress);
if (hostAddress)
free (hostAddress);
if (startOptions)
free (startOptions);
if (authName)
free (authName);
if (authData)
free (authData);
break;
}
case PM_StartProxy:
{
pmStartProxyMsg *pMsg;
char *pData, *pStart;
char *serviceName = NULL;
char *serverAddress;
char *hostAddress;
char *startOptions;
int authLen;
char *authName;
char *authData;
#if 0 /* No-op */
CHECK_AT_LEAST_SIZE (iceConn, pmConn->pmOpcode, opcode,
length, SIZEOF (pmStartProxyMsg), IceFatalToProtocol);
#endif
IceReadCompleteMessage (iceConn, SIZEOF (pmStartProxyMsg),
pmStartProxyMsg, pMsg, pStart);
if (!IceValidIO (iceConn))
{
IceDisposeCompleteMessage (iceConn, pStart);
return;
}
pData = pStart;
SKIP_STRING (pData, swap); /* proxy-service */
CHECK_COMPLETE_SIZE (iceConn, pmConn->pmOpcode, opcode,
length, pData - pStart + SIZEOF (pmStartProxyMsg),
pStart, IceFatalToProtocol);
pData = pStart;
EXTRACT_STRING (pData, swap, serviceName);
assert(serviceName);
if (verbose)
printf ("Got StartProxy on fd %d, serviceName = %s\n",
IceConnectionNumber(iceConn), serviceName);
IceDisposeCompleteMessage (iceConn, pStart);
if (! ActivateProxyService (serviceName, pmConn)) {
fputs ("Configuration error: received unexpected StartProxy for service ", stderr);
fputs (serviceName, stderr);
fputc ('\n', stderr);
IceCloseConnection (iceConn);
}
else {
/*
* Now send the GetProxyAddr message to the proxy.
*/
if (PeekRequestorQueue(pmConn,
NULL, NULL, NULL,
&serverAddress, &hostAddress, &startOptions,
&authLen, &authName, &authData)) {
SendGetProxyAddr(pmConn,
serviceName, serverAddress,
hostAddress, startOptions,
authLen, authName, authData);
}
else if (verbose) {
fputs ("Received StartProxy for service ", stderr);
fputs (serviceName, stderr);
fputs (" but no waiting GetproxyAddr requests\n", stderr);
}
}
free (serviceName);
break;
}
case PM_GetProxyAddrReply:
{
pmGetProxyAddrReplyMsg *pMsg;
char *pData, *pStart;
char *addr = NULL, *error = NULL;
#if 0 /* No-op */
CHECK_AT_LEAST_SIZE (iceConn, pmConn->pmOpcode, opcode,
length, SIZEOF (pmGetProxyAddrReplyMsg), IceFatalToProtocol);
#endif
IceReadCompleteMessage (iceConn, SIZEOF (pmGetProxyAddrReplyMsg),
pmGetProxyAddrReplyMsg, pMsg, pStart);
if (!IceValidIO (iceConn))
{
IceDisposeCompleteMessage (iceConn, pStart);
return;
}
pData = pStart;
SKIP_STRING (pData, swap); /* proxy-address */
SKIP_STRING (pData, swap); /* failure-reason */
CHECK_COMPLETE_SIZE (iceConn, pmConn->pmOpcode, opcode,
length, pData - pStart + SIZEOF (pmGetProxyAddrReplyMsg),
pStart, IceFatalToProtocol);
pData = pStart;
EXTRACT_STRING (pData, swap, addr);
EXTRACT_STRING (pData, swap, error);
if (verbose) {
printf ("Got GetProxyAddrReply from proxy %d, status = %d, ",
IceConnectionNumber(iceConn), pMsg->status);
if (pMsg->status == PM_Success)
printf ("addr = %s\n", addr);
else
printf ("error = %s\n", error);
}
{ /* Ignore any unsolicited replies so we don't get further confused */
running_proxy *proxy = ProxyForPMconn(pmConn);
if (!proxy || !proxy->requests)
{
if (verbose)
fprintf (stderr, "Received unsolicited GetProxyAddrReply from proxy %d; ignoring it.\n",
IceConnectionNumber(iceConn));
IceDisposeCompleteMessage (iceConn, pStart);
break;
}
}
switch (pMsg->status) {
case PM_Success:
{
/*
* Now send the GetProxyAddr reply to xfindproxy.
*/
SendGetProxyAddrReply (
PopRequestorQueue (pmConn, True, True /* free proxy list */),
PM_Success /* status */, addr, NULL);
break;
}
case PM_Unable:
{
running_proxy_list *proxyList;
char *serviceName, *serverAddress, *hostAddress, *startOptions;
PMconn *requestor;
int authLen;
char *authName;
char *authData;
{
running_proxy *proxy = ProxyForPMconn(pmConn);
if (proxy)
proxy->refused_service = True;
else
fputs("Internal error: received GetProxyAddrReply from an unknown proxy\n", stderr);
}
if (! PeekRequestorQueue (pmConn, &requestor,
&proxyList, &serviceName, &serverAddress,
&hostAddress, &startOptions,
&authLen, &authName, &authData)) {
if (verbose)
fputs("Received GetProxyAddrReply from a proxy with no requests\n", stderr);
proxyList = NULL;
serviceName = "?unknown service--internal error";
}
if (proxyList && (proxyList->current < proxyList->count - 1))
{
/*
* Ask the next running proxy if it can service this request.
*/
running_proxy *nextProxy;
proxyList->current++;
nextProxy = proxyList->list[proxyList->current];
if (nextProxy->pmConn != NULL) {
/* send only if the proxy has started */
SendGetProxyAddr (nextProxy->pmConn, serviceName,
serverAddress, hostAddress, startOptions,
authLen, authName, authData);
}
PushRequestorQueue (nextProxy, requestor, proxyList,
serviceName, serverAddress, hostAddress, startOptions,
authLen, authName, authData);
PopRequestorQueue (pmConn, False, False);
}
else
{
/*
* Start a new proxy.
*/
running_proxy *runningProxy = NULL;
char *startCommand;
char *proxyAddress;
Bool managed;
if (!GetConfig (configFile, serviceName, &managed,
&startCommand, &proxyAddress))
{
SendGetProxyAddrReply (requestor, PM_Failure,
NULL, "Could not read proxy manager config file");
}
else
{
runningProxy = StartNewProxy (serviceName, startCommand);
if (runningProxy)
{
PushRequestorQueue (runningProxy,
requestor, proxyList,
serviceName, serverAddress,
hostAddress, startOptions,
authLen, authName, authData);
}
else
{
SendGetProxyAddrReply (pmConn, PM_Failure,
NULL, "Can't start new proxy");
}
}
if (startCommand)
free (startCommand);
if (proxyAddress)
free (proxyAddress);
PopRequestorQueue (pmConn, False,
runningProxy ? False : True /* free proxy list */);
}
break;
}
default:
if (verbose && pMsg->status != PM_Unable)
fprintf(stderr,
"Error: proxy returned unrecognized status: %d\n",
pMsg->status);
/* FALLTHROUGH */
case PM_Failure:
SendGetProxyAddrReply (
PopRequestorQueue (pmConn, True, True /* free proxy list */),
pMsg->status, NULL, error);
}
IceDisposeCompleteMessage (iceConn, pStart);
/* see if there was more work queued for this proxy */
{
char *serviceName, *serverAddress, *hostAddress, *startOptions;
int authLen;
char *authName, *authData;
if (PeekRequestorQueue(pmConn,
NULL, NULL, &serviceName,
&serverAddress, &hostAddress, &startOptions,
&authLen, &authName, &authData)) {
SendGetProxyAddr(pmConn,
serviceName, serverAddress,
hostAddress, startOptions,
authLen, authName, authData);
}
}
if (addr)
free (addr);
if (error)
free (error);
break;
}
case PM_Error:
{
iceErrorMsg *pMsg;
char *pStart;
CHECK_AT_LEAST_SIZE (iceConn, pmConn->pmOpcode, PM_Error, length,
sizeof(iceErrorMsg), IceFatalToProtocol);
IceReadCompleteMessage (iceConn, SIZEOF (iceErrorMsg),
iceErrorMsg, pMsg, pStart);
if (!IceValidIO (iceConn))
{
IceDisposeCompleteMessage (iceConn, pStart);
return;
}
if (swap)
{
pMsg->errorClass = lswaps (pMsg->errorClass);
pMsg->offendingSequenceNum = lswapl (pMsg->offendingSequenceNum);
}
fprintf(stderr, "Received ICE Error: class=0x%x\n offending minor opcode=%d, severity=%d, sequence=%d\n",
pMsg->errorClass, pMsg->offendingMinorOpcode, pMsg->severity,
(int)pMsg->offendingSequenceNum);
IceDisposeCompleteMessage (iceConn, pStart);
break;
}
default:
{
_IceErrorBadMinor (iceConn, pmConn->pmOpcode, opcode, IceCanContinue);
_IceReadSkip (iceConn, length << 3);
break;
}
}
}
void
PMSetupProcessMessages (iceConn, clientData, opcode, length, swap,
replyWait, replyReadyRet)
IceConn iceConn;
IcePointer clientData;
int opcode;
unsigned long length;
Bool swap;
IceReplyWaitInfo *replyWait;
Bool *replyReadyRet;
{
assert (replyWait == NULL);
PMReplyProcessMessages (iceConn, clientData, opcode, length, swap);
}
void
ForwardRequest( requestor, serviceName, serverAddress, hostAddress,
startOptions, authLen, authName, authData )
PMconn *requestor;
char *serviceName, *serverAddress, *hostAddress, *startOptions;
int authLen;
char *authName, *authData;
{
running_proxy_list *proxyList;
running_proxy *runningProxy = NULL;
int pushRequest = 0;
if ((proxyList = GetRunningProxyList (
serviceName, serverAddress)) != NULL)
{
while (proxyList->current < proxyList->count) {
runningProxy = proxyList->list[proxyList->current];
if (runningProxy->pmConn != NULL) {
SendGetProxyAddr (runningProxy->pmConn, serviceName,
serverAddress, hostAddress, NULL,
authLen, authName, authData);
break;
}
proxyList->current++;
}
pushRequest = 1;
}
else
{
Bool managed;
char *startCommand;
char *proxyAddress;
if (!GetConfig (configFile, serviceName, &managed,
&startCommand, &proxyAddress))
{
SendGetProxyAddrReply (requestor, PM_Failure,
NULL, "Could not find requested service");
}
else
{
if (managed)
{
runningProxy = StartNewProxy (serviceName, startCommand);
if (runningProxy)
pushRequest = 1;
else
{
SendGetProxyAddrReply (requestor, PM_Failure,
NULL, "Can't start new proxy");
}
}
else
{
/*
* We have the unmanged proxy's address; now forward
* the request to it.
*/
runningProxy = ConnectToProxy (PMOriginatorOpcode,
serviceName, proxyAddress);
if (runningProxy) {
SendGetProxyAddr (runningProxy->pmConn,
serviceName, serverAddress,
hostAddress, startOptions,
authLen, authName, authData);
pushRequest = 1;
}
else
{
/* %%% We should reread the config file and look
* for another proxy address before giving up.
*/
SendGetProxyAddrReply (requestor, PM_Failure,
NULL, "Can't connect to proxy");
}
}
if (startCommand)
free (startCommand);
if (proxyAddress)
free (proxyAddress);
}
}
if (pushRequest)
{
PushRequestorQueue (runningProxy, requestor, proxyList,
serviceName, serverAddress, hostAddress, startOptions,
authLen, authName, authData);
}
}
/* ARGSUSED */
void
_XtProcessIceMsgProc (client_data, source, id)
XtPointer client_data;
int *source;
XtInputId *id;
{
IceConn ice_conn = (IceConn) client_data;
IceProcessMessagesStatus status;
status = IceProcessMessages (ice_conn, NULL, NULL);
if (status == IceProcessMessagesIOError)
{
Bool activeReqs;
ProxyGone (ice_conn, &activeReqs);
IceSetShutdownNegotiation (ice_conn, False);
IceCloseConnection (ice_conn);
}
}
void
_XtIceWatchProc (ice_conn, client_data, opening, watch_data)
IceConn ice_conn;
IcePointer client_data;
Bool opening;
IcePointer *watch_data;
{
if (opening)
{
XtAppContext appContext = (XtAppContext) client_data;
*watch_data = (IcePointer) XtAppAddInput (
appContext,
IceConnectionNumber (ice_conn),
(XtPointer) XtInputReadMask,
_XtProcessIceMsgProc,
(XtPointer) ice_conn);
}
else
{
XtRemoveInput ((XtInputId) *watch_data);
}
}
Status
InitWatchProcs (appContext)
XtAppContext appContext;
{
return (IceAddConnectionWatch (_XtIceWatchProc, (IcePointer) appContext));
}
/*
* The real way to handle IO errors is to check the return status
* of IceProcessMessages. xsm properly does this.
*
* Unfortunately, a design flaw exists in the ICE library in which
* a default IO error handler is invoked if no IO error handler is
* installed. This default handler exits. We must avoid this.
*
* To get around this problem, we install an IO error handler that
* does a little magic. Since a previous IO handler might have been
* installed, when we install our IO error handler, we do a little
* trick to get both the previous IO error handler and the default
* IO error handler. When our IO error handler is called, if the
* previous handler is not the default handler, we call it. This
* way, everyone's IO error handler gets called except the stupid
* default one which does an exit!
*/
static IceIOErrorHandler prev_handler;
void
MyIoErrorHandler (ice_conn)
IceConn ice_conn;
{
if (prev_handler)
(*prev_handler) (ice_conn);
}
void
InstallIOErrorHandler ()
{
IceIOErrorHandler default_handler;
prev_handler = IceSetIOErrorHandler (NULL);
default_handler = IceSetIOErrorHandler (MyIoErrorHandler);
if (prev_handler == default_handler)
prev_handler = NULL;
}
/*
* Since proxy manager does not authenticate connections, we disable
* authentication by always returning true in the host based auth proc.
*/
Bool
HostBasedAuthProc (hostname)
char *hostname;
{
return (1);
}