xfstrans.c revision 8f34cbf9
1/*
2 * Copyright © 2003 Keith Packard
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Keith Packard not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission.  Keith Packard makes no
11 * representations about the suitability of this software for any purpose.  It
12 * is provided "as is" without express or implied warranty.
13 *
14 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 */
22
23#include <config.h>
24
25#define FONT_t 1
26#define TRANS_REOPEN 1
27#define TRANS_SERVER 1
28
29#include <X11/Xtrans/transport.c>
30
31#ifdef XFS_INETD
32/* xfs special handling for listen socket passed from inetd */
33#include "misc.h"
34
35OldListenRec *
36TRANS(GetInetdListenInfo) (int fd)
37{
38    char *port = "0";
39    XtransConnInfo inetdCI;
40    OldListenRec *old_listen;
41    int portnum;
42
43    /* Create a XtransConnInfo struct for this connection */
44    inetdCI = TRANS(ReopenCOTSServer)(TRANS_SOCKET_TCP_INDEX, fd, port);
45
46    /* Fill in correct address/portnum */
47    TRANS(SocketINETGetAddr)(inetdCI);
48#ifdef AF_INET6
49    if ( ((struct sockaddr *)(inetdCI->addr))->sa_family == AF_INET6 )
50	portnum = ntohs(((struct sockaddr_in6 *)(inetdCI->addr))->sin6_port);
51    else
52#endif
53	portnum = ntohs(((struct sockaddr_in *)(inetdCI->addr))->sin_port);
54    inetdCI->port = malloc(6); /* Base 10 integer <= 65535 + trailing NUL */
55    snprintf(inetdCI->port, 6, "%d", portnum);
56
57    /* Do the socket setup that xtrans normally takes care of in
58     * TRANS(SocketOpen) && TRANS(SocketCreateListener)
59     */
60    {
61	/*
62	 * turn off TCP coalescence for INET sockets
63	 */
64
65	int tmp = 1;
66	setsockopt (fd, IPPROTO_TCP, TCP_NODELAY,
67		    (char *) &tmp, sizeof (int));
68    }
69#ifdef SO_DONTLINGER
70    setsockopt (fd, SOL_SOCKET, SO_DONTLINGER, NULL, 0);
71#else
72# ifdef SO_LINGER
73    {
74	static int linger[2] = { 0, 0 };
75	setsockopt (fd, SOL_SOCKET, SO_LINGER,
76		    (char *) linger, sizeof (linger));
77    }
78# endif
79#endif
80
81    if (listen (fd, BACKLOG) < 0)
82    {
83	FatalError("listen() failed on inetd socket: %s\n",
84		   strerror(errno));
85    }
86
87    /* Pass the inetd socket back through the connection setup code
88     * the same way as a cloned listening port
89     */
90    old_listen =  malloc (sizeof (OldListenRec));
91    if (old_listen != NULL) {
92        char *old_port;
93	TRANS(GetReopenInfo)(inetdCI, &(old_listen->trans_id),
94			     &(old_listen->fd), &old_port);
95
96	old_listen->portnum = portnum;
97    }
98
99    return old_listen;
100}
101#endif /* XFS_INETD */
102