/* * 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; }
/* * 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; #ifdef LOCALCONN struct utsname sys; #endif #ifdef TCPCONN char *tcphostname = NULL; /* A place to save hostname pointer */ #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; #ifdef LOCALCONN /* check if phostname == localnodename AND protocol not specified */ if (!pprotocol && phostname && uname(&sys) >= 0 && !strncmp(phostname, sys.nodename, (strlen(sys.nodename) < strlen(phostname) ? strlen(phostname) : strlen(sys.nodename)))) { #ifdef TCPCONN /* * We'll first attempt to connect using the local transport. If * this fails (which is the case if sshd X protocol forwarding is * being used), retry using tcp and this hostname. */ tcphostname = copystring(phostname, strlen(phostname)); #endif Xfree (phostname); phostname = copystring ("unix", 4); } #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 ConnectionFlags * build parameter the hostname string. If phostname is NULL or equals * the string "local", then choose the best transport. If phostname * is "unix", then choose BSD UNIX domain sockets (if configured). */ #if defined(TCPCONN) || defined(UNIXCONN) || defined(LOCALCONN) || defined(MNX_TCPCONN) || defined(OS2PIPECONN) if (!pprotocol) { if (!phostname) { #if defined(UNIXCONN) || defined(LOCALCONN) || defined(OS2PIPECONN) pprotocol = copystring ("local", 5); #if defined(TCPCONN) tcphostname = copystring("localhost", 9); #endif } else { #endif pprotocol = copystring ("tcp", 3); } } #endif #if defined(UNIXCONN) || defined(LOCALCONN) || defined(OS2PIPECONN) /* * Now that the defaults have been established, see if we have any * special names that we have to override: * * :N => if UNIXCONN then unix-domain-socket * ::N => if UNIXCONN then unix-domain-socket * unix:N => if UNIXCONN then unix-domain-socket * * Note that if UNIXCONN isn't defined, then we can use the default * transport connection function set above. */ if (!phostname) { #ifdef apollo ; /* Unix domain sockets are *really* bad on apollos */ #else if( pprotocol ) Xfree(pprotocol); pprotocol = copystring ("local", 5); #endif } else if (strcmp (phostname, "unix") == 0) { if( pprotocol ) Xfree(pprotocol); pprotocol = copystring ("local", 5); } #endif #if defined(TCPCONN) connect: #endif /* * 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) { sleep(1); 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; sleep(1); 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 */ 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; 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); #ifdef TCPCONN if (tcphostname) Xfree (tcphostname); #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(TCPCONN) if (tcphostname) { pprotocol = copystring("tcp", 3); phostname = tcphostname; tcphostname = NULL; goto connect; } #endif if (pdpynum) Xfree (pdpynum); if (pscrnum) Xfree (pscrnum); return NULL; }
int _XDisconnectDisplay (XtransConnInfo trans_conn) { _X11TransDisconnect(trans_conn); _X11TransClose(trans_conn); return 0; }
void ICVM_X11TransClose(void){ R_R0=_X11TransClose((ciptr)rSTKs32(0)); icvm_SetErr(); }