Beispiel #1
0
static XrmDatabase
InitDefaults(
    Display *dpy)			/* display for defaults.... */
{
    XrmDatabase userdb;
    XrmDatabase xdb;
    char fname[PATH_MAX];               /* longer than any conceivable size */
    char *xenv;

    XrmInitialize();

    /*
     * See lib/Xt/Initialize.c
     *
     * First, get the defaults from the server; if none, then load from
     * ~/.Xdefaults.  Next, if there is an XENVIRONMENT environment variable,
     * then load that file.
     */
     
    if (dpy->xdefaults == NULL) {
	#ifdef _MSC_VER
	const char *slashDotXdefaults = ".Xdefaults";
	#else
	const char *slashDotXdefaults = "/.Xdefaults";
	#endif

	(void) GetHomeDir (fname, PATH_MAX - strlen (slashDotXdefaults) - 1);
	(void) strcat (fname, slashDotXdefaults);
	xdb = XrmGetFileDatabase (fname);
    } else {
	xdb = XrmGetStringDatabase(dpy->xdefaults);
    }

    if (!(xenv = getenv ("XENVIRONMENT"))) {
	#ifdef _MSC_VER
	const char *slashDotXdefaultsDash = ".Xdefaults-";
	#else
	const char *slashDotXdefaultsDash = "/.Xdefaults-";
	#endif
	int len;

	(void) GetHomeDir (fname, PATH_MAX - strlen (slashDotXdefaultsDash) - 1);
	(void) strcat (fname, slashDotXdefaultsDash);
	len = strlen (fname);
	(void) _XGetHostname (fname+len, PATH_MAX-len);
	xenv = fname;
    }
    userdb = XrmGetFileDatabase (xenv);
    XrmMergeDatabases (userdb, &xdb);
    return (xdb);

#ifdef old
    if (fname[0] != '\0') userdb =  XrmGetFileDatabase(fname);
    xdb = XrmGetStringDatabase(dpy->xdefaults);
    XrmMergeDatabases(userdb, &xdb);
    return xdb;
#endif
}
/*
 * Attempts to connect to server, given display name. Returns file descriptor
 * (network socket) or -1 if connection fails.  Display names may be of the
 * following format:
 *
 *     [protocol/] [hostname] : [:] displaynumber [.screennumber]
 *
 * A string with exactly two colons seperating hostname from the display
 * indicates a DECnet style name.  Colons in the hostname may occur if an
 * IPv6 numeric address is used as the hostname.  An IPv6 numeric address
 * may also end in a double colon, so three colons in a row indicates an
 * IPv6 address ending in :: followed by :display.  To make it easier for
 * people to read, an IPv6 numeric address hostname may be surrounded by
 * [ ] in a similar fashion to the IPv6 numeric address URL syntax defined
 * by IETF RFC 2732.
 *
 * If no hostname and no protocol is specified, the string is interpreted
 * as the most efficient local connection to a server on the same machine.
 * This is usually:
 *
 *     o  shared memory
 *     o  local stream
 *     o  UNIX domain socket
 *     o  TCP to local host
 *
 * This function will eventually call the X Transport Interface functions
 * which expects the hostname in the format:
 *
 *	[protocol/] [hostname] : [:] displaynumber
 *
 */
XtransConnInfo
_X11TransConnectDisplay (
    char *display_name,
    char **fullnamep,			/* RETURN */
    int *dpynump,			/* RETURN */
    int *screenp,			/* RETURN */
    char **auth_namep,			/* RETURN */
    int *auth_namelenp,			/* RETURN */
    char **auth_datap,			/* RETURN */
    int *auth_datalenp)			/* RETURN */
{
    int family;
    int saddrlen;
    Xtransaddr *saddr;
    char *lastp, *lastc, *p;		/* char pointers */
    char *pprotocol = NULL;		/* start of protocol name */
    char *phostname = NULL;		/* start of host of display */
    char *pdpynum = NULL;		/* start of dpynum of display */
    char *pscrnum = NULL;		/* start of screen of display */
    Bool dnet = False;			/* if true, then DECnet format */
    int idisplay = 0;			/* required display number */
    int iscreen = 0;			/* optional screen number */
    /*  int (*connfunc)(); */		/* method to create connection */
    int len, hostlen;			/* length tmp variable */
    int retry;				/* retry counter */
    char addrbuf[128];			/* final address passed to
					   X Transport Interface */
    char* address = addrbuf;
    XtransConnInfo trans_conn = NULL;	/* transport connection object */
    int connect_stat;
#if defined(LOCALCONN) || defined(UNIXCONN) || defined(TCPCONN)
    Bool reset_hostname = False;	/* Reset hostname? */
    char *original_hostname = NULL;
    int local_transport_index = -1;
    const char *local_transport[] = { LOCAL_TRANSPORT_LIST, NULL };
#endif

    p = display_name;

    saddrlen = 0;			/* set so that we can clear later */
    saddr = NULL;

    /*
     * Step 0, find the protocol.  This is delimited by the optional
     * slash ('/').
     */
    for (lastp = p; *p && *p != ':' && *p != '/'; p++) ;
    if (!*p) return NULL;		/* must have a colon */

    if (p != lastp && *p != ':') {	/* protocol given? */
	pprotocol = copystring (lastp, p - lastp);
	if (!pprotocol) goto bad;	/* no memory */
	p++;				/* skip the '/' */
    } else
	p = display_name;		/* reset the pointer in
					   case no protocol was given */

    /*
     * Step 1, find the hostname.  This is delimited by either one colon,
     * or two colons in the case of DECnet (DECnet Phase V allows a single
     * colon in the hostname).  (See note above regarding IPv6 numeric
     * addresses with triple colons or [] brackets.)
     */

    lastp = p;
    lastc = NULL;
    for (; *p; p++)
	if (*p == ':')
	    lastc = p;

    if (!lastc) return NULL;		/* must have a colon */

    if ((lastp != lastc) && (*(lastc - 1) == ':')
#if defined(IPv6) && defined(AF_INET6)
      && ( ((lastc - 1) == lastp) || (*(lastc - 2) != ':'))
#endif
	) {
	/* DECnet display specified */

#ifndef DNETCONN
	goto bad;
#else
	dnet = True;
	/* override the protocol specified */
	if (pprotocol)
	    Xfree (pprotocol);
	pprotocol = copystring ("dnet", 4);
	hostlen = lastc - 1 - lastp;
#endif
    }
    else
	hostlen = lastc - lastp;

    if (hostlen > 0) {		/* hostname given? */
	phostname = copystring (lastp, hostlen);
	if (!phostname) goto bad;	/* no memory */
    }

    p = lastc;

#if defined(LOCALCONN) || defined(UNIXCONN) || defined(TCPCONN)
    /* check if phostname == localnodename AND protocol not specified */
    if (!pprotocol && phostname) {
	char localhostname[256];

	if ((_XGetHostname (localhostname, sizeof localhostname) > 0)
	    && (strcmp(phostname, localhostname) == 0)) {
	    original_hostname = phostname;
	    phostname = NULL;
	    reset_hostname = True;
	}
    }
#endif


    /*
     * Step 2, find the display number.  This field is required and is
     * delimited either by a nul or a period, depending on whether or not
     * a screen number is present.
     */

    for (lastp = ++p; *p && isascii(*p) && isdigit(*p); p++) ;
    if ((p == lastp) ||			/* required field */
	(*p != '\0' && *p != '.') ||	/* invalid non-digit terminator */
	!(pdpynum = copystring (lastp, p - lastp)))  /* no memory */
      goto bad;
    idisplay = atoi (pdpynum);


    /*
     * Step 3, find the screen number.  This field is optional.  It is
     * present only if the display number was followed by a period (which
     * we've already verified is the only non-nul character).
     */

    if (*p) {
	for (lastp = ++p; *p && isascii(*p) && isdigit (*p); p++) ;
	if (p != lastp) {
	    if (*p ||			/* non-digits */
		!(pscrnum = copystring (lastp, p - lastp))) /* no memory */
		goto bad;
	    iscreen = atoi (lastp);
	}
    }

    /*
     * At this point, we know the following information:
     *
     *     pprotocol                protocol string or NULL
     *     phostname                hostname string or NULL
     *     idisplay                 display number
     *     iscreen                  screen number
     *     dnet                     DECnet boolean
     *
     * We can now decide which transport to use based on the defined
     * connection types and the hostname string.
     * If phostname & pprotocol are NULL, then choose the best transport.
     * If phostname is "unix" & pprotocol is NULL, then choose UNIX domain
     * sockets (if configured).
     */

#if defined(TCPCONN) || defined(UNIXCONN) || defined(LOCALCONN) || defined(MNX_TCPCONN) || defined(OS2PIPECONN)
    if (!pprotocol) {
#if defined(UNIXCONN)
	if (phostname && (strcmp (phostname, "unix") == 0)) {
	    Xfree(pprotocol);
	    pprotocol = copystring ("unix", 4);
	} else
#endif
#ifdef HAVE_LAUNCHD
	if (phostname && phostname[0]=='/') {
		pprotocol = copystring ("local", 5);
	}
#endif
	if (!phostname)
	{
	    if (local_transport[0] != NULL) {
		pprotocol = Xstrdup(local_transport[0]);
		local_transport_index = 0;
	    }
	}

	if (!pprotocol) { /* if still not found one, tcp is our last resort */
	    pprotocol = copystring ("tcp", 3);
	}
    }
#endif


  connect:
    /*
     * This seems kind of backwards, but we need to put the protocol,
     * host, and port back together to pass to _X11TransOpenCOTSClient().
     */

    {
	int olen = 3 + (pprotocol ? strlen(pprotocol) : 0) +
		       (phostname ? strlen(phostname) : 0) +
		       (pdpynum   ? strlen(pdpynum)   : 0);
	if (olen > sizeof addrbuf) address = Xmalloc (olen);
    }
    if (!address) goto bad;

    sprintf(address,"%s/%s:%d",
	pprotocol ? pprotocol : "",
	phostname ? phostname : "",
	idisplay );

    /*
     * Make the connection, also need to get the auth address info for
     * the connection.  Do retries in case server host has hit its
     * backlog (which, unfortunately, isn't distinguishable from there not
     * being a server listening at all, which is why we have to not retry
     * too many times).
     */
    for(retry=X_CONNECTION_RETRIES; retry>=0; retry-- )
    {
	if ( (trans_conn = _X11TransOpenCOTSClient(address)) == NULL )
	{
	    break;
	}
	if ((connect_stat = _X11TransConnect(trans_conn,address)) < 0 )
	{
	    _X11TransClose(trans_conn);
	    trans_conn = NULL;

	    if (connect_stat == TRANS_TRY_CONNECT_AGAIN)
		continue;
	    else
		break;
	}

	_X11TransGetPeerAddr(trans_conn, &family, &saddrlen, &saddr);

	/*
	 * The family is given in a socket format (ie AF_INET). This
	 * will convert it to the format used by the authorization and
	 * X protocol (ie FamilyInternet).
	 */

	if( _X11TransConvertAddress(&family, &saddrlen, &saddr) < 0 )
	{
	    _X11TransClose(trans_conn);
	    trans_conn = NULL;
	    if (saddr)
	    {
		free ((char *) saddr);
		saddr = NULL;
	    }
	    continue;
	}

	break;
    }

    if (address != addrbuf) Xfree (address);
    address = addrbuf;

    if( trans_conn == NULL )
      goto bad;

    /*
     * Set close-on-exec so that programs that fork() doesn't get confused.
     */

    _X11TransSetOption(trans_conn,TRANS_CLOSEONEXEC,1);

    /*
     * Build the expanded display name:
     *
     *     [host] : [:] dpy . scr \0
     */
#if defined(LOCALCONN) || defined(TCPCONN) || defined(UNIXCONN)
    /*
     *  If we computed the host name, get rid of it so that
     *  XDisplayString() and XDisplayName() agree.
     */
    if (reset_hostname && (phostname != original_hostname)) {
	Xfree (phostname);
	phostname = original_hostname;
	original_hostname = NULL;
    }
#endif
    len = ((phostname ? strlen(phostname) : 0) + 1 + (dnet ? 1 : 0) +
	   strlen(pdpynum) + 1 + (pscrnum ? strlen(pscrnum) : 1) + 1);
    *fullnamep = (char *) Xmalloc (len);
    if (!*fullnamep) goto bad;

#ifdef HAVE_LAUNCHD
    if (phostname && strlen(phostname) > 11 && !strncmp(phostname, "/tmp/launch", 11))
    	sprintf (*fullnamep, "%s%s%d",
	     (phostname ? phostname : ""),
	     (dnet ? "::" : ":"),
	     idisplay);
    else
#endif
    sprintf (*fullnamep, "%s%s%d.%d",
	     (phostname ? phostname : ""),
	     (dnet ? "::" : ":"),
	     idisplay, iscreen);

    *dpynump = idisplay;
    *screenp = iscreen;
    if (pprotocol) Xfree (pprotocol);
    if (phostname) Xfree (phostname);
    if (pdpynum) Xfree (pdpynum);
    if (pscrnum) Xfree (pscrnum);
#if defined(LOCALCONN) || defined(UNIXCONN) || defined(TCPCONN)
    if (original_hostname) Xfree (original_hostname);
#endif

    GetAuthorization(trans_conn, family, (char *) saddr, saddrlen, idisplay,
		     auth_namep, auth_namelenp, auth_datap, auth_datalenp);
    return trans_conn;


    /*
     * error return; make sure everything is cleaned up.
     */
  bad:
    if (trans_conn) (void)_X11TransClose(trans_conn);
    if (saddr) free ((char *) saddr);
    if (pprotocol) Xfree (pprotocol);
    if (phostname) Xfree (phostname);
    if (address && address != addrbuf) { Xfree(address); address = addrbuf; }

#if defined(LOCALCONN) || defined(UNIXCONN) || defined(TCPCONN)
    /* If connecting to the local machine, and we failed, try again with
     * the next transport type available, if there is one.
     */
    if (local_transport_index >= 0) {
	if (local_transport[++local_transport_index] != NULL) {
	    pprotocol = Xstrdup(local_transport[local_transport_index]);
#ifdef TCPCONN
	    if (strcmp(pprotocol, "tcp") == 0) {
		if (original_hostname != NULL) {
		    phostname = original_hostname;
		    original_hostname = NULL;
		} else {
		    phostname = copystring("localhost", 9);
		}
	    } else
#endif /* TCPCONN */
	    {
		if ((phostname != NULL) && (original_hostname == NULL)) {
		    original_hostname = phostname;
		}
		phostname = NULL;
	    }
	    goto connect;
	}
    }

    /* No more to try, we've failed all available local transports */
    if (original_hostname) Xfree(original_hostname);
#endif /* LOCALCONN || UNIXCONN || TCPCONN */

    if (pdpynum) Xfree (pdpynum);
    if (pscrnum) Xfree (pscrnum);
    return NULL;

}