|
|
1.1 ! root 1: #include "copyright.h" ! 2: /* $Header: XConnDis.c,v 11.21 87/09/13 23:03:07 toddb Exp $ */ ! 3: /* Copyright Massachusetts Institute of Technology 1985, 1986 */ ! 4: #define NEED_EVENTS ! 5: /* ! 6: * THIS IS AN OS DEPENDENT FILE! It should work on 4.2BSD derived ! 7: * systems. VMS and System V should plan to have their own version. ! 8: */ ! 9: #include <stdio.h> ! 10: #include "Xlibint.h" ! 11: #include <fcntl.h> ! 12: #include <sys/socket.h> ! 13: #include <strings.h> ! 14: ! 15: #ifdef UNIXCONN ! 16: #include <sys/un.h> ! 17: #define X_UNIX_PATH "/tmp/.X11-unix/X" ! 18: #endif /* UNIXCONN */ ! 19: void bcopy(); ! 20: /* ! 21: * Attempts to connect to server, given display name. Returns file descriptor ! 22: * (network socket) or -1 if connection fails. The expanded display name ! 23: * of the form hostname:number.screen ("::" if DECnet) is returned in a result ! 24: * parameter. The screen number to use is also returned. ! 25: */ ! 26: int _XConnectDisplay (display_name, expanded_name, screen_num) ! 27: ! 28: char *display_name; ! 29: char *expanded_name; /* return */ ! 30: int *screen_num; /* return */ ! 31: ! 32: { ! 33: char displaybuf[256]; /* Display string buffer */ ! 34: register char *display_ptr; /* Display string buffer pointer */ ! 35: register char *numbuf_ptr; /* Server number buffer pointer */ ! 36: char *screen_ptr; /* Pointer for locating screen num */ ! 37: int display_num; /* Display number */ ! 38: struct sockaddr_in inaddr; /* INET socket address. */ ! 39: #ifdef UNIXCONN ! 40: struct sockaddr_un unaddr; /* UNIX socket address. */ ! 41: #endif ! 42: struct sockaddr *addr; /* address to connect to */ ! 43: struct hostent *host_ptr; ! 44: int addrlen; /* length of address */ ! 45: extern char *getenv(); ! 46: extern struct hostent *gethostbyname(); ! 47: int fd; /* Network socket */ ! 48: char numberbuf[16]; ! 49: char *dot_ptr = NULL; /* Pointer to . before screen num */ ! 50: #ifdef DNETCONN ! 51: int dnet = 0; ! 52: char objname[20]; ! 53: extern int dnet_conn(); ! 54: #endif ! 55: ! 56: /* ! 57: * Find the ':' seperator and extract the hostname and the ! 58: * display number. ! 59: * NOTE - if DECnet is to be used, the display name is formatted ! 60: * as "host::number" ! 61: */ ! 62: (void) strncpy(displaybuf, display_name, sizeof(displaybuf)); ! 63: if ((display_ptr = SearchString(displaybuf,':')) == NULL) return (-1); ! 64: #ifdef DNETCONN ! 65: if (*(display_ptr + 1) == ':') { ! 66: dnet++; ! 67: *(display_ptr++) = '\0'; ! 68: } ! 69: #endif ! 70: *(display_ptr++) = '\0'; ! 71: ! 72: /* displaybuf now contains only a null-terminated host name, and ! 73: * display_ptr points to the display number. ! 74: * If the display number is missing there is an error. */ ! 75: ! 76: if (*display_ptr == '\0') return(-1); ! 77: ! 78: /* ! 79: * Build a string of the form <display-number>.<screen-number> in ! 80: * numberbuf, using ".0" as the default. ! 81: */ ! 82: screen_ptr = display_ptr; ! 83: numbuf_ptr = numberbuf; ! 84: while (*screen_ptr != '\0') { ! 85: if (*screen_ptr == '.') { ! 86: dot_ptr = numbuf_ptr; ! 87: *(screen_ptr++) = '\0'; ! 88: *(numbuf_ptr++) = '.'; ! 89: } else { ! 90: *(numbuf_ptr++) = *(screen_ptr++); ! 91: } ! 92: } ! 93: ! 94: /* ! 95: * If the spec doesn't include a screen number, add ".0" (or "0" if ! 96: * only "." is present.) ! 97: */ ! 98: if (dot_ptr == NULL) { ! 99: dot_ptr = numbuf_ptr; ! 100: *(numbuf_ptr++) = '.'; ! 101: *(numbuf_ptr++) = '0'; ! 102: } else { ! 103: if (*(numbuf_ptr - 1) == '.') ! 104: *(numbuf_ptr++) = '0'; ! 105: } ! 106: *numbuf_ptr = '\0'; ! 107: ! 108: /* ! 109: * Return the screen number in the result parameter ! 110: */ ! 111: *screen_num = atoi(dot_ptr + 1); ! 112: ! 113: /* ! 114: * Convert the server number string to an integer. ! 115: */ ! 116: display_num = atoi(display_ptr); ! 117: ! 118: /* ! 119: * If the display name is missing, use current host. ! 120: */ ! 121: if (displaybuf[0] == '\0') ! 122: #ifdef DNETCONN ! 123: if (dnet) ! 124: (void) strcpy (displaybuf, "0"); ! 125: else ! 126: #endif ! 127: #ifdef UNIXCONN ! 128: ; /* Do nothing if UNIX DOMAIN. Will be handled below. */ ! 129: #else ! 130: (void) gethostname (displaybuf, sizeof(displaybuf)); ! 131: #endif ! 132: ! 133: #ifdef DNETCONN ! 134: if (dnet) { ! 135: /* ! 136: * build the target object name. ! 137: */ ! 138: sprintf(objname, "X%d", display_num); ! 139: /* ! 140: * Attempt to open the DECnet connection, return -1 if fails. ! 141: */ ! 142: if ((fd = dnet_conn(displaybuf, ! 143: objname, SOCK_STREAM, 0, 0, 0, 0)) < 0) ! 144: return(-1); /* errno set by dnet_conn. */ ! 145: } else ! 146: #endif ! 147: { ! 148: #ifdef UNIXCONN ! 149: if ((displaybuf[0] == '\0') || ! 150: (strcmp("unix", displaybuf) == 0)) { ! 151: /* Connect locally using Unix domain. */ ! 152: unaddr.sun_family = AF_UNIX; ! 153: (void) strcpy(unaddr.sun_path, X_UNIX_PATH); ! 154: strcat(unaddr.sun_path, display_ptr); ! 155: addr = (struct sockaddr *) &unaddr; ! 156: addrlen = strlen(unaddr.sun_path) + 2; ! 157: /* ! 158: * Open the network connection. ! 159: */ ! 160: if ((fd = socket((int) addr->sa_family, SOCK_STREAM, 0)) < 0) ! 161: return(-1); /* errno set by system call. */ ! 162: } else ! 163: #endif ! 164: { ! 165: /* Get the statistics on the specified host. */ ! 166: if ((inaddr.sin_addr.s_addr = inet_addr(displaybuf)) == -1) { ! 167: if ((host_ptr = gethostbyname(displaybuf)) == NULL) { ! 168: /* No such host! */ ! 169: errno = EINVAL; ! 170: return(-1); ! 171: } ! 172: /* Check the address type for an internet host. */ ! 173: if (host_ptr->h_addrtype != AF_INET) { ! 174: /* Not an Internet host! */ ! 175: errno = EPROTOTYPE; ! 176: return(-1); ! 177: } ! 178: ! 179: /* Set up the socket data. */ ! 180: inaddr.sin_family = host_ptr->h_addrtype; ! 181: bcopy((char *)host_ptr->h_addr, ! 182: (char *)&inaddr.sin_addr, ! 183: sizeof(inaddr.sin_addr)); ! 184: } else { ! 185: inaddr.sin_family = AF_INET; ! 186: } ! 187: addr = (struct sockaddr *) &inaddr; ! 188: addrlen = sizeof (struct sockaddr_in); ! 189: inaddr.sin_port = display_num; ! 190: inaddr.sin_port += X_TCP_PORT; ! 191: inaddr.sin_port = htons(inaddr.sin_port); ! 192: /* ! 193: * Open the network connection. ! 194: */ ! 195: ! 196: if ((fd = socket((int) addr->sa_family, SOCK_STREAM, 0)) < 0) ! 197: return(-1); /* errno set by system call. */ ! 198: /* make sure to turn off TCP coalescence */ ! 199: #ifdef TCP_NODELAY ! 200: { ! 201: int mi; ! 202: setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &mi, sizeof (int)); ! 203: } ! 204: #endif ! 205: } ! 206: ! 207: ! 208: if (connect(fd, addr, addrlen) == -1) { ! 209: (void) close (fd); ! 210: return(-1); /* errno set by system call. */ ! 211: } ! 212: } ! 213: /* ! 214: * set it non-blocking. This is so we can read data when blocked ! 215: * for writing in the library. ! 216: */ ! 217: (void) fcntl(fd, F_SETFL, FNDELAY); ! 218: /* ! 219: * Return the id if the connection succeeded. Rebuild the expanded ! 220: * spec and return it in the result parameter. ! 221: */ ! 222: display_ptr = displaybuf; ! 223: while (*(++display_ptr) != '\0') ! 224: ; ! 225: *(display_ptr++) = ':'; ! 226: #ifdef DNETCONN ! 227: if (dnet) ! 228: *(display_ptr++) = ':'; ! 229: #endif ! 230: numbuf_ptr = numberbuf; ! 231: while (*numbuf_ptr != '\0') ! 232: *(display_ptr++) = *(numbuf_ptr++); ! 233: *display_ptr = '\0'; ! 234: (void) strcpy(expanded_name, displaybuf); ! 235: return(fd); ! 236: ! 237: } ! 238: ! 239: /* ! 240: * Disconnect from server. ! 241: */ ! 242: ! 243: int _XDisconnectDisplay (server) ! 244: ! 245: int server; ! 246: ! 247: { ! 248: (void) close(server); ! 249: } ! 250: ! 251: #undef NULL ! 252: #define NULL ((char *) 0) ! 253: /* ! 254: * This is an OS dependent routine which: ! 255: * 1) returns as soon as the connection can be written on.... ! 256: * 2) if the connection can be read, must enqueue events and handle errors, ! 257: * until the connection is writable. ! 258: */ ! 259: _XWaitForWritable(dpy) ! 260: Display *dpy; ! 261: { ! 262: unsigned long r_mask[MSKCNT]; ! 263: unsigned long w_mask[MSKCNT]; ! 264: int nfound; ! 265: ! 266: CLEARBITS(r_mask); ! 267: CLEARBITS(w_mask); ! 268: ! 269: while (1) { ! 270: BITSET(r_mask, dpy->fd); ! 271: BITSET(w_mask, dpy->fd); ! 272: ! 273: do { ! 274: nfound = select (dpy->fd + 1, r_mask, w_mask, NULL, NULL); ! 275: if (nfound < 0 && errno != EINTR) ! 276: (*_XIOErrorFunction)(dpy); ! 277: } while (nfound <= 0); ! 278: ! 279: if (ANYSET(r_mask)) { ! 280: char buf[BUFSIZE]; ! 281: long pend_not_register; ! 282: register long pend; ! 283: register xEvent *ev; ! 284: ! 285: /* find out how much data can be read */ ! 286: if (BytesReadable(dpy->fd, (char *) &pend_not_register) < 0) ! 287: (*_XIOErrorFunction)(dpy); ! 288: pend = pend_not_register; ! 289: ! 290: /* must read at least one xEvent; if none is pending, then ! 291: we'll just block waiting for it */ ! 292: if (pend < sizeof(xEvent)) pend = sizeof (xEvent); ! 293: ! 294: /* but we won't read more than the max buffer size */ ! 295: if (pend > BUFSIZE) pend = BUFSIZE; ! 296: ! 297: /* round down to an integral number of XReps */ ! 298: pend = (pend / sizeof (xEvent)) * sizeof (xEvent); ! 299: ! 300: _XRead (dpy, buf, pend); ! 301: for (ev = (xEvent *) buf; pend > 0; ev++, pend -= sizeof(xEvent)) ! 302: { ! 303: if (ev->u.u.type == X_Error) ! 304: _XError (dpy, (xError *) ev); ! 305: else /* it's an event packet; enqueue it */ ! 306: _XEnq (dpy, ev); ! 307: } ! 308: } ! 309: if (ANYSET(w_mask)) ! 310: return; ! 311: } ! 312: } ! 313: ! 314: ! 315: _XWaitForReadable(dpy) ! 316: Display *dpy; ! 317: { ! 318: unsigned long r_mask[MSKCNT]; ! 319: int result; ! 320: ! 321: CLEARBITS(r_mask); ! 322: do { ! 323: BITSET(r_mask, dpy->fd); ! 324: result = select(dpy->fd + 1, r_mask, NULL, NULL, NULL); ! 325: if (result == -1 && errno != EINTR) (*_XIOErrorFunction)(dpy); ! 326: } while (result <= 0); ! 327: } ! 328: ! 329: static int padlength[4] = {0, 3, 2, 1}; ! 330: ! 331: _XSendClientPrefix (dpy, client) ! 332: Display *dpy; ! 333: xConnClientPrefix *client; ! 334: { ! 335: /* ! 336: * Authorization string stuff.... Must always transmit multiple of 4 ! 337: * bytes. ! 338: */ ! 339: ! 340: char *auth_proto = ""; ! 341: int auth_length; ! 342: char *auth_string = ""; ! 343: int auth_strlen; ! 344: char pad[3]; ! 345: char buffer[BUFSIZ], *bptr; ! 346: ! 347: int bytes=0; ! 348: ! 349: auth_length = strlen(auth_proto); ! 350: auth_strlen = strlen(auth_string); ! 351: client->nbytesAuthProto = auth_length; ! 352: client->nbytesAuthString = auth_strlen; ! 353: ! 354: bytes = (sizeof(xConnClientPrefix) + ! 355: auth_length + padlength[auth_length & 3] + ! 356: auth_strlen + padlength[auth_strlen & 3]); ! 357: ! 358: bcopy(client, buffer, sizeof(xConnClientPrefix)); ! 359: bptr = buffer + sizeof(xConnClientPrefix); ! 360: if (auth_length) ! 361: { ! 362: bcopy(auth_proto, bptr, auth_length); ! 363: bptr += auth_length; ! 364: if (padlength[auth_length & 3]) ! 365: { ! 366: bcopy(pad, bptr, padlength[auth_length & 3]); ! 367: bptr += padlength[auth_length & 3]; ! 368: } ! 369: } ! 370: if (auth_strlen) ! 371: { ! 372: bcopy(auth_string, bptr, auth_strlen); ! 373: bptr += auth_strlen; ! 374: if (padlength[auth_strlen & 3]) ! 375: { ! 376: bcopy(pad, bptr, padlength[auth_strlen & 3]); ! 377: bptr += padlength[auth_strlen & 3]; ! 378: } ! 379: } ! 380: (void) WriteToServer(dpy->fd, buffer, bytes); ! 381: return; ! 382: } ! 383:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.