main.c revision 5c10afb9
15c10afb9Smrg/* $Xorg: main.c,v 1.6 2001/02/09 02:05:34 xorgcvs Exp $ */
25c10afb9Smrg
35c10afb9Smrg/*
45c10afb9SmrgCopyright 1996, 1998  The Open Group
55c10afb9Smrg
65c10afb9SmrgPermission to use, copy, modify, distribute, and sell this software and its
75c10afb9Smrgdocumentation for any purpose is hereby granted without fee, provided that
85c10afb9Smrgthe above copyright notice appear in all copies and that both that
95c10afb9Smrgcopyright notice and this permission notice appear in supporting
105c10afb9Smrgdocumentation.
115c10afb9Smrg
125c10afb9SmrgThe above copyright notice and this permission notice shall be included
135c10afb9Smrgin all copies or substantial portions of the Software.
145c10afb9Smrg
155c10afb9SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
165c10afb9SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
175c10afb9SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
185c10afb9SmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
195c10afb9SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
205c10afb9SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
215c10afb9SmrgOTHER DEALINGS IN THE SOFTWARE.
225c10afb9Smrg
235c10afb9SmrgExcept as contained in this notice, the name of The Open Group shall
245c10afb9Smrgnot be used in advertising or otherwise to promote the sale, use or
255c10afb9Smrgother dealings in this Software without prior written authorization
265c10afb9Smrgfrom The Open Group.
275c10afb9Smrg*/
285c10afb9Smrg/* $XFree86: xc/programs/proxymngr/main.c,v 1.8tsi Exp $ */
295c10afb9Smrg
305c10afb9Smrg#include <stdlib.h>
315c10afb9Smrg#include "pmint.h"
325c10afb9Smrg#include <X11/StringDefs.h>
335c10afb9Smrg#include <X11/Intrinsic.h>
345c10afb9Smrg#include <X11/ICE/ICEmsg.h>
355c10afb9Smrg#include <X11/ICE/ICEproto.h>
365c10afb9Smrg#include <X11/PM/PMproto.h>
375c10afb9Smrg#include <X11/PM/PM.h>
385c10afb9Smrg#include "pmdb.h"
395c10afb9Smrg#include "config.h"
405c10afb9Smrg#include <assert.h>
415c10afb9Smrg
425c10afb9Smrg#include <netinet/in.h>
435c10afb9Smrg#include <arpa/inet.h>
445c10afb9Smrg#include <sys/socket.h>
455c10afb9Smrg#include <netdb.h>
465c10afb9Smrg
475c10afb9Smrgstatic int PMprotocolSetupProc ( IceConn iceConn, int majorVersion,
485c10afb9Smrg				 int minorVersion, char *vendor,
495c10afb9Smrg				 char *release, IcePointer *clientDataRet,
505c10afb9Smrg				 char **failureReasonRet );
515c10afb9Smrgstatic void SendGetProxyAddr ( PMconn *pmConn, char *serviceName,
525c10afb9Smrg			       char *serverAddress, char *hostAddress,
535c10afb9Smrg			       char *startOptions, int authLen,
545c10afb9Smrg			       char *authName, char *authData );
555c10afb9Smrg
565c10afb9Smrgstatic int PMAcceptorOpcode;
575c10afb9Smrgstatic int PMOriginatorOpcode;
585c10afb9Smrg
595c10afb9Smrgint PMversionCount = 1;
605c10afb9SmrgIcePaVersionRec	PMReplyVersions[] = {{PM_MAJOR_VERSION, PM_MINOR_VERSION,
615c10afb9Smrg				      PMReplyProcessMessages}};
625c10afb9SmrgIcePoVersionRec	PMSetupVersions[] = {{PM_MAJOR_VERSION, PM_MINOR_VERSION,
635c10afb9Smrg				      PMSetupProcessMessages}};
645c10afb9Smrg
655c10afb9Smrgchar *PM_VENDOR_STRING = XVENDORNAME;
665c10afb9Smrgchar *PM_VENDOR_RELEASE = XORG_RELEASE;
675c10afb9Smrg
685c10afb9Smrgint verbose = 0;
695c10afb9Smrg
705c10afb9SmrgXtAppContext	appContext;
715c10afb9Smrg
725c10afb9Smrg#define PM_PORT "6500"
735c10afb9Smrg
745c10afb9Smrgchar *configFile = NULL;
755c10afb9Smrg
765c10afb9Smrgvoid
775c10afb9SmrgUsage ()
785c10afb9Smrg{
795c10afb9Smrg    fprintf (stderr, "Usage: proxymngr [-config file] [-verbose]\n");
805c10afb9Smrg    exit (1);
815c10afb9Smrg}
825c10afb9Smrg
835c10afb9Smrgvoid
845c10afb9SmrgSetCloseOnExec (fd)
855c10afb9Smrg    int	fd;
865c10afb9Smrg{
875c10afb9Smrg#ifdef F_SETFD
885c10afb9Smrg#ifdef FD_CLOEXEC
895c10afb9Smrg    (void) fcntl (fd, F_SETFD, FD_CLOEXEC);
905c10afb9Smrg#else
915c10afb9Smrg    (void) fcntl (fd, F_SETFD, 1);
925c10afb9Smrg#endif /* FD_CLOEXEC */
935c10afb9Smrg#endif /* F_SETFD */
945c10afb9Smrg}
955c10afb9Smrg
965c10afb9Smrg/*
975c10afb9Smrg * Main program
985c10afb9Smrg */
995c10afb9Smrg
1005c10afb9Smrgint
1015c10afb9Smrgmain (int argc, char *argv[])
1025c10afb9Smrg{
1035c10afb9Smrg    IceListenObj *listenObjs;
1045c10afb9Smrg    int		numTransports, i;
1055c10afb9Smrg    char	errormsg[256];
1065c10afb9Smrg    char	*networkIds, *p;
1075c10afb9Smrg
1085c10afb9Smrg    for (i = 1; i < argc; i++)
1095c10afb9Smrg    {
1105c10afb9Smrg	if (strcmp (argv[i], "-config") == 0)
1115c10afb9Smrg	{
1125c10afb9Smrg	    if (++i < argc)
1135c10afb9Smrg	        configFile = argv[i];
1145c10afb9Smrg	    else
1155c10afb9Smrg		Usage ();
1165c10afb9Smrg	}
1175c10afb9Smrg	else if (strcmp(argv[i], "-verbose") == 0)
1185c10afb9Smrg	{
1195c10afb9Smrg	    verbose = 1;
1205c10afb9Smrg	}
1215c10afb9Smrg	else
1225c10afb9Smrg	    Usage ();
1235c10afb9Smrg    }
1245c10afb9Smrg
1255c10afb9Smrg    if (!configFile)
1265c10afb9Smrg	configFile = CONFIG_FILE;
1275c10afb9Smrg
1285c10afb9Smrg    if (verbose)
1295c10afb9Smrg	fprintf (stderr, "config file = %s\n", configFile);
1305c10afb9Smrg
1315c10afb9Smrg    /*
1325c10afb9Smrg     * Install an IO error handler.
1335c10afb9Smrg     */
1345c10afb9Smrg    InstallIOErrorHandler ();
1355c10afb9Smrg
1365c10afb9Smrg    /*
1375c10afb9Smrg     * Register support for PROXY_MANAGEMENT.
1385c10afb9Smrg     */
1395c10afb9Smrg
1405c10afb9Smrg    /* For Managed proxies, the proxy does the Setup */
1415c10afb9Smrg    if ((PMAcceptorOpcode = IceRegisterForProtocolReply (
1425c10afb9Smrg	PM_PROTOCOL_NAME, PM_VENDOR_STRING, PM_VENDOR_RELEASE,
1435c10afb9Smrg	PMversionCount, PMReplyVersions,
1445c10afb9Smrg	0, /* authcount */
1455c10afb9Smrg	NULL, /* authnames */
1465c10afb9Smrg        NULL, /* authprocs */
1475c10afb9Smrg        HostBasedAuthProc,
1485c10afb9Smrg	PMprotocolSetupProc,
1495c10afb9Smrg	NULL, /* protocolActivateProc */
1505c10afb9Smrg	NULL  /* IceIOErrorProc */ )) < 0)
1515c10afb9Smrg    {
1525c10afb9Smrg	fprintf (stderr,
1535c10afb9Smrg	    "Could not register PROXY_MANAGEMENT protocol reply with ICE");
1545c10afb9Smrg	exit (1);
1555c10afb9Smrg    }
1565c10afb9Smrg
1575c10afb9Smrg    /* For Unmanaged proxies, we do the Setup
1585c10afb9Smrg     * ICElib doesn't specify that the same opCode will be returned
1595c10afb9Smrg     * so don't bet on it.
1605c10afb9Smrg     */
1615c10afb9Smrg    if ((PMOriginatorOpcode = IceRegisterForProtocolSetup (
1625c10afb9Smrg	PM_PROTOCOL_NAME, PM_VENDOR_STRING, PM_VENDOR_RELEASE,
1635c10afb9Smrg	PMversionCount, PMSetupVersions,
1645c10afb9Smrg	0, /* authcount */
1655c10afb9Smrg	NULL, /* authnames */
1665c10afb9Smrg        NULL, /* authprocs */
1675c10afb9Smrg	NULL  /* IceIOErrorProc */ )) < 0)
1685c10afb9Smrg    {
1695c10afb9Smrg	fprintf (stderr,
1705c10afb9Smrg	    "Could not register PROXY_MANAGEMENT protocol setup with ICE");
1715c10afb9Smrg	exit (1);
1725c10afb9Smrg    }
1735c10afb9Smrg
1745c10afb9Smrg
1755c10afb9Smrg    if (!IceListenForWellKnownConnections (
1765c10afb9Smrg	PM_PORT, &numTransports, &listenObjs, 256, errormsg))
1775c10afb9Smrg    {
1785c10afb9Smrg	fprintf (stderr, "%s\n", errormsg);
1795c10afb9Smrg	exit (1);
1805c10afb9Smrg    }
1815c10afb9Smrg
1825c10afb9Smrg    networkIds = IceComposeNetworkIdList (numTransports, listenObjs);
1835c10afb9Smrg    p = (char *) malloc(sizeof ("PROXY_MANAGER") + strlen(networkIds) + 2);
1845c10afb9Smrg    sprintf (p, "PROXY_MANAGER=%s", networkIds);
1855c10afb9Smrg    putenv (p);
1865c10afb9Smrg    printf ("%s\n", p);
1875c10afb9Smrg    free (networkIds);
1885c10afb9Smrg
1895c10afb9Smrg    appContext = XtCreateApplicationContext ();
1905c10afb9Smrg
1915c10afb9Smrg    InitWatchProcs (appContext);
1925c10afb9Smrg
1935c10afb9Smrg    for (i = 0; i < numTransports; i++)
1945c10afb9Smrg    {
1955c10afb9Smrg	XtAppAddInput (appContext,
1965c10afb9Smrg	    IceGetListenConnectionNumber (listenObjs[i]),
1975c10afb9Smrg	    (XtPointer) XtInputReadMask,
1985c10afb9Smrg	    NewConnectionXtProc, (XtPointer) listenObjs[i]);
1995c10afb9Smrg
2005c10afb9Smrg	IceSetHostBasedAuthProc (listenObjs[i], HostBasedAuthProc);
2015c10afb9Smrg
2025c10afb9Smrg        SetCloseOnExec (IceGetListenConnectionNumber (listenObjs[i]));
2035c10afb9Smrg    }
2045c10afb9Smrg
2055c10afb9Smrg    /*
2065c10afb9Smrg     * Main loop
2075c10afb9Smrg     */
2085c10afb9Smrg    XtAppMainLoop (appContext);
2095c10afb9Smrg    exit (0);
2105c10afb9Smrg}
2115c10afb9Smrg
2125c10afb9Smrg
2135c10afb9Smrg/*
2145c10afb9Smrg * Xt callback invoked when a client attempts to connect.
2155c10afb9Smrg */
2165c10afb9Smrg
2175c10afb9Smrg/* ARGSUSED */
2185c10afb9Smrgvoid
2195c10afb9SmrgNewConnectionXtProc (client_data, source, id)
2205c10afb9Smrg
2215c10afb9SmrgXtPointer	client_data;
2225c10afb9Smrgint 		*source;
2235c10afb9SmrgXtInputId	*id;
2245c10afb9Smrg
2255c10afb9Smrg{
2265c10afb9Smrg    IceConn 	ice_conn;
2275c10afb9Smrg    char	*connstr;
2285c10afb9Smrg    IceAcceptStatus status;
2295c10afb9Smrg
2305c10afb9Smrg    ice_conn = IceAcceptConnection((IceListenObj) client_data, &status);
2315c10afb9Smrg    if (! ice_conn) {
2325c10afb9Smrg	if (verbose)
2335c10afb9Smrg	    printf ("IceAcceptConnection failed\n");
2345c10afb9Smrg    } else {
2355c10afb9Smrg	IceConnectStatus cstatus;
2365c10afb9Smrg
2375c10afb9Smrg        /*
2385c10afb9Smrg	 * Mark this fd to be closed upon exec
2395c10afb9Smrg	 */
2405c10afb9Smrg        SetCloseOnExec (IceConnectionNumber (ice_conn));
2415c10afb9Smrg
2425c10afb9Smrg	while ((cstatus = IceConnectionStatus (ice_conn))==IceConnectPending) {
2435c10afb9Smrg	    XtAppProcessEvent (appContext, XtIMAll);
2445c10afb9Smrg	}
2455c10afb9Smrg
2465c10afb9Smrg	if (cstatus == IceConnectAccepted) {
2475c10afb9Smrg	    if (verbose) {
2485c10afb9Smrg		printf ("ICE Connection opened by client, IceConn fd = %d, ",
2495c10afb9Smrg			IceConnectionNumber (ice_conn));
2505c10afb9Smrg		connstr = IceConnectionString (ice_conn);
2515c10afb9Smrg		printf ("Accept at networkId %s\n", connstr);
2525c10afb9Smrg		free (connstr);
2535c10afb9Smrg		printf ("\n");
2545c10afb9Smrg	    }
2555c10afb9Smrg	} else {
2565c10afb9Smrg	    if (verbose)
2575c10afb9Smrg	    {
2585c10afb9Smrg		if (cstatus == IceConnectIOError)
2595c10afb9Smrg		    printf ("IO error opening ICE Connection!\n");
2605c10afb9Smrg		else
2615c10afb9Smrg		    printf ("ICE Connection rejected!\n");
2625c10afb9Smrg	    }
2635c10afb9Smrg
2645c10afb9Smrg	    IceCloseConnection (ice_conn);
2655c10afb9Smrg	}
2665c10afb9Smrg    }
2675c10afb9Smrg}
2685c10afb9Smrg
2695c10afb9Smrg
2705c10afb9Smrg/*
2715c10afb9Smrg * See ConnectToProxy() if you change any of the pmConn structure
2725c10afb9Smrg */
2735c10afb9Smrgstatic Status
2745c10afb9SmrgPMprotocolSetupProc (iceConn,
2755c10afb9Smrg    majorVersion, minorVersion, vendor, release,
2765c10afb9Smrg    clientDataRet, failureReasonRet)
2775c10afb9Smrg
2785c10afb9SmrgIceConn    iceConn;
2795c10afb9Smrgint	   majorVersion;
2805c10afb9Smrgint	   minorVersion;
2815c10afb9Smrgchar  	   *vendor;
2825c10afb9Smrgchar 	   *release;
2835c10afb9SmrgIcePointer *clientDataRet;
2845c10afb9Smrgchar	   **failureReasonRet;
2855c10afb9Smrg
2865c10afb9Smrg{
2875c10afb9Smrg    /*
2885c10afb9Smrg     * Allocate new pmConn.
2895c10afb9Smrg     */
2905c10afb9Smrg
2915c10afb9Smrg    static char standardError[] = "Could not allocate memory for new client";
2925c10afb9Smrg    PMconn *pmConn;
2935c10afb9Smrg
2945c10afb9Smrg    if ((pmConn = (PMconn *) malloc (sizeof (PMconn))) == NULL)
2955c10afb9Smrg    {
2965c10afb9Smrg	if (verbose)
2975c10afb9Smrg	    fprintf (stderr, "%s\n", standardError);
2985c10afb9Smrg
2995c10afb9Smrg	*failureReasonRet = standardError;
3005c10afb9Smrg	return (0);
3015c10afb9Smrg    }
3025c10afb9Smrg
3035c10afb9Smrg    pmConn->iceConn = iceConn;
3045c10afb9Smrg    pmConn->pmOpcode = PMAcceptorOpcode;
3055c10afb9Smrg    pmConn->proto_major_version = majorVersion;
3065c10afb9Smrg    pmConn->proto_minor_version = minorVersion;
3075c10afb9Smrg    pmConn->vendor = vendor;
3085c10afb9Smrg    pmConn->release = release;
3095c10afb9Smrg
3105c10afb9Smrg    *clientDataRet = (IcePointer) pmConn;
3115c10afb9Smrg
3125c10afb9Smrg    return (1);
3135c10afb9Smrg}
3145c10afb9Smrg
3155c10afb9Smrg
3165c10afb9Smrgstatic void
3175c10afb9SmrgSendGetProxyAddr (
3185c10afb9Smrg    PMconn *pmConn,
3195c10afb9Smrg    char *serviceName,
3205c10afb9Smrg    char *serverAddress,
3215c10afb9Smrg    char *hostAddress,
3225c10afb9Smrg    char *startOptions,
3235c10afb9Smrg    int authLen,
3245c10afb9Smrg    char *authName,
3255c10afb9Smrg    char *authData)
3265c10afb9Smrg
3275c10afb9Smrg{
3285c10afb9Smrg    IceConn iceConn = pmConn->iceConn;
3295c10afb9Smrg    pmGetProxyAddrMsg *pMsg;
3305c10afb9Smrg    char *pData;
3315c10afb9Smrg    int len;
3325c10afb9Smrg
3335c10afb9Smrg    if (verbose) {
3345c10afb9Smrg	printf ("Sending GetProxyAddr to proxy %d, serviceName = %s, serverAddr = %s\n",
3355c10afb9Smrg		IceConnectionNumber(iceConn), serviceName, serverAddress);
3365c10afb9Smrg	printf ("  hostAddr = %s, options = %s, authLen = %d\n",
3375c10afb9Smrg		hostAddress ? hostAddress : "",
3385c10afb9Smrg		startOptions ? startOptions : "",
3395c10afb9Smrg		authLen);
3405c10afb9Smrg	if (authLen > 0)
3415c10afb9Smrg	    printf ("  authName = %s\n", authName);
3425c10afb9Smrg    }
3435c10afb9Smrg
3445c10afb9Smrg    len = STRING_BYTES (serviceName) +
3455c10afb9Smrg	  STRING_BYTES (serverAddress) +
3465c10afb9Smrg	  STRING_BYTES (hostAddress) +
3475c10afb9Smrg	  STRING_BYTES (startOptions) +
3485c10afb9Smrg	  (authLen > 0 ? (STRING_BYTES (authName) + authLen) : 0);
3495c10afb9Smrg
3505c10afb9Smrg    IceGetHeaderExtra (iceConn, pmConn->pmOpcode, PM_GetProxyAddr,
3515c10afb9Smrg	  SIZEOF (pmGetProxyAddrMsg), WORD64COUNT (len),
3525c10afb9Smrg	  pmGetProxyAddrMsg, pMsg, pData);
3535c10afb9Smrg
3545c10afb9Smrg    pMsg->authLen = authLen;
3555c10afb9Smrg
3565c10afb9Smrg    STORE_STRING (pData, serviceName);
3575c10afb9Smrg    STORE_STRING (pData, serverAddress);
3585c10afb9Smrg    STORE_STRING (pData, hostAddress);
3595c10afb9Smrg    STORE_STRING (pData, startOptions);
3605c10afb9Smrg    if (authLen > 0)
3615c10afb9Smrg    {
3625c10afb9Smrg	STORE_STRING (pData, authName);
3635c10afb9Smrg	memcpy (pData, authData, authLen);
3645c10afb9Smrg    }
3655c10afb9Smrg
3665c10afb9Smrg    IceFlush (iceConn);
3675c10afb9Smrg}
3685c10afb9Smrg
3695c10afb9Smrg
3705c10afb9Smrgvoid
3715c10afb9SmrgSendGetProxyAddrReply (
3725c10afb9Smrg    PMconn *requestor,
3735c10afb9Smrg    int status,
3745c10afb9Smrg    char *addr,
3755c10afb9Smrg    char *error)
3765c10afb9Smrg
3775c10afb9Smrg{
3785c10afb9Smrg    int len = STRING_BYTES (addr) + STRING_BYTES (error);
3795c10afb9Smrg    pmGetProxyAddrReplyMsg *pReply;
3805c10afb9Smrg    char *pData;
3815c10afb9Smrg
3825c10afb9Smrg    if (verbose) {
3835c10afb9Smrg	fputs ("Replying with ", stderr);
3845c10afb9Smrg	fputs (status == PM_Success ? "Success: " :
3855c10afb9Smrg	       status == PM_Failure ? "Failure: " :
3865c10afb9Smrg	       status == PM_Unable  ? "Unable: "  :
3875c10afb9Smrg	       "?unknown status", stderr);
3885c10afb9Smrg	fputs (status == PM_Success ? addr : error, stderr);
3895c10afb9Smrg	fputc ('\n', stderr);
3905c10afb9Smrg    }
3915c10afb9Smrg
3925c10afb9Smrg    IceGetHeaderExtra (requestor->iceConn,
3935c10afb9Smrg	requestor->pmOpcode, PM_GetProxyAddrReply,
3945c10afb9Smrg	SIZEOF (pmGetProxyAddrReplyMsg), WORD64COUNT (len),
3955c10afb9Smrg	pmGetProxyAddrReplyMsg, pReply, pData);
3965c10afb9Smrg
3975c10afb9Smrg    pReply->status = status;
3985c10afb9Smrg
3995c10afb9Smrg    STORE_STRING (pData, addr);
4005c10afb9Smrg    STORE_STRING (pData, error);
4015c10afb9Smrg
4025c10afb9Smrg    IceFlush (requestor->iceConn);
4035c10afb9Smrg}
4045c10afb9Smrg
4055c10afb9Smrg
4065c10afb9Smrg
4075c10afb9Smrgvoid
4085c10afb9SmrgPMReplyProcessMessages (iceConn, clientData, opcode, length, swap)
4095c10afb9Smrg
4105c10afb9SmrgIceConn		 iceConn;
4115c10afb9SmrgIcePointer       clientData;
4125c10afb9Smrgint		 opcode;
4135c10afb9Smrgunsigned long	 length;
4145c10afb9SmrgBool		 swap;
4155c10afb9Smrg
4165c10afb9Smrg{
4175c10afb9Smrg    PMconn *pmConn = (PMconn *) clientData;
4185c10afb9Smrg
4195c10afb9Smrg    assert(pmConn->iceConn == iceConn);
4205c10afb9Smrg
4215c10afb9Smrg    switch (opcode)
4225c10afb9Smrg    {
4235c10afb9Smrg    case PM_GetProxyAddr:
4245c10afb9Smrg    {
4255c10afb9Smrg	pmGetProxyAddrMsg 	*pMsg;
4265c10afb9Smrg	char 			*pData, *pStart;
4275c10afb9Smrg	char			*serviceName = NULL, *serverAddress = NULL;
4285c10afb9Smrg	char			*hostAddress = NULL, *startOptions = NULL;
4295c10afb9Smrg	char			*authName = NULL, *authData = NULL;
4305c10afb9Smrg	int			authLen;
4315c10afb9Smrg
4325c10afb9Smrg#if 0 /* No-op */
4335c10afb9Smrg	CHECK_AT_LEAST_SIZE (iceConn, pmConn->pmOpcode, opcode,
4345c10afb9Smrg	    length, SIZEOF (pmGetProxyAddrMsg), IceFatalToProtocol);
4355c10afb9Smrg#endif
4365c10afb9Smrg
4375c10afb9Smrg	IceReadCompleteMessage (iceConn, SIZEOF (pmGetProxyAddrMsg),
4385c10afb9Smrg	    pmGetProxyAddrMsg, pMsg, pStart);
4395c10afb9Smrg
4405c10afb9Smrg	if (!IceValidIO (iceConn))
4415c10afb9Smrg	{
4425c10afb9Smrg	    IceDisposeCompleteMessage (iceConn, pStart);
4435c10afb9Smrg	    return;
4445c10afb9Smrg	}
4455c10afb9Smrg
4465c10afb9Smrg	authLen = swap ? lswaps (pMsg->authLen) : pMsg->authLen;
4475c10afb9Smrg
4485c10afb9Smrg	pData = pStart;
4495c10afb9Smrg
4505c10afb9Smrg	SKIP_STRING (pData, swap);	/* proxy-service */
4515c10afb9Smrg	SKIP_STRING (pData, swap);	/* server-address */
4525c10afb9Smrg	SKIP_STRING (pData, swap);	/* host-address */
4535c10afb9Smrg	SKIP_STRING (pData, swap);	/* start-options */
4545c10afb9Smrg	if (authLen > 0)
4555c10afb9Smrg	{
4565c10afb9Smrg	    SKIP_STRING (pData, swap);		    /* auth-name */
4575c10afb9Smrg	    pData += (authLen +  PAD64 (authLen));  /* auth-data */
4585c10afb9Smrg	}
4595c10afb9Smrg
4605c10afb9Smrg	CHECK_COMPLETE_SIZE (iceConn, pmConn->pmOpcode, opcode,
4615c10afb9Smrg	   length, pData - pStart + SIZEOF (pmGetProxyAddrMsg),
4625c10afb9Smrg	   pStart, IceFatalToProtocol);
4635c10afb9Smrg
4645c10afb9Smrg	pData = pStart;
4655c10afb9Smrg
4665c10afb9Smrg	EXTRACT_STRING (pData, swap, serviceName);
4675c10afb9Smrg	EXTRACT_STRING (pData, swap, serverAddress);
4685c10afb9Smrg	EXTRACT_STRING (pData, swap, hostAddress);
4695c10afb9Smrg	EXTRACT_STRING (pData, swap, startOptions);
4705c10afb9Smrg	if (authLen > 0)
4715c10afb9Smrg	{
4725c10afb9Smrg	    EXTRACT_STRING (pData, swap, authName);
4735c10afb9Smrg	    authData = (char *) malloc (authLen);
4745c10afb9Smrg	    memcpy (authData, pData, authLen);
4755c10afb9Smrg	}
4765c10afb9Smrg
4775c10afb9Smrg	if (serverAddress)
4785c10afb9Smrg	{
4795c10afb9Smrg	    /*
4805c10afb9Smrg	     * Assume that if serverAddress is something like :0 or :0.0
4815c10afb9Smrg	     * then the request is for a server on the client's host.
4825c10afb9Smrg	     *
4835c10afb9Smrg	     * However, the proxy handling this request may be on a
4845c10afb9Smrg	     * different host than the client or the client host,
4855c10afb9Smrg	     * proxy host and the server host may all be different,
4865c10afb9Smrg	     * thus a serverAddress of :0 or :0.0 is not useful.
4875c10afb9Smrg	     * Therefore, change serverAddress to use the client's
4885c10afb9Smrg	     * hostname.
4895c10afb9Smrg	     */
4905c10afb9Smrg	    char		*tmpName;
4915c10afb9Smrg
4925c10afb9Smrg	    tmpName = strrchr (serverAddress, ':');
4935c10afb9Smrg
4945c10afb9Smrg	    if (tmpName && ((tmpName == serverAddress) ||
4955c10afb9Smrg			    (!strncmp (serverAddress, "unix:", 5))))
4965c10afb9Smrg	    {
4975c10afb9Smrg#if defined(IPv6) && defined(AF_INET6)
4985c10afb9Smrg		struct sockaddr_storage	serverSock;
4995c10afb9Smrg#else
5005c10afb9Smrg		struct sockaddr_in	serverSock;
5015c10afb9Smrg#endif
5025c10afb9Smrg		int 			retVal;
5035c10afb9Smrg		int 			addrLen = sizeof(serverSock);
5045c10afb9Smrg
5055c10afb9Smrg		retVal = getpeername(IceConnectionNumber(iceConn),
5065c10afb9Smrg				     (struct sockaddr *) &serverSock,
5075c10afb9Smrg				     (void *) &addrLen);
5085c10afb9Smrg		if (!retVal)
5095c10afb9Smrg		{
5105c10afb9Smrg		    char *canonname = NULL;
5115c10afb9Smrg#if defined(IPv6) && defined(AF_INET6)
5125c10afb9Smrg		    char hostname[NI_MAXHOST];
5135c10afb9Smrg		    struct addrinfo *ai = NULL, hints;
5145c10afb9Smrg
5155c10afb9Smrg		    if (getnameinfo((struct sockaddr *) &serverSock,
5165c10afb9Smrg		      addrLen, hostname, sizeof(hostname), NULL, 0, 0) == 0) {
5175c10afb9Smrg			(void)memset(&hints, 0, sizeof(hints));
5185c10afb9Smrg			hints.ai_flags = AI_CANONNAME;
5195c10afb9Smrg			if (getaddrinfo(hostname, NULL, &hints, &ai) == 0) {
5205c10afb9Smrg			    canonname = ai->ai_canonname;
5215c10afb9Smrg			} else {
5225c10afb9Smrg			    ai = NULL;
5235c10afb9Smrg			}
5245c10afb9Smrg		    }
5255c10afb9Smrg#else
5265c10afb9Smrg		    struct hostent *hostent;
5275c10afb9Smrg
5285c10afb9Smrg		    hostent = gethostbyname (inet_ntoa(serverSock.sin_addr));
5295c10afb9Smrg
5305c10afb9Smrg		    if (hostent && hostent->h_name)
5315c10afb9Smrg			canonname = hostent->h_name;
5325c10afb9Smrg#endif
5335c10afb9Smrg		    if (canonname)
5345c10afb9Smrg		    {
5355c10afb9Smrg			int		len;
5365c10afb9Smrg			char		* pch = strdup (tmpName);
5375c10afb9Smrg
5385c10afb9Smrg			len = strlen(canonname) + strlen(tmpName) + 1;
5395c10afb9Smrg			serverAddress = (char *) realloc (serverAddress, len);
5405c10afb9Smrg			sprintf (serverAddress, "%s%s", canonname, pch);
5415c10afb9Smrg			free (pch);
5425c10afb9Smrg		    }
5435c10afb9Smrg#if defined(IPv6) && defined(AF_INET6)
5445c10afb9Smrg		    if (ai != NULL)
5455c10afb9Smrg			freeaddrinfo(ai);
5465c10afb9Smrg#endif
5475c10afb9Smrg		}
5485c10afb9Smrg	    }
5495c10afb9Smrg	}
5505c10afb9Smrg
5515c10afb9Smrg	if (verbose) {
5525c10afb9Smrg	    printf ("Got GetProxyAddr, serviceName = %s, serverAddr = %s\n",
5535c10afb9Smrg		    serviceName, serverAddress);
5545c10afb9Smrg	    printf ("  hostAddr = %s, options = %s, authLen = %d\n",
5555c10afb9Smrg		    hostAddress, startOptions, authLen);
5565c10afb9Smrg	    if (authLen > 0)
5575c10afb9Smrg		printf ("  authName = %s\n", authName);
5585c10afb9Smrg	}
5595c10afb9Smrg
5605c10afb9Smrg	IceDisposeCompleteMessage (iceConn, pStart);
5615c10afb9Smrg
5625c10afb9Smrg	ForwardRequest (pmConn, serviceName, serverAddress, hostAddress,
5635c10afb9Smrg			startOptions, authLen, authName, authData);
5645c10afb9Smrg
5655c10afb9Smrg	if (serviceName)
5665c10afb9Smrg	    free (serviceName);
5675c10afb9Smrg	if (serverAddress)
5685c10afb9Smrg	    free (serverAddress);
5695c10afb9Smrg	if (hostAddress)
5705c10afb9Smrg	    free (hostAddress);
5715c10afb9Smrg	if (startOptions)
5725c10afb9Smrg	    free (startOptions);
5735c10afb9Smrg	if (authName)
5745c10afb9Smrg	    free (authName);
5755c10afb9Smrg	if (authData)
5765c10afb9Smrg	    free (authData);
5775c10afb9Smrg
5785c10afb9Smrg	break;
5795c10afb9Smrg    }
5805c10afb9Smrg
5815c10afb9Smrg    case PM_StartProxy:
5825c10afb9Smrg    {
5835c10afb9Smrg	pmStartProxyMsg *pMsg;
5845c10afb9Smrg	char 		*pData, *pStart;
5855c10afb9Smrg	char		*serviceName = NULL;
5865c10afb9Smrg	char		*serverAddress;
5875c10afb9Smrg	char		*hostAddress;
5885c10afb9Smrg	char		*startOptions;
5895c10afb9Smrg	int		authLen;
5905c10afb9Smrg	char		*authName;
5915c10afb9Smrg	char		*authData;
5925c10afb9Smrg
5935c10afb9Smrg#if 0 /* No-op */
5945c10afb9Smrg	CHECK_AT_LEAST_SIZE (iceConn, pmConn->pmOpcode, opcode,
5955c10afb9Smrg	    length, SIZEOF (pmStartProxyMsg), IceFatalToProtocol);
5965c10afb9Smrg#endif
5975c10afb9Smrg
5985c10afb9Smrg	IceReadCompleteMessage (iceConn, SIZEOF (pmStartProxyMsg),
5995c10afb9Smrg	    pmStartProxyMsg, pMsg, pStart);
6005c10afb9Smrg
6015c10afb9Smrg	if (!IceValidIO (iceConn))
6025c10afb9Smrg	{
6035c10afb9Smrg	    IceDisposeCompleteMessage (iceConn, pStart);
6045c10afb9Smrg	    return;
6055c10afb9Smrg	}
6065c10afb9Smrg
6075c10afb9Smrg	pData = pStart;
6085c10afb9Smrg
6095c10afb9Smrg	SKIP_STRING (pData, swap);	/* proxy-service */
6105c10afb9Smrg
6115c10afb9Smrg	CHECK_COMPLETE_SIZE (iceConn, pmConn->pmOpcode, opcode,
6125c10afb9Smrg	   length, pData - pStart + SIZEOF (pmStartProxyMsg),
6135c10afb9Smrg	   pStart, IceFatalToProtocol);
6145c10afb9Smrg
6155c10afb9Smrg	pData = pStart;
6165c10afb9Smrg
6175c10afb9Smrg	EXTRACT_STRING (pData, swap, serviceName);
6185c10afb9Smrg
6195c10afb9Smrg	assert(serviceName);
6205c10afb9Smrg
6215c10afb9Smrg	if (verbose)
6225c10afb9Smrg	    printf ("Got StartProxy on fd %d, serviceName = %s\n",
6235c10afb9Smrg		    IceConnectionNumber(iceConn), serviceName);
6245c10afb9Smrg
6255c10afb9Smrg	IceDisposeCompleteMessage (iceConn, pStart);
6265c10afb9Smrg
6275c10afb9Smrg	if (! ActivateProxyService (serviceName, pmConn)) {
6285c10afb9Smrg	    fputs ("Configuration error: received unexpected StartProxy for service ", stderr);
6295c10afb9Smrg	    fputs (serviceName, stderr);
6305c10afb9Smrg	    fputc ('\n', stderr);
6315c10afb9Smrg	    IceCloseConnection (iceConn);
6325c10afb9Smrg	}
6335c10afb9Smrg	else {
6345c10afb9Smrg
6355c10afb9Smrg	    /*
6365c10afb9Smrg	     * Now send the GetProxyAddr message to the proxy.
6375c10afb9Smrg	     */
6385c10afb9Smrg	    if (PeekRequestorQueue(pmConn,
6395c10afb9Smrg				   NULL, NULL, NULL,
6405c10afb9Smrg				   &serverAddress, &hostAddress, &startOptions,
6415c10afb9Smrg				   &authLen, &authName, &authData)) {
6425c10afb9Smrg		SendGetProxyAddr(pmConn,
6435c10afb9Smrg				 serviceName, serverAddress,
6445c10afb9Smrg				 hostAddress, startOptions,
6455c10afb9Smrg				 authLen, authName, authData);
6465c10afb9Smrg	    }
6475c10afb9Smrg	    else if (verbose) {
6485c10afb9Smrg		    fputs ("Received StartProxy for service ", stderr);
6495c10afb9Smrg		    fputs (serviceName, stderr);
6505c10afb9Smrg		    fputs (" but no waiting GetproxyAddr requests\n", stderr);
6515c10afb9Smrg	    }
6525c10afb9Smrg	}
6535c10afb9Smrg
6545c10afb9Smrg	free (serviceName);
6555c10afb9Smrg
6565c10afb9Smrg	break;
6575c10afb9Smrg    }
6585c10afb9Smrg
6595c10afb9Smrg    case PM_GetProxyAddrReply:
6605c10afb9Smrg
6615c10afb9Smrg    {
6625c10afb9Smrg	pmGetProxyAddrReplyMsg 	*pMsg;
6635c10afb9Smrg	char			*pData, *pStart;
6645c10afb9Smrg	char			*addr = NULL, *error = NULL;
6655c10afb9Smrg
6665c10afb9Smrg#if 0 /* No-op */
6675c10afb9Smrg	CHECK_AT_LEAST_SIZE (iceConn, pmConn->pmOpcode, opcode,
6685c10afb9Smrg	    length, SIZEOF (pmGetProxyAddrReplyMsg), IceFatalToProtocol);
6695c10afb9Smrg#endif
6705c10afb9Smrg
6715c10afb9Smrg	IceReadCompleteMessage (iceConn, SIZEOF (pmGetProxyAddrReplyMsg),
6725c10afb9Smrg	    pmGetProxyAddrReplyMsg, pMsg, pStart);
6735c10afb9Smrg
6745c10afb9Smrg	if (!IceValidIO (iceConn))
6755c10afb9Smrg	{
6765c10afb9Smrg	    IceDisposeCompleteMessage (iceConn, pStart);
6775c10afb9Smrg	    return;
6785c10afb9Smrg	}
6795c10afb9Smrg
6805c10afb9Smrg	pData = pStart;
6815c10afb9Smrg
6825c10afb9Smrg	SKIP_STRING (pData, swap);		/* proxy-address */
6835c10afb9Smrg	SKIP_STRING (pData, swap);		/* failure-reason */
6845c10afb9Smrg
6855c10afb9Smrg	CHECK_COMPLETE_SIZE (iceConn, pmConn->pmOpcode, opcode,
6865c10afb9Smrg	    length, pData - pStart + SIZEOF (pmGetProxyAddrReplyMsg),
6875c10afb9Smrg	    pStart, IceFatalToProtocol);
6885c10afb9Smrg
6895c10afb9Smrg	pData = pStart;
6905c10afb9Smrg
6915c10afb9Smrg	EXTRACT_STRING (pData, swap, addr);
6925c10afb9Smrg	EXTRACT_STRING (pData, swap, error);
6935c10afb9Smrg
6945c10afb9Smrg	if (verbose) {
6955c10afb9Smrg	    printf ("Got GetProxyAddrReply from proxy %d, status = %d, ",
6965c10afb9Smrg		    IceConnectionNumber(iceConn), pMsg->status);
6975c10afb9Smrg	    if (pMsg->status == PM_Success)
6985c10afb9Smrg		printf ("addr = %s\n", addr);
6995c10afb9Smrg	    else
7005c10afb9Smrg		printf ("error = %s\n", error);
7015c10afb9Smrg	}
7025c10afb9Smrg
7035c10afb9Smrg	{ /* Ignore any unsolicited replies so we don't get further confused */
7045c10afb9Smrg	    running_proxy *proxy = ProxyForPMconn(pmConn);
7055c10afb9Smrg
7065c10afb9Smrg	    if (!proxy || !proxy->requests)
7075c10afb9Smrg	    {
7085c10afb9Smrg		if (verbose)
7095c10afb9Smrg		    fprintf (stderr, "Received unsolicited GetProxyAddrReply from proxy %d; ignoring it.\n",
7105c10afb9Smrg			     IceConnectionNumber(iceConn));
7115c10afb9Smrg
7125c10afb9Smrg		IceDisposeCompleteMessage (iceConn, pStart);
7135c10afb9Smrg		break;
7145c10afb9Smrg	    }
7155c10afb9Smrg	}
7165c10afb9Smrg
7175c10afb9Smrg	switch (pMsg->status) {
7185c10afb9Smrg
7195c10afb9Smrg	case PM_Success:
7205c10afb9Smrg	{
7215c10afb9Smrg	    /*
7225c10afb9Smrg	     * Now send the GetProxyAddr reply to xfindproxy.
7235c10afb9Smrg	     */
7245c10afb9Smrg
7255c10afb9Smrg	    SendGetProxyAddrReply (
7265c10afb9Smrg		PopRequestorQueue (pmConn, True, True /* free proxy list */),
7275c10afb9Smrg		PM_Success /* status */, addr, NULL);
7285c10afb9Smrg
7295c10afb9Smrg	    break;
7305c10afb9Smrg	}
7315c10afb9Smrg
7325c10afb9Smrg	case PM_Unable:
7335c10afb9Smrg	{
7345c10afb9Smrg	    running_proxy_list *proxyList;
7355c10afb9Smrg	    char *serviceName, *serverAddress, *hostAddress, *startOptions;
7365c10afb9Smrg	    PMconn *requestor;
7375c10afb9Smrg	    int authLen;
7385c10afb9Smrg	    char *authName;
7395c10afb9Smrg	    char *authData;
7405c10afb9Smrg
7415c10afb9Smrg	    {
7425c10afb9Smrg		running_proxy *proxy = ProxyForPMconn(pmConn);
7435c10afb9Smrg		if (proxy)
7445c10afb9Smrg		    proxy->refused_service = True;
7455c10afb9Smrg		else
7465c10afb9Smrg		    fputs("Internal error: received GetProxyAddrReply from an unknown proxy\n", stderr);
7475c10afb9Smrg	    }
7485c10afb9Smrg
7495c10afb9Smrg	    if (! PeekRequestorQueue (pmConn, &requestor,
7505c10afb9Smrg				      &proxyList, &serviceName, &serverAddress,
7515c10afb9Smrg				      &hostAddress, &startOptions,
7525c10afb9Smrg				      &authLen, &authName, &authData)) {
7535c10afb9Smrg		if (verbose)
7545c10afb9Smrg		    fputs("Received GetProxyAddrReply from a proxy with no requests\n", stderr);
7555c10afb9Smrg
7565c10afb9Smrg		proxyList = NULL;
7575c10afb9Smrg		serviceName = "?unknown service--internal error";
7585c10afb9Smrg	    }
7595c10afb9Smrg
7605c10afb9Smrg	    if (proxyList && (proxyList->current < proxyList->count - 1))
7615c10afb9Smrg	    {
7625c10afb9Smrg		/*
7635c10afb9Smrg		 * Ask the next running proxy if it can service this request.
7645c10afb9Smrg		 */
7655c10afb9Smrg		running_proxy *nextProxy;
7665c10afb9Smrg
7675c10afb9Smrg		proxyList->current++;
7685c10afb9Smrg		nextProxy = proxyList->list[proxyList->current];
7695c10afb9Smrg
7705c10afb9Smrg		if (nextProxy->pmConn != NULL) {
7715c10afb9Smrg		    /* send only if the proxy has started */
7725c10afb9Smrg		    SendGetProxyAddr (nextProxy->pmConn, serviceName,
7735c10afb9Smrg				      serverAddress, hostAddress, startOptions,
7745c10afb9Smrg				      authLen, authName, authData);
7755c10afb9Smrg		}
7765c10afb9Smrg
7775c10afb9Smrg		PushRequestorQueue (nextProxy, requestor, proxyList,
7785c10afb9Smrg	            serviceName, serverAddress, hostAddress, startOptions,
7795c10afb9Smrg		    authLen, authName, authData);
7805c10afb9Smrg
7815c10afb9Smrg		PopRequestorQueue (pmConn, False, False);
7825c10afb9Smrg	    }
7835c10afb9Smrg	    else
7845c10afb9Smrg	    {
7855c10afb9Smrg		/*
7865c10afb9Smrg		 * Start a new proxy.
7875c10afb9Smrg		 */
7885c10afb9Smrg
7895c10afb9Smrg		running_proxy *runningProxy = NULL;
7905c10afb9Smrg		char *startCommand;
7915c10afb9Smrg		char *proxyAddress;
7925c10afb9Smrg		Bool managed;
7935c10afb9Smrg
7945c10afb9Smrg		if (!GetConfig (configFile, serviceName, &managed,
7955c10afb9Smrg	            &startCommand, &proxyAddress))
7965c10afb9Smrg		{
7975c10afb9Smrg		    SendGetProxyAddrReply (requestor, PM_Failure,
7985c10afb9Smrg		        NULL, "Could not read proxy manager config file");
7995c10afb9Smrg		}
8005c10afb9Smrg		else
8015c10afb9Smrg		{
8025c10afb9Smrg		    runningProxy = StartNewProxy (serviceName, startCommand);
8035c10afb9Smrg
8045c10afb9Smrg		    if (runningProxy)
8055c10afb9Smrg		    {
8065c10afb9Smrg			PushRequestorQueue (runningProxy,
8075c10afb9Smrg			    requestor, proxyList,
8085c10afb9Smrg			    serviceName, serverAddress,
8095c10afb9Smrg			    hostAddress, startOptions,
8105c10afb9Smrg			    authLen, authName, authData);
8115c10afb9Smrg		    }
8125c10afb9Smrg		    else
8135c10afb9Smrg		    {
8145c10afb9Smrg			SendGetProxyAddrReply (pmConn, PM_Failure,
8155c10afb9Smrg		            NULL, "Can't start new proxy");
8165c10afb9Smrg		    }
8175c10afb9Smrg		}
8185c10afb9Smrg
8195c10afb9Smrg		if (startCommand)
8205c10afb9Smrg		    free (startCommand);
8215c10afb9Smrg		if (proxyAddress)
8225c10afb9Smrg		    free (proxyAddress);
8235c10afb9Smrg
8245c10afb9Smrg		PopRequestorQueue (pmConn, False,
8255c10afb9Smrg		    runningProxy ? False : True /* free proxy list */);
8265c10afb9Smrg	    }
8275c10afb9Smrg	    break;
8285c10afb9Smrg	}
8295c10afb9Smrg
8305c10afb9Smrg	default:
8315c10afb9Smrg	    if (verbose && pMsg->status != PM_Unable)
8325c10afb9Smrg		fprintf(stderr,
8335c10afb9Smrg			"Error: proxy returned unrecognized status: %d\n",
8345c10afb9Smrg			pMsg->status);
8355c10afb9Smrg	    /* FALLTHROUGH */
8365c10afb9Smrg
8375c10afb9Smrg	case PM_Failure:
8385c10afb9Smrg	    SendGetProxyAddrReply (
8395c10afb9Smrg		PopRequestorQueue (pmConn, True, True /* free proxy list */),
8405c10afb9Smrg		pMsg->status, NULL, error);
8415c10afb9Smrg	}
8425c10afb9Smrg
8435c10afb9Smrg	IceDisposeCompleteMessage (iceConn, pStart);
8445c10afb9Smrg
8455c10afb9Smrg	/* see if there was more work queued for this proxy */
8465c10afb9Smrg	{
8475c10afb9Smrg	    char *serviceName, *serverAddress, *hostAddress, *startOptions;
8485c10afb9Smrg	    int authLen;
8495c10afb9Smrg	    char *authName, *authData;
8505c10afb9Smrg
8515c10afb9Smrg	    if (PeekRequestorQueue(pmConn,
8525c10afb9Smrg				   NULL, NULL, &serviceName,
8535c10afb9Smrg				   &serverAddress, &hostAddress, &startOptions,
8545c10afb9Smrg				   &authLen, &authName, &authData)) {
8555c10afb9Smrg		SendGetProxyAddr(pmConn,
8565c10afb9Smrg				 serviceName, serverAddress,
8575c10afb9Smrg				 hostAddress, startOptions,
8585c10afb9Smrg				 authLen, authName, authData);
8595c10afb9Smrg	    }
8605c10afb9Smrg	}
8615c10afb9Smrg
8625c10afb9Smrg	if (addr)
8635c10afb9Smrg	    free (addr);
8645c10afb9Smrg	if (error)
8655c10afb9Smrg	    free (error);
8665c10afb9Smrg
8675c10afb9Smrg	break;
8685c10afb9Smrg    }
8695c10afb9Smrg
8705c10afb9Smrg    case PM_Error:
8715c10afb9Smrg    {
8725c10afb9Smrg	iceErrorMsg *pMsg;
8735c10afb9Smrg	char *pStart;
8745c10afb9Smrg
8755c10afb9Smrg	CHECK_AT_LEAST_SIZE (iceConn, pmConn->pmOpcode, PM_Error, length,
8765c10afb9Smrg			     sizeof(iceErrorMsg), IceFatalToProtocol);
8775c10afb9Smrg
8785c10afb9Smrg	IceReadCompleteMessage (iceConn, SIZEOF (iceErrorMsg),
8795c10afb9Smrg				iceErrorMsg, pMsg, pStart);
8805c10afb9Smrg
8815c10afb9Smrg	if (!IceValidIO (iceConn))
8825c10afb9Smrg	{
8835c10afb9Smrg	    IceDisposeCompleteMessage (iceConn, pStart);
8845c10afb9Smrg	    return;
8855c10afb9Smrg	}
8865c10afb9Smrg
8875c10afb9Smrg	if (swap)
8885c10afb9Smrg	{
8895c10afb9Smrg	    pMsg->errorClass = lswaps (pMsg->errorClass);
8905c10afb9Smrg	    pMsg->offendingSequenceNum = lswapl (pMsg->offendingSequenceNum);
8915c10afb9Smrg	}
8925c10afb9Smrg
8935c10afb9Smrg	fprintf(stderr, "Received ICE Error: class=0x%x\n  offending minor opcode=%d, severity=%d, sequence=%d\n",
8945c10afb9Smrg		pMsg->errorClass, pMsg->offendingMinorOpcode, pMsg->severity,
8955c10afb9Smrg		(int)pMsg->offendingSequenceNum);
8965c10afb9Smrg
8975c10afb9Smrg	IceDisposeCompleteMessage (iceConn, pStart);
8985c10afb9Smrg
8995c10afb9Smrg	break;
9005c10afb9Smrg    }
9015c10afb9Smrg
9025c10afb9Smrg    default:
9035c10afb9Smrg    {
9045c10afb9Smrg	_IceErrorBadMinor (iceConn, pmConn->pmOpcode, opcode, IceCanContinue);
9055c10afb9Smrg	_IceReadSkip (iceConn, length << 3);
9065c10afb9Smrg	break;
9075c10afb9Smrg    }
9085c10afb9Smrg    }
9095c10afb9Smrg}
9105c10afb9Smrg
9115c10afb9Smrgvoid
9125c10afb9SmrgPMSetupProcessMessages (iceConn, clientData, opcode, length, swap,
9135c10afb9Smrg			replyWait, replyReadyRet)
9145c10afb9Smrg
9155c10afb9SmrgIceConn		 iceConn;
9165c10afb9SmrgIcePointer       clientData;
9175c10afb9Smrgint		 opcode;
9185c10afb9Smrgunsigned long	 length;
9195c10afb9SmrgBool		 swap;
9205c10afb9SmrgIceReplyWaitInfo *replyWait;
9215c10afb9SmrgBool		 *replyReadyRet;
9225c10afb9Smrg
9235c10afb9Smrg{
9245c10afb9Smrg    assert (replyWait == NULL);
9255c10afb9Smrg
9265c10afb9Smrg    PMReplyProcessMessages (iceConn, clientData, opcode, length, swap);
9275c10afb9Smrg}
9285c10afb9Smrg
9295c10afb9Smrg
9305c10afb9Smrgvoid
9315c10afb9SmrgForwardRequest( requestor, serviceName, serverAddress, hostAddress,
9325c10afb9Smrg		startOptions, authLen, authName, authData )
9335c10afb9Smrg    PMconn *requestor;
9345c10afb9Smrg    char *serviceName, *serverAddress, *hostAddress, *startOptions;
9355c10afb9Smrg    int authLen;
9365c10afb9Smrg    char *authName, *authData;
9375c10afb9Smrg{
9385c10afb9Smrg    running_proxy_list	*proxyList;
9395c10afb9Smrg    running_proxy	*runningProxy = NULL;
9405c10afb9Smrg    int			pushRequest = 0;
9415c10afb9Smrg
9425c10afb9Smrg    if ((proxyList = GetRunningProxyList (
9435c10afb9Smrg	serviceName, serverAddress)) != NULL)
9445c10afb9Smrg    {
9455c10afb9Smrg	while (proxyList->current < proxyList->count) {
9465c10afb9Smrg	    runningProxy = proxyList->list[proxyList->current];
9475c10afb9Smrg
9485c10afb9Smrg	    if (runningProxy->pmConn != NULL) {
9495c10afb9Smrg		SendGetProxyAddr (runningProxy->pmConn, serviceName,
9505c10afb9Smrg				  serverAddress, hostAddress, NULL,
9515c10afb9Smrg				  authLen, authName, authData);
9525c10afb9Smrg		break;
9535c10afb9Smrg	    }
9545c10afb9Smrg	    proxyList->current++;
9555c10afb9Smrg	}
9565c10afb9Smrg
9575c10afb9Smrg	pushRequest = 1;
9585c10afb9Smrg    }
9595c10afb9Smrg    else
9605c10afb9Smrg    {
9615c10afb9Smrg	Bool managed;
9625c10afb9Smrg	char *startCommand;
9635c10afb9Smrg	char *proxyAddress;
9645c10afb9Smrg
9655c10afb9Smrg	if (!GetConfig (configFile, serviceName, &managed,
9665c10afb9Smrg	    &startCommand, &proxyAddress))
9675c10afb9Smrg	{
9685c10afb9Smrg	    SendGetProxyAddrReply (requestor, PM_Failure,
9695c10afb9Smrg		NULL, "Could not find requested service");
9705c10afb9Smrg	}
9715c10afb9Smrg	else
9725c10afb9Smrg	{
9735c10afb9Smrg	    if (managed)
9745c10afb9Smrg	    {
9755c10afb9Smrg		runningProxy = StartNewProxy (serviceName, startCommand);
9765c10afb9Smrg
9775c10afb9Smrg		if (runningProxy)
9785c10afb9Smrg		    pushRequest = 1;
9795c10afb9Smrg		else
9805c10afb9Smrg		{
9815c10afb9Smrg		    SendGetProxyAddrReply (requestor, PM_Failure,
9825c10afb9Smrg			NULL, "Can't start new proxy");
9835c10afb9Smrg		}
9845c10afb9Smrg	    }
9855c10afb9Smrg	    else
9865c10afb9Smrg	    {
9875c10afb9Smrg		/*
9885c10afb9Smrg		 * We have the unmanged proxy's address; now forward
9895c10afb9Smrg		 * the request to it.
9905c10afb9Smrg		 */
9915c10afb9Smrg
9925c10afb9Smrg		runningProxy = ConnectToProxy (PMOriginatorOpcode,
9935c10afb9Smrg					       serviceName, proxyAddress);
9945c10afb9Smrg
9955c10afb9Smrg		if (runningProxy) {
9965c10afb9Smrg		    SendGetProxyAddr (runningProxy->pmConn,
9975c10afb9Smrg				      serviceName, serverAddress,
9985c10afb9Smrg				      hostAddress, startOptions,
9995c10afb9Smrg				      authLen, authName, authData);
10005c10afb9Smrg		    pushRequest = 1;
10015c10afb9Smrg		}
10025c10afb9Smrg		else
10035c10afb9Smrg		{
10045c10afb9Smrg		    /* %%% We should reread the config file and look
10055c10afb9Smrg		     * for another proxy address before giving up.
10065c10afb9Smrg		     */
10075c10afb9Smrg		    SendGetProxyAddrReply (requestor, PM_Failure,
10085c10afb9Smrg			NULL, "Can't connect to proxy");
10095c10afb9Smrg		}
10105c10afb9Smrg	    }
10115c10afb9Smrg
10125c10afb9Smrg	    if (startCommand)
10135c10afb9Smrg		free (startCommand);
10145c10afb9Smrg	    if (proxyAddress)
10155c10afb9Smrg		free (proxyAddress);
10165c10afb9Smrg	}
10175c10afb9Smrg    }
10185c10afb9Smrg
10195c10afb9Smrg    if (pushRequest)
10205c10afb9Smrg    {
10215c10afb9Smrg	PushRequestorQueue (runningProxy, requestor, proxyList,
10225c10afb9Smrg	    serviceName, serverAddress, hostAddress, startOptions,
10235c10afb9Smrg	    authLen, authName, authData);
10245c10afb9Smrg    }
10255c10afb9Smrg}
10265c10afb9Smrg
10275c10afb9Smrg
10285c10afb9Smrg/* ARGSUSED */
10295c10afb9Smrgvoid
10305c10afb9Smrg_XtProcessIceMsgProc (client_data, source, id)
10315c10afb9Smrg
10325c10afb9SmrgXtPointer	client_data;
10335c10afb9Smrgint 		*source;
10345c10afb9SmrgXtInputId	*id;
10355c10afb9Smrg
10365c10afb9Smrg{
10375c10afb9Smrg    IceConn			ice_conn = (IceConn) client_data;
10385c10afb9Smrg    IceProcessMessagesStatus	status;
10395c10afb9Smrg
10405c10afb9Smrg    status = IceProcessMessages (ice_conn, NULL, NULL);
10415c10afb9Smrg
10425c10afb9Smrg    if (status == IceProcessMessagesIOError)
10435c10afb9Smrg    {
10445c10afb9Smrg	Bool activeReqs;
10455c10afb9Smrg
10465c10afb9Smrg	ProxyGone (ice_conn, &activeReqs);
10475c10afb9Smrg	IceSetShutdownNegotiation (ice_conn, False);
10485c10afb9Smrg	IceCloseConnection (ice_conn);
10495c10afb9Smrg    }
10505c10afb9Smrg}
10515c10afb9Smrg
10525c10afb9Smrg
10535c10afb9Smrgvoid
10545c10afb9Smrg_XtIceWatchProc (ice_conn, client_data, opening, watch_data)
10555c10afb9Smrg
10565c10afb9SmrgIceConn 	ice_conn;
10575c10afb9SmrgIcePointer	client_data;
10585c10afb9SmrgBool		opening;
10595c10afb9SmrgIcePointer	*watch_data;
10605c10afb9Smrg
10615c10afb9Smrg{
10625c10afb9Smrg    if (opening)
10635c10afb9Smrg    {
10645c10afb9Smrg	XtAppContext appContext = (XtAppContext) client_data;
10655c10afb9Smrg
10665c10afb9Smrg	*watch_data = (IcePointer) XtAppAddInput (
10675c10afb9Smrg	    appContext,
10685c10afb9Smrg	    IceConnectionNumber (ice_conn),
10695c10afb9Smrg            (XtPointer) XtInputReadMask,
10705c10afb9Smrg	    _XtProcessIceMsgProc,
10715c10afb9Smrg	    (XtPointer) ice_conn);
10725c10afb9Smrg    }
10735c10afb9Smrg    else
10745c10afb9Smrg    {
10755c10afb9Smrg	XtRemoveInput ((XtInputId) *watch_data);
10765c10afb9Smrg    }
10775c10afb9Smrg}
10785c10afb9Smrg
10795c10afb9Smrg
10805c10afb9SmrgStatus
10815c10afb9SmrgInitWatchProcs (appContext)
10825c10afb9Smrg
10835c10afb9SmrgXtAppContext appContext;
10845c10afb9Smrg
10855c10afb9Smrg{
10865c10afb9Smrg    return (IceAddConnectionWatch (_XtIceWatchProc, (IcePointer) appContext));
10875c10afb9Smrg}
10885c10afb9Smrg
10895c10afb9Smrg
10905c10afb9Smrg/*
10915c10afb9Smrg * The real way to handle IO errors is to check the return status
10925c10afb9Smrg * of IceProcessMessages.  xsm properly does this.
10935c10afb9Smrg *
10945c10afb9Smrg * Unfortunately, a design flaw exists in the ICE library in which
10955c10afb9Smrg * a default IO error handler is invoked if no IO error handler is
10965c10afb9Smrg * installed.  This default handler exits.  We must avoid this.
10975c10afb9Smrg *
10985c10afb9Smrg * To get around this problem, we install an IO error handler that
10995c10afb9Smrg * does a little magic.  Since a previous IO handler might have been
11005c10afb9Smrg * installed, when we install our IO error handler, we do a little
11015c10afb9Smrg * trick to get both the previous IO error handler and the default
11025c10afb9Smrg * IO error handler.  When our IO error handler is called, if the
11035c10afb9Smrg * previous handler is not the default handler, we call it.  This
11045c10afb9Smrg * way, everyone's IO error handler gets called except the stupid
11055c10afb9Smrg * default one which does an exit!
11065c10afb9Smrg */
11075c10afb9Smrg
11085c10afb9Smrgstatic IceIOErrorHandler prev_handler;
11095c10afb9Smrg
11105c10afb9Smrgvoid
11115c10afb9SmrgMyIoErrorHandler (ice_conn)
11125c10afb9Smrg
11135c10afb9SmrgIceConn ice_conn;
11145c10afb9Smrg
11155c10afb9Smrg{
11165c10afb9Smrg    if (prev_handler)
11175c10afb9Smrg	(*prev_handler) (ice_conn);
11185c10afb9Smrg}
11195c10afb9Smrg
11205c10afb9Smrgvoid
11215c10afb9SmrgInstallIOErrorHandler ()
11225c10afb9Smrg
11235c10afb9Smrg{
11245c10afb9Smrg    IceIOErrorHandler default_handler;
11255c10afb9Smrg
11265c10afb9Smrg    prev_handler = IceSetIOErrorHandler (NULL);
11275c10afb9Smrg    default_handler = IceSetIOErrorHandler (MyIoErrorHandler);
11285c10afb9Smrg    if (prev_handler == default_handler)
11295c10afb9Smrg	prev_handler = NULL;
11305c10afb9Smrg}
11315c10afb9Smrg
11325c10afb9Smrg
11335c10afb9Smrg/*
11345c10afb9Smrg * Since proxy manager does not authenticate connections, we disable
11355c10afb9Smrg * authentication by always returning true in the host based auth proc.
11365c10afb9Smrg */
11375c10afb9Smrg
11385c10afb9SmrgBool
11395c10afb9SmrgHostBasedAuthProc (hostname)
11405c10afb9Smrg
11415c10afb9Smrgchar *hostname;
11425c10afb9Smrg
11435c10afb9Smrg{
11445c10afb9Smrg    return (1);
11455c10afb9Smrg}
1146