]> git.sesse.net Git - rdpsrv/blob - Xserver/lib/xtrans/Xtranssock.c
Import X server from vnc-3.3.7.
[rdpsrv] / Xserver / lib / xtrans / Xtranssock.c
1 /* $XConsortium: Xtranssock.c /main/58 1996/12/04 10:22:50 lehors $ */
2 /* $XFree86: xc/lib/xtrans/Xtranssock.c,v 3.25.2.4 1998/02/01 16:04:34 robin Exp $ */
3 /*
4
5 Copyright (c) 1993, 1994  X Consortium
6
7 Permission is hereby granted, free of charge, to any person obtaining
8 a copy of this software and associated documentation files (the
9 "Software"), to deal in the Software without restriction, including
10 without limitation the rights to use, copy, modify, merge, publish,
11 distribute, sublicense, and/or sell copies of the Software, and to
12 permit persons to whom the Software is furnished to do so, subject to
13 the following conditions:
14
15 The above copyright notice and this permission notice shall be included
16 in all copies or substantial portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 OTHER DEALINGS IN THE SOFTWARE.
25
26 Except as contained in this notice, the name of the X Consortium shall
27 not be used in advertising or otherwise to promote the sale, use or
28 other dealings in this Software without prior written authorization
29 from the X Consortium.
30
31 */
32
33 /* Copyright (c) 1993, 1994 NCR Corporation - Dayton, Ohio, USA
34  *
35  * All Rights Reserved
36  *
37  * Permission to use, copy, modify, and distribute this software and its
38  * documentation for any purpose and without fee is hereby granted, provided
39  * that the above copyright notice appear in all copies and that both that
40  * copyright notice and this permission notice appear in supporting
41  * documentation, and that the name NCR not be used in advertising
42  * or publicity pertaining to distribution of the software without specific,
43  * written prior permission.  NCR makes no representations about the
44  * suitability of this software for any purpose.  It is provided "as is"
45  * without express or implied warranty.
46  *
47  * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
48  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
49  * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
50  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
51  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
52  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
53  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
54  */
55
56 #include <ctype.h>
57 #ifdef XTHREADS
58 #include <X11/Xthreads.h>
59 #endif
60 #ifndef WIN32
61
62 #if defined(TCPCONN) || defined(UNIXCONN)
63 #include <netinet/in.h>
64 #else
65 #ifdef ESIX
66 #include <lan/in.h>
67 #endif
68 #endif
69 #if defined(TCPCONN) || defined(UNIXCONN)
70 #define X_INCLUDE_NETDB_H
71 #define XOS_USE_NO_LOCKING
72 #include <X11/Xos_r.h>
73 #endif
74
75 #ifdef UNIXCONN
76 #ifndef X_NO_SYS_UN
77 #ifndef Lynx
78 #include <sys/un.h>
79 #else
80 #include <un.h>
81 #endif
82 #endif
83 #include <sys/stat.h>
84 #endif
85
86 #if defined(hpux) || defined(__EMX__)
87 #define NO_TCP_H
88 #endif /* hpux */
89 #ifdef MOTOROLA
90 #ifdef SYSV
91 #define NO_TCP_H
92 #endif /* SYSV */
93 #endif /* MOTOROLA */
94 #ifndef NO_TCP_H
95 #ifdef __osf__
96 #include <sys/param.h>
97 #endif /* osf */
98 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) 
99 #include <machine/endian.h>
100 #endif /* __NetBSD__ || __OpenBSD__ || __FreeBSD__ */
101 #include <netinet/tcp.h>
102 #endif /* !NO_TCP_H */
103 #include <sys/ioctl.h>
104 #if defined(SVR4) && !defined(SCO325)
105 #include <sys/filio.h>
106 #endif
107 #if (defined(i386) && defined(SYSV)) || defined(_SEQUENT_)
108 #if !defined(_SEQUENT_) && !defined(ESIX) && !defined(sco)
109 #include <net/errno.h>
110 #endif /* _SEQUENT_  || ESIX  || SCO */
111 #if !defined(ISC) || !defined(I_NREAD) || defined(SCO325)
112 #include <sys/stropts.h>
113 #endif
114 #endif /* i386 && SYSV || _SEQUENT_ */
115
116 #else /* !WIN32 */
117
118 #include <X11/Xwinsock.h>
119 #include <X11/Xw32defs.h>
120 #undef close
121 #define close closesocket
122 #define ECONNREFUSED WSAECONNREFUSED
123 #define EADDRINUSE WSAEADDRINUSE
124 #define EPROTOTYPE WSAEPROTOTYPE
125 #undef EWOULDBLOCK
126 #define EWOULDBLOCK WSAEWOULDBLOCK
127 #undef EINTR
128 #define EINTR WSAEINTR
129 #define X_INCLUDE_NETDB_H
130 #define XOS_USE_MTSAFE_NETDBAPI
131 #include <X11/Xos_r.h>
132 #endif /* WIN32 */
133
134 #if defined(SO_DONTLINGER) && defined(SO_LINGER)
135 #undef SO_DONTLINGER
136 #endif
137
138 #if defined(__EMX__)
139 #if defined(NOT_EMX09A)
140 static int IBMsockInit = 0;
141 #define SocketInitOnce()\
142     if (!IBMsockInit) {\
143         sock_init();\
144         IBMsockInit = 1;\
145     }
146 #undef EINTR
147 #define EINTR SOCEINTR
148 #undef EINVAL
149 #define EINVAL SOCEINVAL
150 #undef errno
151 #define errno sock_errno()
152 #undef close
153 #define close soclose
154 #undef ioctl
155 #define ioctl sockioctl
156 #else
157 #define SocketInitOnce() /**/
158 #endif
159 /* this is still not there */
160 #define SOCKET int
161 #else
162 /* others don't need this */
163 #define SocketInitOnce() /**/
164 #endif
165
166 #define MIN_BACKLOG 128
167 #ifdef SOMAXCONN
168 #if SOMAXCONN > MIN_BACKLOG
169 #define BACKLOG SOMAXCONN
170 #endif
171 #endif
172 #ifndef BACKLOG
173 #define BACKLOG MIN_BACKLOG
174 #endif
175 /*
176  * This is the Socket implementation of the X Transport service layer
177  *
178  * This file contains the implementation for both the UNIX and INET domains,
179  * and can be built for either one, or both.
180  *
181  */
182
183 typedef struct _Sockettrans2dev {      
184     char        *transname;
185     int         family;
186     int         devcotsname;
187     int         devcltsname;
188     int         protocol;
189 } Sockettrans2dev;
190
191 static Sockettrans2dev Sockettrans2devtab[] = {
192 #ifdef TCPCONN
193     {"inet",AF_INET,SOCK_STREAM,SOCK_DGRAM,0},
194     {"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0},
195 #endif /* TCPCONN */
196 #ifdef UNIXCONN
197     {"unix",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0},
198 #if !defined(LOCALCONN)
199     {"local",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0},
200 #endif /* !LOCALCONN */
201 #endif /* UNIXCONN */
202 };
203
204 #define NUMSOCKETFAMILIES (sizeof(Sockettrans2devtab)/sizeof(Sockettrans2dev))
205
206
207 #ifdef UNIXCONN
208
209 #ifdef hpux
210
211 #if defined(X11_t)
212 #define UNIX_PATH "/usr/spool/sockets/X11/"
213 #define UNIX_DIR "/usr/spool/sockets/X11"
214 #define OLD_UNIX_PATH "/tmp/.X11-unix/X"
215 #endif /* X11_t */
216 #if defined(XIM_t)
217 #define UNIX_PATH "/usr/spool/sockets/XIM/"
218 #define UNIX_DIR "/usr/spool/sockets/XIM"
219 #define OLD_UNIX_PATH "/tmp/.XIM-unix/XIM"
220 #endif /* XIM_t */
221 #if defined(FS_t) || defined(FONT_t)
222 #define UNIX_PATH "/usr/spool/sockets/fontserv/"
223 #define UNIX_DIR "/usr/spool/sockets/fontserv"
224 #endif /* FS_t || FONT_t */
225 #if defined(ICE_t)
226 #define UNIX_PATH "/usr/spool/sockets/ICE/"
227 #define UNIX_DIR "/usr/spool/sockets/ICE"
228 #endif /* ICE_t */
229 #if defined(TEST_t)
230 #define UNIX_PATH "/usr/spool/sockets/xtrans_test/"
231 #define UNIX_DIR "/usr/spool/sockets/xtrans_test"
232 #endif
233
234 #else /* !hpux */
235
236 #if defined(X11_t)
237 #define UNIX_PATH "/tmp/.X11-unix/X"
238 #define UNIX_DIR "/tmp/.X11-unix"
239 #endif /* X11_t */
240 #if defined(XIM_t)
241 #define UNIX_PATH "/tmp/.XIM-unix/XIM"
242 #define UNIX_DIR "/tmp/.XIM-unix"
243 #endif /* XIM_t */
244 #if defined(FS_t) || defined(FONT_t)
245 #define UNIX_PATH "/tmp/.font-unix/fs"
246 #define UNIX_DIR "/tmp/.font-unix"
247 #endif /* FS_t || FONT_t */
248 #if defined(ICE_t)
249 #define UNIX_PATH "/tmp/.ICE-unix/"
250 #define UNIX_DIR "/tmp/.ICE-unix"
251 #endif /* ICE_t */
252 #if defined(TEST_t)
253 #define UNIX_PATH "/tmp/.Test-unix/test"
254 #define UNIX_DIR "/tmp/.Test-unix"
255 #endif
256
257 #endif /* hpux */
258
259 #endif /* UNIXCONN */
260
261
262 /*
263  * These are some utility function used by the real interface function below.
264  */
265
266 static int
267 TRANS(SocketSelectFamily) (family)
268
269 char *family;
270
271 {
272     int     i;
273
274     PRMSG (3,"SocketSelectFamily(%s)\n", family, 0, 0);
275
276     for (i = 0; i < NUMSOCKETFAMILIES;i++)
277     {
278         if (!strcmp (family, Sockettrans2devtab[i].transname))
279             return i;
280     }
281
282     return -1;
283 }
284
285
286 /*
287  * This function gets the local address of the socket and stores it in the
288  * XtransConnInfo structure for the connection.
289  */
290
291 static int
292 TRANS(SocketINETGetAddr) (ciptr)
293
294 XtransConnInfo ciptr;
295
296 {
297     struct sockaddr_in  sockname;
298 #if defined(SVR4) || defined(SCO325)
299     size_t namelen = sizeof sockname;
300 #else
301     int namelen = sizeof sockname;
302 #endif
303
304     PRMSG (3,"SocketINETGetAddr(%x)\n", ciptr, 0, 0);
305
306     if (getsockname (ciptr->fd,(struct sockaddr *) &sockname, &namelen) < 0)
307     {
308         PRMSG (1,"SocketINETGetAddr: getsockname() failed: %d\n",
309             EGET(),0, 0);
310         return -1;
311     }
312
313     /*
314      * Everything looks good: fill in the XtransConnInfo structure.
315      */
316
317     if ((ciptr->addr = (char *) xalloc (namelen)) == NULL)
318     {
319         PRMSG (1,
320             "SocketINETGetAddr: Can't allocate space for the addr\n",
321             0, 0, 0);
322         return -1;
323     }
324
325     ciptr->family = sockname.sin_family;
326     ciptr->addrlen = namelen;
327     memcpy (ciptr->addr, &sockname, ciptr->addrlen);
328
329     return 0;
330 }
331
332
333 /*
334  * This function gets the remote address of the socket and stores it in the
335  * XtransConnInfo structure for the connection.
336  */
337
338 static int
339 TRANS(SocketINETGetPeerAddr) (ciptr)
340
341 XtransConnInfo ciptr;
342
343 {
344     struct sockaddr_in  sockname;
345 #if defined(SVR4) || defined(SCO325)
346     size_t namelen = sizeof sockname;
347 #else
348     int namelen = sizeof sockname;
349 #endif
350
351     PRMSG (3,"SocketINETGetPeerAddr(%x)\n", ciptr, 0, 0);
352
353     if (getpeername (ciptr->fd, (struct sockaddr *) &sockname, &namelen) < 0)
354     {
355         PRMSG (1,"SocketINETGetPeerAddr: getpeername() failed: %d\n",
356             EGET(), 0, 0);
357         return -1;
358     }
359
360     /*
361      * Everything looks good: fill in the XtransConnInfo structure.
362      */
363
364     if ((ciptr->peeraddr = (char *) xalloc (namelen)) == NULL)
365     {
366         PRMSG (1,
367            "SocketINETGetPeerAddr: Can't allocate space for the addr\n",
368            0, 0, 0);
369         return -1;
370     }
371
372     ciptr->peeraddrlen = namelen;
373     memcpy (ciptr->peeraddr, &sockname, ciptr->peeraddrlen);
374
375     return 0;
376 }
377
378
379 static XtransConnInfo
380 TRANS(SocketOpen) (i, type)
381
382 int i;
383 int type;
384
385 {
386     XtransConnInfo      ciptr;
387
388     PRMSG (3,"SocketOpen(%d,%d)\n", i, type, 0);
389
390     if ((ciptr = (XtransConnInfo) xcalloc (
391         1, sizeof(struct _XtransConnInfo))) == NULL)
392     {
393         PRMSG (1, "SocketOpen: malloc failed\n", 0, 0, 0);
394         return NULL;
395     }
396
397     if ((ciptr->fd = socket(Sockettrans2devtab[i].family, type,
398         Sockettrans2devtab[i].protocol)) < 0
399 #ifndef WIN32
400 #if (defined(X11_t) && !defined(USE_POLL)) || defined(FS_t) || defined(FONT_t)
401        || ciptr->fd >= TRANS_OPEN_MAX
402 #endif
403 #endif
404       ) {
405         PRMSG (1, "SocketOpen: socket() failed for %s\n",
406             Sockettrans2devtab[i].transname, 0, 0);
407
408         xfree ((char *) ciptr);
409         return NULL;
410     }
411
412 #ifdef TCP_NODELAY
413     if (Sockettrans2devtab[i].family == AF_INET)
414     {
415         /*
416          * turn off TCP coalescence for INET sockets
417          */
418
419         int tmp = 1;
420         setsockopt (ciptr->fd, IPPROTO_TCP, TCP_NODELAY,
421             (char *) &tmp, sizeof (int));
422     }
423 #endif
424
425     return ciptr;
426 }
427
428
429 #ifdef TRANS_REOPEN
430
431 static XtransConnInfo
432 TRANS(SocketReopen) (i, type, fd, port)
433
434 int  i;
435 int  type;
436 int  fd;
437 char *port;
438
439 {
440     XtransConnInfo      ciptr;
441
442     PRMSG (3,"SocketReopen(%d,%d,%s)\n", type, fd, port);
443
444     if ((ciptr = (XtransConnInfo) xcalloc (
445         1, sizeof(struct _XtransConnInfo))) == NULL)
446     {
447         PRMSG (1, "SocketReopen: malloc failed\n", 0, 0, 0);
448         return NULL;
449     }
450
451     ciptr->fd = fd;
452
453     return ciptr;
454 }
455
456 #endif /* TRANS_REOPEN */
457
458
459 /*
460  * These functions are the interface supplied in the Xtransport structure
461  */
462
463 #ifdef TRANS_CLIENT
464
465 static XtransConnInfo
466 TRANS(SocketOpenCOTSClient) (thistrans, protocol, host, port)
467
468 Xtransport *thistrans;
469 char       *protocol;
470 char       *host;
471 char       *port;
472
473 {
474     XtransConnInfo      ciptr;
475     int                 i;
476
477     PRMSG (2, "SocketOpenCOTSClient(%s,%s,%s)\n",
478         protocol, host, port);
479
480     SocketInitOnce();
481
482     if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0)
483     {
484         PRMSG (1,
485        "SocketOpenCOTSClient: Unable to determine socket type for %s\n",
486             thistrans->TransName, 0, 0);
487         return NULL;
488     }
489
490     if ((ciptr = TRANS(SocketOpen) (
491         i, Sockettrans2devtab[i].devcotsname)) == NULL)
492     {
493         PRMSG (1,"SocketOpenCOTSClient: Unable to open socket for %s\n",
494             thistrans->TransName, 0, 0);
495         return NULL;
496     }
497
498     /* Save the index for later use */
499
500     ciptr->index = i;
501
502     return ciptr;
503 }
504
505 #endif /* TRANS_CLIENT */
506
507
508 #ifdef TRANS_SERVER
509
510 static XtransConnInfo
511 TRANS(SocketOpenCOTSServer) (thistrans, protocol, host, port)
512
513 Xtransport *thistrans;
514 char       *protocol;
515 char       *host;
516 char       *port;
517
518 {
519     XtransConnInfo      ciptr;
520     int i;
521
522     PRMSG (2,"SocketOpenCOTSServer(%s,%s,%s)\n", protocol, host, port);
523
524     SocketInitOnce();
525
526     if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0)
527     {
528         PRMSG (1,
529        "SocketOpenCOTSServer: Unable to determine socket type for %s\n",
530             thistrans->TransName, 0, 0);
531         return NULL;
532     }
533
534     if ((ciptr = TRANS(SocketOpen) (
535         i, Sockettrans2devtab[i].devcotsname)) == NULL)
536     {
537         PRMSG (1,"SocketOpenCOTSServer: Unable to open socket for %s\n",
538             thistrans->TransName, 0, 0);
539         return NULL;
540     }
541
542     /*
543      * Using this prevents the bind() check for an existing server listening
544      * on the same port, but it is required for other reasons.
545      */
546 #ifdef SO_REUSEADDR
547
548     /*
549      * SO_REUSEADDR only applied to AF_INET
550      */
551
552     if (Sockettrans2devtab[i].family == AF_INET)
553     {
554         int one = 1;
555         setsockopt (ciptr->fd, SOL_SOCKET, SO_REUSEADDR,
556                     (char *) &one, sizeof (int));
557     }
558 #endif
559
560     /* Save the index for later use */
561
562     ciptr->index = i;
563
564     return ciptr;
565 }
566
567 #endif /* TRANS_SERVER */
568
569
570 #ifdef TRANS_CLIENT
571
572 static XtransConnInfo
573 TRANS(SocketOpenCLTSClient) (thistrans, protocol, host, port)
574
575 Xtransport *thistrans;
576 char       *protocol;
577 char       *host;
578 char       *port;
579
580 {
581     XtransConnInfo      ciptr;
582     int                 i;
583
584     PRMSG (2,"SocketOpenCLTSClient(%s,%s,%s)\n", protocol, host, port);
585
586     SocketInitOnce();
587
588     if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0)
589     {
590         PRMSG (1,
591        "SocketOpenCLTSClient: Unable to determine socket type for %s\n",
592             thistrans->TransName, 0, 0);
593         return NULL;
594     }
595
596     if ((ciptr = TRANS(SocketOpen) (
597         i, Sockettrans2devtab[i].devcotsname)) == NULL)
598     {
599         PRMSG (1,"SocketOpenCLTSClient: Unable to open socket for %s\n",
600               thistrans->TransName, 0, 0);
601         return NULL;
602     }
603
604     /* Save the index for later use */
605
606     ciptr->index = i;
607
608     return ciptr;
609 }
610
611 #endif /* TRANS_CLIENT */
612
613
614 #ifdef TRANS_SERVER
615
616 static XtransConnInfo
617 TRANS(SocketOpenCLTSServer) (thistrans, protocol, host, port)
618
619 Xtransport *thistrans;
620 char       *protocol;
621 char       *host;
622 char       *port;
623
624 {
625     XtransConnInfo      ciptr;
626     int i;
627
628     PRMSG (2,"SocketOpenCLTSServer(%s,%s,%s)\n", protocol, host, port);
629
630     SocketInitOnce();
631
632     if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0)
633     {
634         PRMSG (1,
635        "SocketOpenCLTSServer: Unable to determine socket type for %s\n",
636               thistrans->TransName, 0, 0);
637         return NULL;
638     }
639
640     if ((ciptr = TRANS(SocketOpen) (
641         i, Sockettrans2devtab[i].devcotsname)) == NULL)
642     {
643         PRMSG (1,"SocketOpenCLTSServer: Unable to open socket for %s\n",
644               thistrans->TransName, 0, 0);
645         return NULL;
646     }
647
648     /* Save the index for later use */
649
650     ciptr->index = i;
651
652     return ciptr;
653 }
654
655 #endif /* TRANS_SERVER */
656
657
658 #ifdef TRANS_REOPEN
659
660 static XtransConnInfo
661 TRANS(SocketReopenCOTSServer) (thistrans, fd, port)
662
663 Xtransport *thistrans;
664 int        fd;
665 char       *port;
666
667 {
668     XtransConnInfo      ciptr;
669     int                 i;
670
671     PRMSG (2,
672         "SocketReopenCOTSServer(%d, %s)\n", fd, port, 0);
673
674     SocketInitOnce();
675
676     if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0)
677     {
678         PRMSG (1,
679        "SocketReopenCOTSServer: Unable to determine socket type for %s\n",
680             thistrans->TransName, 0, 0);
681         return NULL;
682     }
683
684     if ((ciptr = TRANS(SocketReopen) (
685         i, Sockettrans2devtab[i].devcotsname, fd, port)) == NULL)
686     {
687         PRMSG (1,
688             "SocketReopenCOTSServer: Unable to reopen socket for %s\n",
689             thistrans->TransName, 0, 0);
690         return NULL;
691     }
692
693     /* Save the index for later use */
694
695     ciptr->index = i;
696
697     return ciptr;
698 }
699
700 static XtransConnInfo
701 TRANS(SocketReopenCLTSServer) (thistrans, fd, port)
702
703 Xtransport *thistrans;
704 int        fd;
705 char       *port;
706
707 {
708     XtransConnInfo      ciptr;
709     int                 i;
710
711     PRMSG (2,
712         "SocketReopenCLTSServer(%d, %s)\n", fd, port, 0);
713
714     SocketInitOnce();
715
716     if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0)
717     {
718         PRMSG (1,
719        "SocketReopenCLTSServer: Unable to determine socket type for %s\n",
720               thistrans->TransName, 0, 0);
721         return NULL;
722     }
723
724     if ((ciptr = TRANS(SocketReopen) (
725         i, Sockettrans2devtab[i].devcotsname, fd, port)) == NULL)
726     {
727         PRMSG (1,
728              "SocketReopenCLTSServer: Unable to reopen socket for %s\n",
729              thistrans->TransName, 0, 0);
730         return NULL;
731     }
732
733     /* Save the index for later use */
734
735     ciptr->index = i;
736
737     return ciptr;
738 }
739
740 #endif /* TRANS_REOPEN */
741
742
743 static int
744 TRANS(SocketSetOption) (ciptr, option, arg)
745
746 XtransConnInfo  ciptr;
747 int             option;
748 int             arg;
749
750 {
751     PRMSG (2,"SocketSetOption(%d,%d,%d)\n", ciptr->fd, option, arg);
752
753     return -1;
754 }
755
756
757 #ifdef TRANS_SERVER
758
759 static int
760 TRANS(SocketCreateListener) (ciptr, sockname, socknamelen)
761
762 XtransConnInfo  ciptr;
763 struct sockaddr *sockname;
764 int             socknamelen;
765
766 {
767     int namelen = socknamelen;
768     int fd = ciptr->fd;
769     int retry;
770
771     PRMSG (3, "SocketCreateListener(%x,%d)\n", ciptr, fd, 0);
772
773     if (Sockettrans2devtab[ciptr->index].family == AF_INET)
774         retry = 20;
775     else
776         retry = 0;
777
778     while (bind (fd, (struct sockaddr *) sockname, namelen) < 0)
779     {
780         if (errno == EADDRINUSE)
781             return TRANS_ADDR_IN_USE;
782
783         if (retry-- == 0) {
784             PRMSG (1, "SocketCreateListener: failed to bind listener\n",
785                 0, 0, 0);
786             close (fd);
787             return TRANS_CREATE_LISTENER_FAILED;
788         }
789 #ifdef SO_REUSEADDR
790         sleep (1);
791 #else
792         sleep (10);
793 #endif /* SO_REUSEDADDR */
794     }
795
796     if (Sockettrans2devtab[ciptr->index].family == AF_INET) {
797 #ifdef SO_DONTLINGER
798         setsockopt (fd, SOL_SOCKET, SO_DONTLINGER, (char *) NULL, 0);
799 #else
800 #ifdef SO_LINGER
801     {
802         static int linger[2] = { 0, 0 };
803         setsockopt (fd, SOL_SOCKET, SO_LINGER,
804                 (char *) linger, sizeof (linger));
805     }
806 #endif
807 #endif
808 }
809
810     if (listen (fd, BACKLOG) < 0)
811     {
812         PRMSG (1, "SocketCreateListener: listen() failed\n", 0, 0, 0);
813         close (fd);
814         return TRANS_CREATE_LISTENER_FAILED;
815     }
816         
817     /* Set a flag to indicate that this connection is a listener */
818
819     ciptr->flags = 1;
820
821     return 0;
822 }
823
824
825 #ifdef TCPCONN
826 static int
827 TRANS(SocketINETCreateListener) (ciptr, port)
828
829 XtransConnInfo  ciptr;
830 char            *port;
831
832 {
833     struct sockaddr_in  sockname;
834     int         namelen = sizeof(sockname);
835     int         status;
836     short       tmpport;
837     _Xgetservbynameparams sparams;
838     struct servent *servp;
839
840 #define PORTBUFSIZE     64      /* what is a real size for this? */
841
842     char        portbuf[PORTBUFSIZE];
843     
844     PRMSG (2, "SocketINETCreateListener(%s)\n", port, 0, 0);
845
846 #ifdef X11_t
847     /*
848      * X has a well known port, that is transport dependent. It is easier
849      * to handle it here, than try and come up with a transport independent
850      * representation that can be passed in and resolved the usual way.
851      *
852      * The port that is passed here is really a string containing the idisplay
853      * from ConnectDisplay().
854      */
855
856     if (is_numeric (port))
857     {
858         tmpport = (short) atoi (port);
859
860         sprintf (portbuf,"%d", X_TCP_PORT+tmpport);
861     }
862     else
863         strncpy (portbuf, port, PORTBUFSIZE);
864
865     port = portbuf;
866 #endif
867
868     if (port && *port)
869     {
870         /* Check to see if the port string is just a number (handles X11) */
871
872         if (!is_numeric (port))
873         {
874             if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL)
875             {
876                 PRMSG (1,
877              "SocketINETCreateListener: Unable to get service for %s\n",
878                       port, 0, 0);
879                 return TRANS_CREATE_LISTENER_FAILED;
880             }
881             sockname.sin_port = servp->s_port;
882         }
883         else
884         {
885             tmpport = (short) atoi (port);
886             sockname.sin_port = htons (tmpport);
887         }
888     }
889     else
890         sockname.sin_port = htons (0);
891
892 #ifdef BSD44SOCKETS
893     sockname.sin_len = sizeof (sockname);
894 #endif
895     sockname.sin_family = AF_INET;
896     sockname.sin_addr.s_addr = htonl (INADDR_ANY);
897
898     if ((status = TRANS(SocketCreateListener) (ciptr,
899         (struct sockaddr *) &sockname, namelen)) < 0)
900     {
901         PRMSG (1,
902     "SocketINETCreateListener: ...SocketCreateListener() failed\n",
903             0, 0, 0);
904         return status;
905     }
906
907     if (TRANS(SocketINETGetAddr) (ciptr) < 0)
908     {
909         PRMSG (1,
910        "SocketINETCreateListener: ...SocketINETGetAddr() failed\n",
911             0, 0, 0);
912         return TRANS_CREATE_LISTENER_FAILED;
913     }
914
915     return 0;
916 }
917
918 #endif /* SOCKCONN */
919
920
921 #ifdef UNIXCONN
922
923 static
924 TRANS(SocketUNIXCreateListener) (ciptr, port)
925
926 XtransConnInfo ciptr;
927 char *port;
928
929 {
930     struct sockaddr_un  sockname;
931     int                 namelen;
932     int                 oldUmask;
933     int                 status;
934
935     PRMSG (2, "SocketUNIXCreateListener(%s)\n",
936         port ? port : "NULL", 0, 0);
937
938     /* Make sure the directory is created */
939
940     oldUmask = umask (0);
941
942 #ifdef UNIX_DIR
943     if (!mkdir (UNIX_DIR, 01777))
944         chmod (UNIX_DIR, 01777);
945 #endif
946
947     sockname.sun_family = AF_UNIX;
948
949     if (port && *port) {
950         if (*port == '/') { /* a full pathname */
951             sprintf (sockname.sun_path, "%s", port);
952         } else {
953             sprintf (sockname.sun_path, "%s%s", UNIX_PATH, port);
954         }
955     } else {
956         sprintf (sockname.sun_path, "%s%d", UNIX_PATH, getpid());
957     }
958
959 #if defined(BSD44SOCKETS) && !defined(Lynx)
960     sockname.sun_len = strlen(sockname.sun_path);
961     namelen = SUN_LEN(&sockname);
962 #else
963     namelen = strlen(sockname.sun_path) + sizeof(sockname.sun_family);
964 #endif
965
966     unlink (sockname.sun_path);
967
968     if ((status = TRANS(SocketCreateListener) (ciptr,
969         (struct sockaddr *) &sockname, namelen)) < 0)
970     {
971         PRMSG (1,
972     "SocketUNIXCreateListener: ...SocketCreateListener() failed\n",
973             0, 0, 0);
974         return status;
975     }
976
977     /*
978      * Now that the listener is esablished, create the addr info for
979      * this connection. getpeername() doesn't work for UNIX Domain Sockets
980      * on some systems (hpux at least), so we will just do it manually, instead
981      * of calling something like TRANS(SocketUNIXGetAddr).
982      */
983
984     namelen = sizeof (sockname); /* this will always make it the same size */
985
986     if ((ciptr->addr = (char *) xalloc (namelen)) == NULL)
987     {
988         PRMSG (1,
989         "SocketUNIXCreateListener: Can't allocate space for the addr\n",
990             0, 0, 0);
991         return TRANS_CREATE_LISTENER_FAILED;
992     }
993
994     ciptr->family = sockname.sun_family;
995     ciptr->addrlen = namelen;
996     memcpy (ciptr->addr, &sockname, ciptr->addrlen);
997
998     (void) umask (oldUmask);
999
1000     return 0;
1001 }
1002
1003
1004 static
1005 TRANS(SocketUNIXResetListener) (ciptr)
1006
1007 XtransConnInfo ciptr;
1008
1009 {
1010     /*
1011      * See if the unix domain socket has disappeared.  If it has, recreate it.
1012      */
1013
1014     struct sockaddr_un  *unsock = (struct sockaddr_un *) ciptr->addr;
1015     struct stat         statb;
1016     int                 status = TRANS_RESET_NOOP;
1017     void                TRANS(FreeConnInfo) ();
1018
1019     PRMSG (3, "SocketUNIXResetListener(%x,%d)\n", ciptr, ciptr->fd, 0);
1020
1021     if (stat (unsock->sun_path, &statb) == -1 ||
1022         ((statb.st_mode & S_IFMT) !=
1023 #if (defined (sun) && defined(SVR4)) || defined(NCR) || defined(SCO) || defined(sco) || !defined(S_IFSOCK)
1024                         S_IFIFO))
1025 #else
1026                         S_IFSOCK))
1027 #endif
1028     {
1029         int oldUmask = umask (0);
1030
1031 #ifdef UNIX_DIR
1032         if (!mkdir (UNIX_DIR, 01777))
1033             chmod (UNIX_DIR, 01777);
1034 #endif
1035
1036         close (ciptr->fd);
1037         unlink (unsock->sun_path);
1038
1039         if ((ciptr->fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
1040         {
1041             TRANS(FreeConnInfo) (ciptr);
1042             return TRANS_RESET_FAILURE;
1043         }
1044
1045         if (bind (ciptr->fd, (struct sockaddr *) unsock, ciptr->addrlen) < 0)
1046         {
1047             close (ciptr->fd);
1048             TRANS(FreeConnInfo) (ciptr);
1049             return TRANS_RESET_FAILURE;
1050         }
1051
1052         if (listen (ciptr->fd, BACKLOG) < 0)
1053         {
1054             close (ciptr->fd);
1055             TRANS(FreeConnInfo) (ciptr);
1056             return TRANS_RESET_FAILURE;
1057         }
1058
1059         umask (oldUmask);
1060
1061         status = TRANS_RESET_NEW_FD;
1062     }
1063
1064     return status;
1065 }
1066
1067 #endif /* UNIXCONN */
1068
1069
1070 #ifdef TCPCONN
1071
1072 static XtransConnInfo
1073 TRANS(SocketINETAccept) (ciptr, status)
1074
1075 XtransConnInfo ciptr;
1076 int            *status;
1077
1078 {
1079     XtransConnInfo      newciptr;
1080     struct sockaddr_in  sockname;
1081     int                 namelen = sizeof(sockname);
1082
1083     PRMSG (2, "SocketINETAccept(%x,%d)\n", ciptr, ciptr->fd, 0);
1084
1085     if ((newciptr = (XtransConnInfo) xcalloc (
1086         1, sizeof(struct _XtransConnInfo))) == NULL)
1087     {
1088         PRMSG (1, "SocketINETAccept: malloc failed\n", 0, 0, 0);
1089         *status = TRANS_ACCEPT_BAD_MALLOC;
1090         return NULL;
1091     }
1092
1093     if ((newciptr->fd = accept (ciptr->fd,
1094         (struct sockaddr *) &sockname, &namelen)) < 0)
1095     {
1096         PRMSG (1, "SocketINETAccept: accept() failed\n", 0, 0, 0);
1097         xfree (newciptr);
1098         *status = TRANS_ACCEPT_FAILED;
1099         return NULL;
1100     }
1101
1102 #ifdef TCP_NODELAY
1103     {
1104         /*
1105          * turn off TCP coalescence for INET sockets
1106          */
1107
1108         int tmp = 1;
1109         setsockopt (newciptr->fd, IPPROTO_TCP, TCP_NODELAY,
1110             (char *) &tmp, sizeof (int));
1111     }
1112 #endif
1113
1114     /*
1115      * Get this address again because the transport may give a more 
1116      * specific address now that a connection is established.
1117      */
1118
1119     if (TRANS(SocketINETGetAddr) (newciptr) < 0)
1120     {
1121         PRMSG (1,
1122             "SocketINETAccept: ...SocketINETGetAddr() failed:\n",
1123             0, 0, 0);
1124         close (newciptr->fd);
1125         xfree (newciptr);
1126         *status = TRANS_ACCEPT_MISC_ERROR;
1127         return NULL;
1128     }
1129
1130     if (TRANS(SocketINETGetPeerAddr) (newciptr) < 0)
1131     {
1132         PRMSG (1,
1133           "SocketINETAccept: ...SocketINETGetPeerAddr() failed:\n",
1134                 0, 0, 0);
1135         close (newciptr->fd);
1136         if (newciptr->addr) xfree (newciptr->addr);
1137         xfree (newciptr);
1138         *status = TRANS_ACCEPT_MISC_ERROR;
1139         return NULL;
1140     }
1141
1142     *status = 0;
1143
1144     return newciptr;
1145 }
1146
1147 #endif /* TCPCONN */
1148
1149
1150 #ifdef UNIXCONN
1151 static XtransConnInfo
1152 TRANS(SocketUNIXAccept) (ciptr, status)
1153
1154 XtransConnInfo ciptr;
1155 int            *status;
1156
1157 {
1158     XtransConnInfo      newciptr;
1159     struct sockaddr_un  sockname;
1160 #if defined(SVR4) || defined(SCO325)
1161     size_t namelen = sizeof sockname;
1162 #else
1163     int namelen = sizeof sockname;
1164 #endif
1165
1166     PRMSG (2, "SocketUNIXAccept(%x,%d)\n", ciptr, ciptr->fd, 0);
1167
1168     if ((newciptr = (XtransConnInfo) xcalloc (
1169         1, sizeof(struct _XtransConnInfo))) == NULL)
1170     {
1171         PRMSG (1, "SocketUNIXAccept: malloc() failed\n", 0, 0, 0);
1172         *status = TRANS_ACCEPT_BAD_MALLOC;
1173         return NULL;
1174     }
1175
1176     if ((newciptr->fd = accept (ciptr->fd,
1177         (struct sockaddr *) &sockname, &namelen)) < 0)
1178     {
1179         PRMSG (1, "SocketUNIXAccept: accept() failed\n", 0, 0, 0);
1180         xfree (newciptr);
1181         *status = TRANS_ACCEPT_FAILED;
1182         return NULL;
1183     }
1184
1185     /*
1186      * Get the socket name and the peer name from the listener socket,
1187      * since this is unix domain.
1188      */
1189
1190     if ((newciptr->addr = (char *) xalloc (ciptr->addrlen)) == NULL)
1191     {
1192         PRMSG (1,
1193         "SocketUNIXAccept: Can't allocate space for the addr\n",
1194               0, 0, 0);
1195         close (newciptr->fd);
1196         xfree (newciptr);
1197         *status = TRANS_ACCEPT_BAD_MALLOC;
1198         return NULL;
1199     }
1200
1201
1202     newciptr->addrlen = ciptr->addrlen;
1203     memcpy (newciptr->addr, ciptr->addr, newciptr->addrlen);
1204
1205     if ((newciptr->peeraddr = (char *) xalloc (ciptr->addrlen)) == NULL)
1206     {
1207         PRMSG (1,
1208               "SocketUNIXAccept: Can't allocate space for the addr\n",
1209               0, 0, 0);
1210         close (newciptr->fd);
1211         if (newciptr->addr) xfree (newciptr->addr);
1212         xfree (newciptr);
1213         *status = TRANS_ACCEPT_BAD_MALLOC;
1214         return NULL;
1215     }
1216     
1217     newciptr->peeraddrlen = ciptr->addrlen;
1218     memcpy (newciptr->peeraddr, ciptr->addr, newciptr->addrlen);
1219
1220     newciptr->family = AF_UNIX;
1221
1222     *status = 0;
1223
1224     return newciptr;
1225 }
1226
1227 #endif /* UNIXCONN */
1228
1229 #endif /* TRANS_SERVER */
1230
1231
1232 #ifdef TRANS_CLIENT
1233
1234 #ifdef TCPCONN
1235 static int
1236 TRANS(SocketINETConnect) (ciptr, host, port)
1237
1238 XtransConnInfo  ciptr;
1239 char            *host;
1240 char            *port;
1241
1242 {
1243     struct sockaddr_in  sockname;
1244 #if defined(SVR4) || defined(SCO325)
1245     size_t namelen = sizeof sockname;
1246 #else
1247     int namelen = sizeof sockname;
1248 #endif
1249     _Xgethostbynameparams hparams;
1250     _Xgetservbynameparams sparams;
1251     struct hostent      *hostp;
1252     struct servent      *servp;
1253
1254 #define PORTBUFSIZE     64      /* what is a real size for this? */
1255     char        portbuf[PORTBUFSIZE];
1256
1257     int                 ret;
1258     short               tmpport;
1259     unsigned long       tmpaddr;
1260     char                hostnamebuf[256];               /* tmp space */
1261
1262     PRMSG (2,"SocketINETConnect(%d,%s,%s)\n", ciptr->fd, host, port);
1263
1264     if (!host)
1265     {
1266         hostnamebuf[0] = '\0';
1267         (void) TRANS(GetHostname) (hostnamebuf, sizeof hostnamebuf);
1268         host = hostnamebuf;
1269     }
1270
1271 #ifdef X11_t
1272     /*
1273      * X has a well known port, that is transport dependent. It is easier
1274      * to handle it here, than try and come up with a transport independent
1275      * representation that can be passed in and resolved the usual way.
1276      *
1277      * The port that is passed here is really a string containing the idisplay
1278      * from ConnectDisplay().
1279      */
1280
1281     if (is_numeric (port))
1282     {
1283         tmpport = (short) atoi (port);
1284
1285         sprintf (portbuf, "%d", X_TCP_PORT + tmpport);
1286     }
1287     else
1288 #endif
1289         strncpy (portbuf, port, PORTBUFSIZE);
1290
1291     /*
1292      * Build the socket name.
1293      */
1294
1295 #ifdef BSD44SOCKETS
1296     sockname.sin_len = sizeof (struct sockaddr_in);
1297 #endif
1298     sockname.sin_family = AF_INET;
1299
1300     /*
1301      * fill in sin_addr
1302      */
1303
1304     /* check for ww.xx.yy.zz host string */
1305
1306     if (isascii (host[0]) && isdigit (host[0])) {
1307         tmpaddr = inet_addr (host); /* returns network byte order */
1308     } else {
1309         tmpaddr = -1;
1310     }
1311
1312     PRMSG (4,"SocketINETConnect: inet_addr(%s) = %x\n",
1313         host, tmpaddr, 0);
1314
1315     if (tmpaddr == -1)
1316     {
1317         if ((hostp = _XGethostbyname(host,hparams)) == NULL)
1318         {
1319             PRMSG (1,"SocketINETConnect: Can't get address for %s\n",
1320                   host, 0, 0);
1321             ESET(EINVAL);
1322             return TRANS_CONNECT_FAILED;
1323         }
1324         if (hostp->h_addrtype != AF_INET)  /* is IP host? */
1325         {
1326             PRMSG (1,"SocketINETConnect: not INET host%s\n",
1327                   host, 0, 0);
1328             ESET(EPROTOTYPE);
1329             return TRANS_CONNECT_FAILED;
1330         }
1331         
1332 #if defined(CRAY) && defined(OLDTCP)
1333         /* Only Cray UNICOS3 and UNICOS4 will define this */
1334         {
1335         long t;
1336         memcpy ((char *)&t, (char *) hostp->h_addr, sizeof (t));
1337         sockname.sin_addr = t;
1338         }
1339 #else
1340         memcpy ((char *) &sockname.sin_addr, (char *) hostp->h_addr,
1341                 sizeof (sockname.sin_addr));
1342 #endif /* CRAY and OLDTCP */
1343         
1344     }
1345 else
1346     {
1347 #if defined(CRAY) && defined(OLDTCP)
1348         /* Only Cray UNICOS3 and UNICOS4 will define this */
1349         sockname.sin_addr = tmpaddr;
1350 #else
1351         sockname.sin_addr.s_addr = tmpaddr;
1352 #endif /* CRAY and OLDTCP */
1353     }
1354
1355     /*
1356      * fill in sin_port
1357      */
1358     
1359     /* Check for number in the port string */
1360
1361     if (!is_numeric (portbuf))
1362     {
1363         if ((servp = _XGetservbyname (portbuf,"tcp",sparams)) == NULL)
1364         {
1365             PRMSG (1,"SocketINETConnect: Can't get service for %s\n",
1366                   portbuf, 0, 0);
1367             return TRANS_CONNECT_FAILED;
1368         }
1369         sockname.sin_port = servp->s_port;
1370     }
1371     else
1372     {
1373         tmpport = (short) atoi (portbuf);
1374         sockname.sin_port = htons (tmpport);
1375     }
1376     
1377     PRMSG (4,"SocketINETConnect: sockname.sin_port = %d\n",
1378           ntohs(sockname.sin_port), 0, 0);
1379
1380     /*
1381      * Do the connect()
1382      */
1383
1384     if (connect (ciptr->fd, (struct sockaddr *) &sockname, namelen) < 0)
1385     {
1386 #ifdef WIN32
1387         int olderrno = WSAGetLastError();
1388 #else
1389         int olderrno = errno;
1390 #endif
1391
1392         PRMSG (1,"SocketINETConnect: Can't connect: errno = %d\n",
1393           EGET(),0, 0);
1394
1395         /*
1396          * If the error was ECONNREFUSED, the server may be overloaded
1397          * and we should try again.
1398          *
1399          * If the error was EINTR, the connect was interrupted and we
1400          * should try again.
1401          */
1402
1403         if (olderrno == ECONNREFUSED || olderrno == EINTR)
1404             return TRANS_TRY_CONNECT_AGAIN;
1405         else
1406             return TRANS_CONNECT_FAILED;        
1407     }
1408     
1409
1410     /*
1411      * Sync up the address fields of ciptr.
1412      */
1413     
1414     if (TRANS(SocketINETGetAddr) (ciptr) < 0)
1415     {
1416         PRMSG (1,
1417            "SocketINETConnect: ...SocketINETGetAddr() failed:\n",
1418            0, 0, 0);
1419         return TRANS_CONNECT_FAILED;
1420     }
1421
1422     if (TRANS(SocketINETGetPeerAddr) (ciptr) < 0)
1423     {
1424         PRMSG (1,
1425          "SocketINETConnect: ...SocketINETGetPeerAddr() failed:\n",
1426               0, 0, 0);
1427         return TRANS_CONNECT_FAILED;
1428     }
1429
1430     return 0;
1431 }
1432
1433 #endif /* TCPCONN */
1434
1435
1436 \f
1437 #ifdef UNIXCONN
1438
1439 /*
1440  * Make sure 'host' is really local.
1441  */
1442
1443 static int
1444 UnixHostReallyLocal (host)
1445
1446 char *host;
1447
1448 {
1449     char hostnamebuf[256];
1450
1451     TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf));
1452
1453     if (strcmp (hostnamebuf, host) == 0)
1454     {
1455         return (1);
1456     }
1457     else
1458     {
1459         /*
1460          * A host may have more than one network address.  If any of the
1461          * network addresses of 'host' (specified to the connect call)
1462          * match any of the network addresses of 'hostname' (determined
1463          * by TRANS(GetHostname)), then the two hostnames are equivalent,
1464          * and we know that 'host' is really a local host.
1465          */
1466         char specified_local_addr_list[10][4];
1467         int scount, equiv, i, j;
1468         _Xgethostbynameparams hparams;
1469         struct hostent *hostp;
1470
1471         if ((hostp = _XGethostbyname (host,hparams)) == NULL)
1472             return (0);
1473
1474         scount = 0;
1475         while (hostp->h_addr_list[scount] && scount <= 8)
1476         {
1477             /*
1478              * The 2nd call to gethostname() overrides the data
1479              * from the 1st call, so we must save the address list.
1480              */
1481
1482             specified_local_addr_list[scount][0] = 
1483                                 hostp->h_addr_list[scount][0];
1484             specified_local_addr_list[scount][1] = 
1485                                 hostp->h_addr_list[scount][1];
1486             specified_local_addr_list[scount][2] = 
1487                                 hostp->h_addr_list[scount][2];
1488             specified_local_addr_list[scount][3] = 
1489                                 hostp->h_addr_list[scount][3];
1490             scount++;
1491         }
1492         if ((hostp = _XGethostbyname (hostnamebuf,hparams)) == NULL)
1493             return (0);
1494
1495         equiv = 0;
1496         i = 0;
1497
1498         while (i < scount && !equiv)
1499         {
1500             j = 0;
1501
1502             while (hostp->h_addr_list[j])
1503             {
1504                 if ((specified_local_addr_list[i][0] == 
1505                                         hostp->h_addr_list[j][0]) &&
1506                     (specified_local_addr_list[i][1] == 
1507                                         hostp->h_addr_list[j][1]) &&
1508                     (specified_local_addr_list[i][2] == 
1509                                         hostp->h_addr_list[j][2]) &&
1510                     (specified_local_addr_list[i][3] == 
1511                                         hostp->h_addr_list[j][3]))
1512                 {
1513                     /* They're equal, so we're done */
1514                     
1515                     equiv = 1;
1516                     break;
1517                 }
1518
1519                 j++;
1520             }
1521
1522             i++;
1523         }
1524         
1525     return (equiv);
1526     }
1527 }
1528
1529 static int
1530 TRANS(SocketUNIXConnect) (ciptr, host, port)
1531
1532 XtransConnInfo ciptr;
1533 char *host;
1534 char *port;
1535
1536 {
1537     struct sockaddr_un  sockname;
1538     int                 namelen;
1539
1540 #if defined(hpux) && defined(X11_t)
1541     struct sockaddr_un  old_sockname;
1542     int                 old_namelen;
1543 #endif
1544
1545
1546     PRMSG (2,"SocketUNIXConnect(%d,%s,%s)\n", ciptr->fd, host, port);
1547     
1548     /*
1549      * Make sure 'host' is really local.  If not, we return failure.
1550      * The reason we make this check is because a process may advertise
1551      * a "local" network ID for which it can accept connections, but if
1552      * a process on a remote machine tries to connect to this network ID,
1553      * we know for sure it will fail.
1554      */
1555
1556     if (strcmp (host, "unix") != 0 && !UnixHostReallyLocal (host))
1557     {
1558         PRMSG (1,
1559            "SocketUNIXConnect: Cannot connect to non-local host %s\n",
1560                host, 0, 0);
1561         return TRANS_CONNECT_FAILED;
1562     }
1563
1564
1565     /*
1566      * Check the port.
1567      */
1568
1569     if (!port || !*port)
1570     {
1571         PRMSG (1,"SocketUNIXConnect: Missing port specification\n",
1572               0, 0, 0);
1573         return TRANS_CONNECT_FAILED;
1574     }
1575
1576     /*
1577      * Build the socket name.
1578      */
1579     
1580     sockname.sun_family = AF_UNIX;
1581
1582     if (*port == '/') { /* a full pathname */
1583         sprintf (sockname.sun_path, "%s", port);
1584     } else {
1585         sprintf (sockname.sun_path, "%s%s", UNIX_PATH, port);
1586     }
1587
1588 #if defined(BSD44SOCKETS) && !defined(Lynx)
1589     sockname.sun_len = strlen (sockname.sun_path);
1590     namelen = SUN_LEN (&sockname);
1591 #else
1592     namelen = strlen (sockname.sun_path) + sizeof (sockname.sun_family);
1593 #endif
1594
1595
1596 #if defined(hpux) && defined(X11_t)
1597     /*
1598      * This is gross, but it was in Xlib
1599      */
1600     old_sockname.sun_family = AF_UNIX;
1601     if (*port == '/') { /* a full pathname */
1602         sprintf (old_sockname.sun_path, "%s", port);
1603     } else {
1604         sprintf (old_sockname.sun_path, "%s%s", OLD_UNIX_PATH, port);
1605     }
1606     old_namelen = strlen (old_sockname.sun_path) +
1607         sizeof (old_sockname.sun_family);
1608 #endif
1609
1610
1611     /*
1612      * Do the connect()
1613      */
1614
1615     if (connect (ciptr->fd, (struct sockaddr *) &sockname, namelen) < 0)
1616     {
1617         int olderrno = errno;
1618         int connected = 0;
1619         
1620 #if defined(hpux) && defined(X11_t)
1621         if (olderrno == ENOENT)
1622         {
1623             if (connect (ciptr->fd,
1624                 (struct sockaddr *) &old_sockname, old_namelen) >= 0)
1625             {
1626                 connected = 1;
1627             }
1628             else
1629                 olderrno = errno;
1630         }
1631 #endif
1632         if (!connected)
1633         {
1634             errno = olderrno;
1635             
1636             PRMSG (1,"SocketUNIXConnect: Can't connect: errno = %d\n",
1637                   EGET(),0, 0);
1638
1639             if (olderrno == ENOENT || olderrno == EINTR)
1640                 return TRANS_TRY_CONNECT_AGAIN;
1641             else
1642                 return TRANS_CONNECT_FAILED;
1643         }
1644     }
1645
1646     /*
1647      * Get the socket name and the peer name from the connect socket,
1648      * since this is unix domain.
1649      */
1650
1651     if ((ciptr->addr = (char *) xalloc(namelen)) == NULL ||
1652        (ciptr->peeraddr = (char *) xalloc(namelen)) == NULL)
1653     {
1654         PRMSG (1,
1655         "SocketUNIXCreateListener: Can't allocate space for the addr\n",
1656               0, 0, 0);
1657         return TRANS_CONNECT_FAILED;
1658     }
1659
1660     ciptr->family = AF_UNIX;
1661     ciptr->addrlen = namelen;
1662     ciptr->peeraddrlen = namelen;
1663     memcpy (ciptr->addr, &sockname, ciptr->addrlen);
1664     memcpy (ciptr->peeraddr, &sockname, ciptr->peeraddrlen);
1665     
1666     return 0;
1667 }
1668
1669 #endif /* UNIXCONN */
1670
1671 #endif /* TRANS_CLIENT */
1672
1673
1674 static int
1675 TRANS(SocketBytesReadable) (ciptr, pend)
1676
1677 XtransConnInfo ciptr;
1678 BytesReadable_t *pend;
1679 {
1680     PRMSG (2,"SocketBytesReadable(%x,%d,%x)\n",
1681         ciptr, ciptr->fd, pend);
1682
1683 #ifdef WIN32
1684     return ioctlsocket ((SOCKET) ciptr->fd, FIONREAD, (u_long *) pend);
1685 #else
1686 #if (defined(i386) && defined(SYSV)) || defined(_SEQUENT_)
1687     return ioctl (ciptr->fd, I_NREAD, (char *) pend);
1688 #else
1689 #if defined(__EMX__)
1690     return ioctl (ciptr->fd, FIONREAD, (char*) pend, sizeof(int));
1691 #else
1692     return ioctl (ciptr->fd, FIONREAD, (char *) pend);
1693 #endif /* __EMX__ */
1694 #endif /* i386 && SYSV && !SCO || _SEQUENT_ */
1695 #endif /* WIN32 */
1696 }
1697
1698
1699 static int
1700 TRANS(SocketRead) (ciptr, buf, size)
1701
1702 XtransConnInfo  ciptr;
1703 char            *buf;
1704 int             size;
1705
1706 {
1707     PRMSG (2,"SocketRead(%d,%x,%d)\n", ciptr->fd, buf, size);
1708
1709 #if defined(WIN32) || defined(__EMX__)
1710     return recv ((SOCKET)ciptr->fd, buf, size, 0);
1711 #else
1712     return read (ciptr->fd, buf, size);
1713 #endif /* WIN32 */
1714 }
1715
1716
1717 static int
1718 TRANS(SocketWrite) (ciptr, buf, size)
1719
1720 XtransConnInfo ciptr;
1721 char           *buf;
1722 int            size;
1723
1724 {
1725     PRMSG (2,"SocketWrite(%d,%x,%d)\n", ciptr->fd, buf, size);
1726
1727 #if defined(WIN32) || defined(__EMX__)
1728     return send ((SOCKET)ciptr->fd, buf, size, 0);
1729 #else
1730     return write (ciptr->fd, buf, size);
1731 #endif /* WIN32 */
1732 }
1733
1734
1735 static int
1736 TRANS(SocketReadv) (ciptr, buf, size)
1737
1738 XtransConnInfo  ciptr;
1739 struct iovec    *buf;
1740 int             size;
1741
1742 {
1743     PRMSG (2,"SocketReadv(%d,%x,%d)\n", ciptr->fd, buf, size);
1744
1745     return READV (ciptr, buf, size);
1746 }
1747
1748
1749 static int
1750 TRANS(SocketWritev) (ciptr, buf, size)
1751
1752 XtransConnInfo  ciptr;
1753 struct iovec    *buf;
1754 int             size;
1755
1756 {
1757     PRMSG (2,"SocketWritev(%d,%x,%d)\n", ciptr->fd, buf, size);
1758
1759     return WRITEV (ciptr, buf, size);
1760 }
1761
1762
1763 static int
1764 TRANS(SocketDisconnect) (ciptr)
1765
1766 XtransConnInfo ciptr;
1767
1768 {
1769     PRMSG (2,"SocketDisconnect(%x,%d)\n", ciptr, ciptr->fd, 0);
1770
1771     return shutdown (ciptr->fd, 2); /* disallow further sends and receives */
1772 }
1773
1774
1775 #ifdef TCPCONN
1776 static int
1777 TRANS(SocketINETClose) (ciptr)
1778
1779 XtransConnInfo ciptr;
1780
1781 {
1782     PRMSG (2,"SocketINETClose(%x,%d)\n", ciptr, ciptr->fd, 0);
1783
1784     return close (ciptr->fd);
1785 }
1786
1787 #endif /* TCPCONN */
1788
1789
1790 #ifdef UNIXCONN
1791 static int
1792 TRANS(SocketUNIXClose) (ciptr)
1793
1794 XtransConnInfo ciptr;
1795
1796 {
1797     /*
1798      * If this is the server side, then once the socket is closed,
1799      * it must be unlinked to completely close it
1800      */
1801
1802     struct sockaddr_un  *sockname = (struct sockaddr_un *) ciptr->addr;
1803     char        path[200]; /* > sizeof sun_path +1 */
1804     int ret;
1805
1806     PRMSG (2,"SocketUNIXClose(%x,%d)\n", ciptr, ciptr->fd, 0);
1807
1808     ret = close(ciptr->fd);
1809
1810     if (ciptr->flags
1811        && sockname
1812        && sockname->sun_family == AF_UNIX
1813        && sockname->sun_path[0])
1814     {
1815         strncpy (path, sockname->sun_path,
1816                 ciptr->addrlen - sizeof (sockname->sun_family));
1817         unlink (path);
1818     }
1819
1820     return ret;
1821 }
1822
1823 static int
1824 TRANS(SocketUNIXCloseForCloning) (ciptr)
1825
1826 XtransConnInfo ciptr;
1827
1828 {
1829     /*
1830      * Don't unlink path.
1831      */
1832
1833     int ret;
1834
1835     PRMSG (2,"SocketUNIXCloseForCloning(%x,%d)\n",
1836         ciptr, ciptr->fd, 0);
1837
1838     ret = close(ciptr->fd);
1839
1840     return ret;
1841 }
1842
1843 #endif /* UNIXCONN */
1844
1845
1846 #ifdef TCPCONN
1847 Xtransport      TRANS(SocketTCPFuncs) = {
1848         /* Socket Interface */
1849         "tcp",
1850         0,
1851 #ifdef TRANS_CLIENT
1852         TRANS(SocketOpenCOTSClient),
1853 #endif /* TRANS_CLIENT */
1854 #ifdef TRANS_SERVER
1855         TRANS(SocketOpenCOTSServer),
1856 #endif /* TRANS_SERVER */
1857 #ifdef TRANS_CLIENT
1858         TRANS(SocketOpenCLTSClient),
1859 #endif /* TRANS_CLIENT */
1860 #ifdef TRANS_SERVER
1861         TRANS(SocketOpenCLTSServer),
1862 #endif /* TRANS_SERVER */
1863 #ifdef TRANS_REOPEN
1864         TRANS(SocketReopenCOTSServer),
1865         TRANS(SocketReopenCLTSServer),
1866 #endif
1867         TRANS(SocketSetOption),
1868 #ifdef TRANS_SERVER
1869         TRANS(SocketINETCreateListener),
1870         NULL,                                   /* ResetListener */
1871         TRANS(SocketINETAccept),
1872 #endif /* TRANS_SERVER */
1873 #ifdef TRANS_CLIENT
1874         TRANS(SocketINETConnect),
1875 #endif /* TRANS_CLIENT */
1876         TRANS(SocketBytesReadable),
1877         TRANS(SocketRead),
1878         TRANS(SocketWrite),
1879         TRANS(SocketReadv),
1880         TRANS(SocketWritev),
1881         TRANS(SocketDisconnect),
1882         TRANS(SocketINETClose),
1883         TRANS(SocketINETClose),
1884         };
1885
1886 Xtransport      TRANS(SocketINETFuncs) = {
1887         /* Socket Interface */
1888         "inet",
1889         TRANS_ALIAS,
1890 #ifdef TRANS_CLIENT
1891         TRANS(SocketOpenCOTSClient),
1892 #endif /* TRANS_CLIENT */
1893 #ifdef TRANS_SERVER
1894         TRANS(SocketOpenCOTSServer),
1895 #endif /* TRANS_SERVER */
1896 #ifdef TRANS_CLIENT
1897         TRANS(SocketOpenCLTSClient),
1898 #endif /* TRANS_CLIENT */
1899 #ifdef TRANS_SERVER
1900         TRANS(SocketOpenCLTSServer),
1901 #endif /* TRANS_SERVER */
1902 #ifdef TRANS_REOPEN
1903         TRANS(SocketReopenCOTSServer),
1904         TRANS(SocketReopenCLTSServer),
1905 #endif
1906         TRANS(SocketSetOption),
1907 #ifdef TRANS_SERVER
1908         TRANS(SocketINETCreateListener),
1909         NULL,                                   /* ResetListener */
1910         TRANS(SocketINETAccept),
1911 #endif /* TRANS_SERVER */
1912 #ifdef TRANS_CLIENT
1913         TRANS(SocketINETConnect),
1914 #endif /* TRANS_CLIENT */
1915         TRANS(SocketBytesReadable),
1916         TRANS(SocketRead),
1917         TRANS(SocketWrite),
1918         TRANS(SocketReadv),
1919         TRANS(SocketWritev),
1920         TRANS(SocketDisconnect),
1921         TRANS(SocketINETClose),
1922         TRANS(SocketINETClose),
1923         };
1924
1925 #endif /* TCPCONN */
1926
1927 #ifdef UNIXCONN
1928 #if !defined(LOCALCONN)
1929 Xtransport      TRANS(SocketLocalFuncs) = {
1930         /* Socket Interface */
1931         "local",
1932         0,
1933 #ifdef TRANS_CLIENT
1934         TRANS(SocketOpenCOTSClient),
1935 #endif /* TRANS_CLIENT */
1936 #ifdef TRANS_SERVER
1937         TRANS(SocketOpenCOTSServer),
1938 #endif /* TRANS_SERVER */
1939 #ifdef TRANS_CLIENT
1940         TRANS(SocketOpenCLTSClient),
1941 #endif /* TRANS_CLIENT */
1942 #ifdef TRANS_SERVER
1943         TRANS(SocketOpenCLTSServer),
1944 #endif /* TRANS_SERVER */
1945 #ifdef TRANS_REOPEN
1946         TRANS(SocketReopenCOTSServer),
1947         TRANS(SocketReopenCLTSServer),
1948 #endif
1949         TRANS(SocketSetOption),
1950 #ifdef TRANS_SERVER
1951         TRANS(SocketUNIXCreateListener),
1952         TRANS(SocketUNIXResetListener),
1953         TRANS(SocketUNIXAccept),
1954 #endif /* TRANS_SERVER */
1955 #ifdef TRANS_CLIENT
1956         TRANS(SocketUNIXConnect),
1957 #endif /* TRANS_CLIENT */
1958         TRANS(SocketBytesReadable),
1959         TRANS(SocketRead),
1960         TRANS(SocketWrite),
1961         TRANS(SocketReadv),
1962         TRANS(SocketWritev),
1963         TRANS(SocketDisconnect),
1964         TRANS(SocketUNIXClose),
1965         TRANS(SocketUNIXCloseForCloning),
1966         };
1967 #endif /* !LOCALCONN */
1968
1969 Xtransport      TRANS(SocketUNIXFuncs) = {
1970         /* Socket Interface */
1971         "unix",
1972 #if !defined(LOCALCONN)
1973         TRANS_ALIAS,
1974 #else
1975         0,
1976 #endif
1977 #ifdef TRANS_CLIENT
1978         TRANS(SocketOpenCOTSClient),
1979 #endif /* TRANS_CLIENT */
1980 #ifdef TRANS_SERVER
1981         TRANS(SocketOpenCOTSServer),
1982 #endif /* TRANS_SERVER */
1983 #ifdef TRANS_CLIENT
1984         TRANS(SocketOpenCLTSClient),
1985 #endif /* TRANS_CLIENT */
1986 #ifdef TRANS_SERVER
1987         TRANS(SocketOpenCLTSServer),
1988 #endif /* TRANS_SERVER */
1989 #ifdef TRANS_REOPEN
1990         TRANS(SocketReopenCOTSServer),
1991         TRANS(SocketReopenCLTSServer),
1992 #endif
1993         TRANS(SocketSetOption),
1994 #ifdef TRANS_SERVER
1995         TRANS(SocketUNIXCreateListener),
1996         TRANS(SocketUNIXResetListener),
1997         TRANS(SocketUNIXAccept),
1998 #endif /* TRANS_SERVER */
1999 #ifdef TRANS_CLIENT
2000         TRANS(SocketUNIXConnect),
2001 #endif /* TRANS_CLIENT */
2002         TRANS(SocketBytesReadable),
2003         TRANS(SocketRead),
2004         TRANS(SocketWrite),
2005         TRANS(SocketReadv),
2006         TRANS(SocketWritev),
2007         TRANS(SocketDisconnect),
2008         TRANS(SocketUNIXClose),
2009         TRANS(SocketUNIXCloseForCloning),
2010         };
2011
2012 #endif /* UNIXCONN */