|
|
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.