xfstrans.c revision 30e1ba2c
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
34/* XXX duplicated from misc.h */
35typedef struct {		/* when cloning, need old transport info */
36    int trans_id;
37    int fd;
38    int portnum;
39} OldListenRec;
40
41OldListenRec *
42TRANS(GetInetdListenInfo) (int fd)
43{
44    const char *port = "0";
45    XtransConnInfo inetdCI;
46    OldListenRec *old_listen;
47    int portnum;
48
49    /* Create a XtransConnInfo struct for this connection */
50    inetdCI = TRANS(ReopenCOTSServer)(TRANS_SOCKET_TCP_INDEX, fd, port);
51
52    /* Fill in correct address/portnum */
53    TRANS(SocketINETGetAddr)(inetdCI);
54#if defined(IPv6) && defined(AF_INET6)
55    if ( ((struct sockaddr *)(inetdCI->addr))->sa_family == AF_INET6 )
56	portnum = ntohs(((struct sockaddr_in6 *)(inetdCI->addr))->sin6_port);
57    else
58#endif
59	portnum = ntohs(((struct sockaddr_in *)(inetdCI->addr))->sin_port);
60    inetdCI->port = malloc(6); /* Base 10 integer <= 65535 + trailing NUL */
61    snprintf(inetdCI->port, 6, "%d", portnum);
62
63    /* Do the socket setup that xtrans normally takes care of in
64     * TRANS(SocketOpen) && TRANS(SocketCreateListener)
65     */
66    {
67	/*
68	 * turn off TCP coalescence for INET sockets
69	 */
70
71	int tmp = 1;
72	setsockopt (fd, IPPROTO_TCP, TCP_NODELAY,
73		    (char *) &tmp, sizeof (int));
74    }
75#ifdef SO_DONTLINGER
76    setsockopt (fd, SOL_SOCKET, SO_DONTLINGER, NULL, 0);
77#else
78# ifdef SO_LINGER
79    {
80	static int linger[2] = { 0, 0 };
81	setsockopt (fd, SOL_SOCKET, SO_LINGER,
82		    (char *) linger, sizeof (linger));
83    }
84# endif
85#endif
86
87    if (listen (fd, BACKLOG) < 0)
88        return NULL;
89
90    /* Pass the inetd socket back through the connection setup code
91     * the same way as a cloned listening port
92     */
93    old_listen =  malloc (sizeof (OldListenRec));
94    if (old_listen != NULL) {
95        char *old_port;
96	TRANS(GetReopenInfo)(inetdCI, &(old_listen->trans_id),
97			     &(old_listen->fd), &old_port);
98
99	old_listen->portnum = portnum;
100    }
101
102    return old_listen;
103}
104#endif /* XFS_INETD */
105