|
|
1.1 root 1: #include "copyright.h"
2: /* $XConsortium: XConnDis.c,v 11.36 88/09/16 11:09:34 jim 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 <X11/Xos.h>
11: #include "Xlibint.h"
12: #include <sys/socket.h>
13: #ifndef hpux
14: #include <netinet/tcp.h>
15: #endif
16:
17: #ifdef hpux
18: #include <sys/utsname.h>
19: #endif
20:
21: #ifdef UNIXCONN
22: #include <sys/un.h>
23: #ifndef X_UNIX_PATH
24: #define X_UNIX_PATH "/tmp/.X11-unix/X"
25: #endif /* X_UNIX_PATH */
26: #endif /* UNIXCONN */
27: void bcopy();
28:
29: #ifdef ISOCONN
30: #include <isode/psap.h>
31: #include <isode/tsap.h>
32: #include <isode/isoservent.h>
33:
34: #ifdef ISODEBUG
35: extern char *isodetcpath;
36:
37: int isodexbug = 0;
38: #endif /* ISODEBUG */
39: #endif /* ISOCONN */
40:
41: #ifdef ISOCONN
42:
43: /*
44: * array of fd 2 family map so we can lookup right function below...
45: * Its initialised at connection setup...
46: */
47: int fd2family[MAXSOCKS];
48: /*
49: * Globals for storing functions appropos each fd/socket type
50: * UNIX_IO (0) map to sys calls
51: * ISODE_IO (1) maps to my fns...
52: */
53: extern int read(), TReadFromServer();
54: int (*readfn[])() =
55: {
56: read, TReadFromServer
57: };
58: extern int write(), TWriteToServer();
59: int (*writefn[])() =
60: {
61: write, TWriteToServer
62: };
63: extern int readv(), TReadvFromServer();
64: int (*readvfn[])() =
65: {
66: readv, TReadvFromServer
67: };
68: extern writev(), TWritevToServer();
69: int (*writevfn[])() =
70: {
71: writev, TWritevToServer
72: };
73: extern int UBytesReadable(), TBytesReadable();
74: int (*ioctlfn[])() =
75: {
76: UBytesReadable, TBytesReadable
77: };
78: extern int close(), TDiscFromServer();
79: int (*closefn[])() =
80: {
81: close, TDiscFromServer
82: };
83:
84: static
85: int iso_conn(server)
86: char *server;
87: {
88: struct TSAPconnect tcs;
89: struct TSAPconnect *tc = &tcs;
90: struct TSAPdisconnect tds;
91: struct TSAPdisconnect *td = &tds;
92: struct QOStype qo;
93: struct QOStype *qos = &qo;
94: AEI aei;
95: struct PSAPaddr *pa, rpa, *mpa, rmpa;
96: int ret;
97: char *x;
98: extern char *index();
99:
100: #ifdef ISODEBUG
101: isodetcpath = ISODEPATH;
102: #endif /* ISODEBUG */
103:
104: /*
105: * Get their TSAP from their AEI
106: */
107: if ((x = index(server, ':')) != NULL) {
108: *(x++) = '\0';
109: aei = str2aei(server, x);
110: } else {
111: aei = str2aei(server, DEFAULTTSERVICE);
112: }
113:
114: if (aei == NULLAEI) {
115: fprintf(stderr, "No AEI for %s\n", server);
116: return -1;
117: }
118:
119: if ((pa = aei2addr (aei)) == NULLPA) {
120: fprintf (stderr, "address translation failed");
121: return -1;
122: }
123: rpa = *pa; /* struct copy */
124: /*
125: * Get my address for completeness
126: */
127: mpa = NULLPA;
128: if (x != NULL)
129: aei = str2aei(TLocalHostName(), x);
130: else
131: aei = str2aei(TLocalHostName(), DEFAULTTSERVICE);
132: if (aei == NULLAEI) {
133: fprintf (stderr, "my AEI lookup failed %s\n",
134: TLocalHostName());
135: return -1;
136: }
137:
138: if ((mpa = aei2addr (aei)) == NULLPA) {
139: fprintf (stderr, "my address translation failed %s\n",
140: TLocalHostName());
141: return -1;
142: }
143:
144: rmpa = *mpa; /* struct copy */
145: /*
146: * No Xpedited required !
147: */
148: tc->tc_expedited = 0;
149: /*
150: * Just a guess - i dont understand
151: * the comment in the documentation about TSDUsizes
152: */
153: tc->tc_tsdusize = 16000;
154: tc->tc_cc = 0;
155: qos->qos_reliability = LOW_QUALITY; /* Well this is X after all */
156:
157: ret = TConnRequest(&(rmpa.pa_addr.sa_addr),
158: &(rpa.pa_addr.sa_addr),
159: 0, 0, NULLCP, qos, tc, td);
160:
161: /*
162: * Should map errors to perrors somehow???
163: */
164: if (ret == NOTOK) {
165: #ifdef ISODEBUG
166: if (isodexbug)
167: fprintf(stderr, "TCR Failed %s\n",
168: TErrString(td->td_reason));
169: #endif /* ISODEBUG */
170: return -1;
171: }
172: else {
173: #ifdef ISODEBUG
174: if (isodexbug)
175: fprintf(stderr, "client: isoconn ok\n");
176: #endif /* ISODEBUG */
177: ret = tc->tc_sd;
178: return ret;
179: }
180: }
181: #endif /* ISOCONN */
182:
183: /*
184: * Attempts to connect to server, given display name. Returns file descriptor
185: * (network socket) or -1 if connection fails. The expanded display name
186: * of the form hostname:number.screen ("::" if DECnet) is returned in a result
187: * parameter. The screen number to use is also returned.
188: */
189: int _XConnectDisplay (display_name, expanded_name, prop_name, screen_num)
190: char *display_name;
191: char *expanded_name; /* return */
192: char *prop_name; /* return */
193: int *screen_num; /* return */
194:
195: {
196: char displaybuf[256]; /* Display string buffer */
197: register char *display_ptr; /* Display string buffer pointer */
198: register char *numbuf_ptr; /* Server number buffer pointer */
199: char *screen_ptr; /* Pointer for locating screen num */
200: int display_num; /* Display number */
201: struct sockaddr_in inaddr; /* INET socket address. */
202: unsigned long hostinetaddr; /* result of inet_addr of arpa addr */
203: #ifdef UNIXCONN
204: struct sockaddr_un unaddr; /* UNIX socket address. */
205: #endif
206: struct sockaddr *addr; /* address to connect to */
207: struct hostent *host_ptr;
208: int addrlen; /* length of address */
209: extern char *getenv();
210: extern struct hostent *gethostbyname();
211: int fd; /* Network socket */
212: char numberbuf[16];
213: char *dot_ptr = NULL; /* Pointer to . before screen num */
214: #ifdef DNETCONN
215: int dnet = 0;
216: char objname[20];
217: extern int dnet_conn();
218: #endif
219: #ifdef ISOCONN
220: int isoconn = 0;
221: char isochar = 'X';
222:
223: /*
224: * ISO Host name are "host:T-Namenumber"
225: * T-Name = T (for TCP) or X (for X.25) should really be
226: * TP4 or TP0 whathaveyou
227: */
228: #endif /* ISOCONN */
229:
230: /*
231: * Find the ':' seperator and extract the hostname and the
232: * display number.
233: * NOTE - if DECnet is to be used, the display name is formatted
234: * as "host::number"
235: */
236: (void) strncpy(displaybuf, display_name, sizeof(displaybuf));
237: if ((display_ptr = SearchString(displaybuf,':')) == NULL) return (-1);
238: #ifdef DNETCONN
239: if (*(display_ptr + 1) == ':') {
240: dnet++;
241: *(display_ptr++) = '\0';
242: }
243: #endif
244: #ifdef ISOCONN
245: if ((*(display_ptr + 1) == 'X') || (*(display_ptr + 1) == 'T')) {
246: isochar = *(display_ptr + 1);
247: isoconn++;
248: *(display_ptr++) = '\0';
249: }
250: #endif /* ISOCONN */
251: *(display_ptr++) = '\0';
252:
253: /* displaybuf now contains only a null-terminated host name, and
254: * display_ptr points to the display number.
255: * If the display number is missing there is an error. */
256:
257: if (*display_ptr == '\0') return(-1);
258:
259: /*
260: * Build a string of the form <display-number>.<screen-number> in
261: * numberbuf, using ".0" as the default.
262: */
263: screen_ptr = display_ptr; /* points to #.#.propname */
264: numbuf_ptr = numberbuf; /* beginning of buffer */
265: while (*screen_ptr != '\0') {
266: if (*screen_ptr == '.') { /* either screen or prop */
267: if (dot_ptr) { /* then found prop_name */
268: screen_ptr++;
269: break;
270: }
271: dot_ptr = numbuf_ptr; /* found screen_num */
272: *(screen_ptr++) = '\0';
273: *(numbuf_ptr++) = '.';
274: } else {
275: *(numbuf_ptr++) = *(screen_ptr++);
276: }
277: }
278:
279: /*
280: * If the spec doesn't include a screen number, add ".0" (or "0" if
281: * only "." is present.)
282: */
283: if (dot_ptr == NULL) { /* no screen num or prop */
284: dot_ptr = numbuf_ptr;
285: *(numbuf_ptr++) = '.';
286: *(numbuf_ptr++) = '0';
287: } else {
288: if (*(numbuf_ptr - 1) == '.')
289: *(numbuf_ptr++) = '0';
290: }
291: *numbuf_ptr = '\0';
292:
293: /*
294: * Return the screen number and property names in the result parameters
295: */
296: *screen_num = atoi(dot_ptr + 1);
297: strcpy (prop_name, screen_ptr);
298:
299: /*
300: * Convert the server number string to an integer.
301: */
302: display_num = atoi(display_ptr);
303:
304: /*
305: * If the display name is missing, use current host.
306: */
307: if (displaybuf[0] == '\0')
308: #ifdef DNETCONN
309: if (dnet)
310: (void) strcpy (displaybuf, "0");
311: else
312: #endif
313: #ifdef UNIXCONN
314: ; /* Do nothing if UNIX DOMAIN. Will be handled below. */
315: #else
316: #ifdef hpux
317: /*
318: * same host name crock as in server and xinit.
319: */
320: {
321: struct utsname name;
322:
323: uname(&name);
324: strcpy(displaybuf, name.nodename);
325: }
326: #else
327: (void) gethostname (displaybuf, sizeof(displaybuf));
328: #endif /* hpux */
329: #endif /* UNIXCONN else TCPCONN (assumed) */
330:
331: #ifdef DNETCONN
332: if (dnet) {
333: /*
334: * build the target object name.
335: */
336: sprintf(objname, "X$X%d", display_num);
337: /*
338: * Attempt to open the DECnet connection, return -1 if fails.
339: */
340: if ((fd = dnet_conn(displaybuf,
341: objname, SOCK_STREAM, 0, 0, 0, 0)) < 0)
342: return(-1); /* errno set by dnet_conn. */
343: #ifdef ISOCONN
344: else
345: fd2family[fd] = UNIX_IO;
346: #endif /* ISOCONN */
347:
348: } else
349: #endif
350: #ifdef ISOCONN
351: if (isoconn) {
352: if ((fd = iso_conn(displaybuf)) < 0)
353: return(-1);
354: else
355: fd2family[fd] = ISODE_IO;
356: } else
357: #endif
358: {
359: #ifdef UNIXCONN
360: if ((displaybuf[0] == '\0') ||
361: (strcmp("unix", displaybuf) == 0)) {
362: /* Connect locally using Unix domain. */
363: unaddr.sun_family = AF_UNIX;
364: (void) strcpy(unaddr.sun_path, X_UNIX_PATH);
365: strcat(unaddr.sun_path, display_ptr);
366: addr = (struct sockaddr *) &unaddr;
367: addrlen = strlen(unaddr.sun_path) + 2;
368: /*
369: * Open the network connection.
370: */
371: if ((fd = socket((int) addr->sa_family, SOCK_STREAM, 0)) < 0)
372: return(-1); /* errno set by system call. */
373: } else
374: #endif
375: {
376: /* Get the statistics on the specified host. */
377: hostinetaddr = inet_addr (displaybuf);
378: if (hostinetaddr == -1) {
379: if ((host_ptr = gethostbyname(displaybuf)) == NULL) {
380: /* No such host! */
381: errno = EINVAL;
382: return(-1);
383: }
384: /* Check the address type for an internet host. */
385: if (host_ptr->h_addrtype != AF_INET) {
386: /* Not an Internet host! */
387: errno = EPROTOTYPE;
388: return(-1);
389: }
390:
391: /* Set up the socket data. */
392: inaddr.sin_family = host_ptr->h_addrtype;
393: #if defined(CRAY) && defined(OLDTCP)
394: /* Only Cray UNICOS3 and UNICOS4 will define this */
395: {
396: long t;
397: bcopy((char *)host_ptr->h_addr,
398: (char *)&t,
399: sizeof(inaddr.sin_addr));
400: inaddr.sin_addr = t;
401: }
402: #else
403: bcopy((char *)host_ptr->h_addr,
404: (char *)&inaddr.sin_addr,
405: sizeof(inaddr.sin_addr));
406: #endif /* CRAY and OLDTCP */
407: } else {
408: #if defined(CRAY) && defined(OLDTCP)
409: /* Only Cray UNICOS3 and UNICOS4 will define this */
410: inaddr.sin_addr = hostinetaddr;
411: #else
412: inaddr.sin_addr.s_addr = hostinetaddr;
413: #endif /* CRAY and OLDTCP */
414: inaddr.sin_family = AF_INET;
415: }
416: addr = (struct sockaddr *) &inaddr;
417: addrlen = sizeof (struct sockaddr_in);
418: inaddr.sin_port = display_num;
419: inaddr.sin_port += X_TCP_PORT;
420: inaddr.sin_port = htons(inaddr.sin_port);
421: /*
422: * Open the network connection.
423: */
424:
425: if ((fd = socket((int) addr->sa_family, SOCK_STREAM, 0)) < 0)
426: return(-1); /* errno set by system call. */
427: #ifdef ISOCONN
428: fd2family[fd] = UNIX_IO;
429: #endif /* ISOCONN */
430: /* make sure to turn off TCP coalescence */
431: #ifdef TCP_NODELAY
432: {
433: int mi = 1;
434: setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &mi, sizeof (int));
435: }
436: #endif
437: }
438:
439:
440: if (connect(fd, addr, addrlen) == -1) {
441: (void) close (fd);
442: return(-1); /* errno set by system call. */
443: }
444: }
445:
446: #ifdef ISOCONN
447: if (!isoconn) {
448: #endif /* ISOCONN */
449: /*
450: * Not required for ISO T-Service
451: */
452: /*
453: * set it non-blocking. This is so we can read data when blocked
454: * for writing in the library.
455: */
456: #ifdef FIOSNBIO
457: {
458: int arg = 1;
459: ioctl(fd, FIOSNBIO, &arg);
460: }
461: #else
462: (void) fcntl(fd, F_SETFL, FNDELAY);
463: #endif /* FIOSNBIO */
464:
465: #ifdef ISOCONN
466: }
467: #endif /* ISOCONN */
468: /*
469: * Return the id if the connection succeeded. Rebuild the expanded
470: * spec and return it in the result parameter.
471: */
472: display_ptr = displaybuf-1;
473: while (*(++display_ptr) != '\0')
474: ;
475: *(display_ptr++) = ':';
476: #ifdef DNETCONN
477: if (dnet)
478: *(display_ptr++) = ':';
479: #endif
480: #ifdef ISOCONN
481: if (isoconn) {
482: *(display_ptr++) = isochar;
483: }
484: #endif
485: numbuf_ptr = numberbuf;
486: while (*numbuf_ptr != '\0')
487: *(display_ptr++) = *(numbuf_ptr++);
488: if (prop_name[0] != '\0') {
489: char *cp;
490:
491: *(display_ptr++) = '.';
492: for (cp = prop_name; *cp; cp++) *(display_ptr++) = *cp;
493: }
494: *display_ptr = '\0';
495: (void) strcpy(expanded_name, displaybuf);
496: return(fd);
497:
498: }
499:
500: /*
501: * Disconnect from server.
502: */
503:
504: int _XDisconnectDisplay (server)
505:
506: int server;
507:
508: {
509: #ifdef ISOCONN
510: (void)CloseToServer(server);
511: #else /* ISOCONN */
512: (void) close(server);
513: #endif /* ISOCONN */
514: }
515:
516: #undef NULL
517: #define NULL ((char *) 0)
518: /*
519: * This is an OS dependent routine which:
520: * 1) returns as soon as the connection can be written on....
521: * 2) if the connection can be read, must enqueue events and handle errors,
522: * until the connection is writable.
523: */
524: _XWaitForWritable(dpy)
525: Display *dpy;
526: {
527: unsigned long r_mask[MSKCNT];
528: unsigned long w_mask[MSKCNT];
529: int nfound;
530:
531: CLEARBITS(r_mask);
532: CLEARBITS(w_mask);
533:
534: while (1) {
535: BITSET(r_mask, dpy->fd);
536: BITSET(w_mask, dpy->fd);
537:
538: do {
539: #ifdef ISOCONN
540: /*
541: * Note, we shouldnt get any connections to us as we're a client,
542: * But the elements of style say we should check...
543: * and of course, a TDR
544: */
545: int vecp;
546: char *vec[4];
547: struct TSAPdisconnect tds;
548: struct TSAPdisconnect *td = &tds;
549: nfound = TNetAccept(&vecp, vec, dpy->fd + 1, r_mask, w_mask,
550: NULL, NOTOK, td);
551: #ifdef ISODEBUG
552: if (nfound < 0) {
553: int sverrno = errno;
554: fprintf(stderr, "TNetAcc err %d %s\n", errno,
555: TErrString(td->td_reason));
556: errno = sverrno;
557: }
558: #endif /* ISODEBUG */
559: #ifdef ISODEBUG
560: if (vecp > 0) {
561: fprintf(stderr, "Weirdness, connect to a client?\n");
562: }
563: #endif
564: #else /* ISOCONN */
565: nfound = select (dpy->fd + 1, r_mask, w_mask, NULL, NULL);
566: #endif /* ISOCONN */
567: if (nfound < 0 && errno != EINTR)
568: (*_XIOErrorFunction)(dpy);
569: } while (nfound <= 0);
570:
571: if (ANYSET(r_mask)) {
572: char buf[BUFSIZE];
573: long pend_not_register;
574: register long pend;
575: register xEvent *ev;
576:
577: /* find out how much data can be read */
578: if (BytesReadable(dpy->fd, (char *) &pend_not_register) < 0)
579: (*_XIOErrorFunction)(dpy);
580: pend = pend_not_register;
581:
582: /* must read at least one xEvent; if none is pending, then
583: we'll just block waiting for it */
584: if (pend < SIZEOF(xEvent)) pend = SIZEOF(xEvent);
585:
586: /* but we won't read more than the max buffer size */
587: if (pend > BUFSIZE) pend = BUFSIZE;
588:
589: /* round down to an integral number of XReps */
590: pend = (pend / SIZEOF(xEvent)) * SIZEOF(xEvent);
591:
592: _XRead (dpy, buf, pend);
593:
594: /* no space between comma and type or else macro will die */
595: STARTITERATE (ev,xEvent, buf, (pend > 0),
596: (pend -= SIZEOF(xEvent))) {
597: if (ev->u.u.type == X_Error)
598: _XError (dpy, (xError *) ev);
599: else /* it's an event packet; enqueue it */
600: _XEnq (dpy, ev);
601: }
602: ENDITERATE
603: }
604: if (ANYSET(w_mask))
605: return;
606: }
607: }
608:
609:
610: _XWaitForReadable(dpy)
611: Display *dpy;
612: {
613: unsigned long r_mask[MSKCNT];
614: int result;
615:
616: CLEARBITS(r_mask);
617: do {
618: #ifdef ISOCONN
619: /*
620: * Note, we shouldnt get any connections to us as we're a client,
621: * But the elements of style say we should check...
622: * and of course, a TDR
623: */
624: int vecp;
625: char *vec[4];
626: struct TSAPdisconnect tds;
627: struct TSAPdisconnect *td = &tds;
628:
629: BITSET(r_mask, dpy->fd);
630: result = TNetAccept(&vecp, vec, dpy->fd + 1, r_mask, NULL, NULL,
631: NOTOK, td);
632: #else /* ISOCONN */
633: BITSET(r_mask, dpy->fd);
634: result = select(dpy->fd + 1, r_mask, NULL, NULL, NULL);
635: #endif /* ISOCONN */
636: if (result == -1 && errno != EINTR) (*_XIOErrorFunction)(dpy);
637: } while (result <= 0);
638: }
639:
640: static int padlength[4] = {0, 3, 2, 1};
641:
642: _XSendClientPrefix (dpy, client)
643: Display *dpy;
644: xConnClientPrefix *client;
645: {
646: /*
647: * Authorization string stuff.... Must always transmit multiple of 4
648: * bytes.
649: */
650:
651: char *auth_proto = "";
652: int auth_length;
653: char *auth_string = "";
654: int auth_strlen;
655: char pad[3];
656: char buffer[BUFSIZ], *bptr;
657:
658: int bytes=0;
659:
660: auth_length = strlen(auth_proto);
661: auth_strlen = strlen(auth_string);
662: client->nbytesAuthProto = auth_length;
663: client->nbytesAuthString = auth_strlen;
664:
665: bytes = (SIZEOF(xConnClientPrefix) +
666: auth_length + padlength[auth_length & 3] +
667: auth_strlen + padlength[auth_strlen & 3]);
668:
669: bcopy(client, buffer, SIZEOF(xConnClientPrefix));
670: bptr = buffer + SIZEOF(xConnClientPrefix);
671: if (auth_length)
672: {
673: bcopy(auth_proto, bptr, auth_length);
674: bptr += auth_length;
675: if (padlength[auth_length & 3])
676: {
677: bcopy(pad, bptr, padlength[auth_length & 3]);
678: bptr += padlength[auth_length & 3];
679: }
680: }
681: if (auth_strlen)
682: {
683: bcopy(auth_string, bptr, auth_strlen);
684: bptr += auth_strlen;
685: if (padlength[auth_strlen & 3])
686: {
687: bcopy(pad, bptr, padlength[auth_strlen & 3]);
688: bptr += padlength[auth_strlen & 3];
689: }
690: }
691: (void) WriteToServer(dpy->fd, buffer, bytes);
692: return;
693: }
694:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.