static int doit_passive (kx_context *kc) { int otherside; u_char msg[1024], *p; int len; uint32_t tmp; const char *host = kc->host; otherside = connect_host (kc); if (otherside < 0) return 1; #if defined(SO_KEEPALIVE) && defined(HAVE_SETSOCKOPT) if (kc->keepalive_flag) { int one = 1; setsockopt (otherside, SOL_SOCKET, SO_KEEPALIVE, (void *)&one, sizeof(one)); } #endif p = msg; *p++ = INIT; len = strlen(kc->user); p += kx_put_int (len, p, sizeof(msg) - 1, 4); memcpy(p, kc->user, len); p += len; *p++ = PASSIVE | (kc->keepalive_flag ? KEEP_ALIVE : 0); if (kx_write (kc, otherside, msg, p - msg) != p - msg) err (1, "write to %s", host); len = kx_read (kc, otherside, msg, sizeof(msg)); if (len <= 0) errx (1, "error reading initial message from %s: " "this probably means it's using an old version.", host); p = (u_char *)msg; if (*p == ERROR) { p++; p += kx_get_int (p, &tmp, 4, 0); errx (1, "%s: %.*s", host, (int)tmp, p); } else if (*p != ACK) { errx (1, "%s: strange msg %d", host, *p); } else p++; p += kx_get_int (p, &tmp, 4, 0); memcpy(display, p, tmp); display[tmp] = '\0'; p += tmp; p += kx_get_int (p, &tmp, 4, 0); memcpy(xauthfile, p, tmp); xauthfile[tmp] = '\0'; p += tmp; status_output (kc->debug_flag); for (;;) { pid_t child; len = kx_read (kc, otherside, msg, sizeof(msg)); if (len < 0) err (1, "read from %s", host); else if (len == 0) return 0; p = (u_char *)msg; if (*p == ERROR) { p++; p += kx_get_int (p, &tmp, 4, 0); errx (1, "%s: %.*s", host, (int)tmp, p); } else if(*p != NEW_CONN) { errx (1, "%s: strange msg %d", host, *p); } else { p++; p += kx_get_int (p, &tmp, 4, 0); } ++nchild; child = fork (); if (child < 0) { warn("fork"); continue; } else if (child == 0) { int fd; int xserver; close (otherside); socket_set_port(kc->thataddr, htons(tmp)); fd = socket (kc->thataddr->sa_family, SOCK_STREAM, 0); if (fd < 0) err(1, "socket"); #if defined(TCP_NODELAY) && defined(HAVE_SETSOCKOPT) { int one = 1; setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, (void *)&one, sizeof(one)); } #endif #if defined(SO_KEEPALIVE) && defined(HAVE_SETSOCKOPT) if (kc->keepalive_flag) { int one = 1; setsockopt (fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&one, sizeof(one)); } #endif if (connect (fd, kc->thataddr, kc->thataddr_len) < 0) err(1, "connect(%s)", host); { int d = 0; char *s; s = getenv ("DISPLAY"); if (s != NULL) { s = strchr (s, ':'); if (s != NULL) d = atoi (s + 1); } xserver = connect_local_xsocket (d); if (xserver < 0) return 1; } return passive_session (xserver, fd, kc); } else { } } }
/** * @brief * This function is called whenever there is a connection accepted by the * port forwarder at qsub side. It will further send the data read by port * forwarder to the x server listening on the display number set in the * environment. * @param[in] display - The display number where X server is listening in * qsub. * @param[in] alsounused - This parameter is not used. its there just to * maintain consistency between function pointers used * by port_forwarder. * @return int * @retval socket number which is connected to Xserver. success * @retval -1 Failure */ int x11_connect_display( char *display, long alsounused) { int display_number, sock = 0; char buf[1024], *cp; struct addrinfo hints, *ai, *aitop; char strport[NI_MAXSERV]; int gaierr; /* * Now we decode the value of the DISPLAY variable and make a * connection to the real X server. */ /* * Check if it is a unix domain socket. Unix domain displays are in * one of the following formats: unix:d[.s], :d[.s], ::d[.s] */ if (strncmp(display, "unix:", 5) == 0 || display[0] == ':') { /* Connect to the unix domain socket. */ if (sscanf(strrchr(display, ':') + 1, "%d", &display_number) != 1) { fprintf(stderr, "Could not parse display number from DISPLAY: %.100s", display); return -1; } /* Create a socket. */ sock = connect_local_xsocket(display_number); if (sock < 0) return -1; /* OK, we now have a connection to the display. */ return sock; } /* * Connect to an inet socket. The DISPLAY value is supposedly * hostname:d[.s], where hostname may also be numeric IP address. */ strncpy(buf, display, sizeof(buf)); cp = strchr(buf, ':'); if (!cp) { fprintf(stderr, "Could not find ':' in DISPLAY: %.100s", display); return -1; } *cp = 0; /* buf now contains the host name. But first we parse the display number. */ if (sscanf(cp + 1, "%d", &display_number) != 1) { fprintf(stderr, "Could not parse display number from DISPLAY: %.100s", display); return -1; } /* Look up the host address */ memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; snprintf(strport, sizeof(strport), "%d", 6000 + display_number); if ((gaierr = getaddrinfo(buf, strport, &hints, &aitop)) != 0) { fprintf(stderr, "%100s: unknown host. (%s)", buf, gai_strerror(gaierr)); return -1; } for (ai = aitop; ai; ai = ai->ai_next) { /* Create a socket. */ sock = socket(ai->ai_family, SOCK_STREAM, 0); if (sock < 0) { fprintf(stderr, "socket: %.100s", strerror(errno)); continue; } /* Connect it to the display. */ if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0) { fprintf(stderr, "connect %.100s port %d: %.100s", buf, 6000 + display_number, strerror(errno)); close(sock); continue; } /* Success */ break; } freeaddrinfo(aitop); if (!ai) { fprintf(stderr, "connect %.100s port %d: %.100s", buf, 6000 + display_number, strerror(errno)); return -1; } set_nodelay(sock); return sock; }