connection.c revision 6747b715
105b261ecSmrg/***********************************************************
205b261ecSmrg
305b261ecSmrgCopyright 1987, 1989, 1998  The Open Group
405b261ecSmrg
505b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its
605b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that
705b261ecSmrgthe above copyright notice appear in all copies and that both that
805b261ecSmrgcopyright notice and this permission notice appear in supporting
905b261ecSmrgdocumentation.
1005b261ecSmrg
1105b261ecSmrgThe above copyright notice and this permission notice shall be included in
1205b261ecSmrgall copies or substantial portions of the Software.
1305b261ecSmrg
1405b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1505b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1605b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
1705b261ecSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1805b261ecSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1905b261ecSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2005b261ecSmrg
2105b261ecSmrgExcept as contained in this notice, the name of The Open Group shall not be
2205b261ecSmrgused in advertising or otherwise to promote the sale, use or other dealings
2305b261ecSmrgin this Software without prior written authorization from The Open Group.
2405b261ecSmrg
2505b261ecSmrg
2605b261ecSmrgCopyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
2705b261ecSmrg
2805b261ecSmrg                        All Rights Reserved
2905b261ecSmrg
3005b261ecSmrgPermission to use, copy, modify, and distribute this software and its
3105b261ecSmrgdocumentation for any purpose and without fee is hereby granted,
3205b261ecSmrgprovided that the above copyright notice appear in all copies and that
3305b261ecSmrgboth that copyright notice and this permission notice appear in
3405b261ecSmrgsupporting documentation, and that the name of Digital not be
3505b261ecSmrgused in advertising or publicity pertaining to distribution of the
3605b261ecSmrgsoftware without specific, written prior permission.
3705b261ecSmrg
3805b261ecSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
3905b261ecSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
4005b261ecSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
4105b261ecSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
4205b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
4305b261ecSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
4405b261ecSmrgSOFTWARE.
4505b261ecSmrg
4605b261ecSmrg******************************************************************/
4705b261ecSmrg/*****************************************************************
4805b261ecSmrg *  Stuff to create connections --- OS dependent
4905b261ecSmrg *
5005b261ecSmrg *      EstablishNewConnections, CreateWellKnownSockets, ResetWellKnownSockets,
5105b261ecSmrg *      CloseDownConnection, CheckConnections, AddEnabledDevice,
5205b261ecSmrg *	RemoveEnabledDevice, OnlyListToOneClient,
5305b261ecSmrg *      ListenToAllClients,
5405b261ecSmrg *
5505b261ecSmrg *      (WaitForSomething is in its own file)
5605b261ecSmrg *
5705b261ecSmrg *      In this implementation, a client socket table is not kept.
5805b261ecSmrg *      Instead, what would be the index into the table is just the
5905b261ecSmrg *      file descriptor of the socket.  This won't work for if the
6005b261ecSmrg *      socket ids aren't small nums (0 - 2^8)
6105b261ecSmrg *
6205b261ecSmrg *****************************************************************/
6305b261ecSmrg
6405b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
6505b261ecSmrg#include <dix-config.h>
6605b261ecSmrg#endif
6705b261ecSmrg
6805b261ecSmrg#ifdef WIN32
6905b261ecSmrg#include <X11/Xwinsock.h>
7005b261ecSmrg#endif
7105b261ecSmrg#include <X11/X.h>
7205b261ecSmrg#include <X11/Xproto.h>
7305b261ecSmrg#define XSERV_t
7405b261ecSmrg#define TRANS_SERVER
7505b261ecSmrg#define TRANS_REOPEN
7605b261ecSmrg#include <X11/Xtrans/Xtrans.h>
774642e01fSmrg#include <X11/Xtrans/Xtransint.h>
7805b261ecSmrg#include <errno.h>
7905b261ecSmrg#include <signal.h>
8005b261ecSmrg#include <stdio.h>
8105b261ecSmrg#include <stdlib.h>
8205b261ecSmrg
8305b261ecSmrg#ifndef WIN32
8405b261ecSmrg#include <sys/socket.h>
8505b261ecSmrg
8605b261ecSmrg
8705b261ecSmrg
8805b261ecSmrg#if defined(TCPCONN) || defined(STREAMSCONN)
8905b261ecSmrg# include <netinet/in.h>
9005b261ecSmrg# include <arpa/inet.h>
9105b261ecSmrg#  ifdef apollo
9205b261ecSmrg#   ifndef NO_TCP_H
9305b261ecSmrg#    include <netinet/tcp.h>
9405b261ecSmrg#   endif
9505b261ecSmrg#  else
9605b261ecSmrg#   ifdef CSRG_BASED
9705b261ecSmrg#    include <sys/param.h>
9805b261ecSmrg#   endif
9905b261ecSmrg#   include <netinet/tcp.h>
10005b261ecSmrg#  endif
10105b261ecSmrg# include <arpa/inet.h>
10205b261ecSmrg#endif
10305b261ecSmrg
10405b261ecSmrg#include <sys/uio.h>
1054642e01fSmrg
10605b261ecSmrg#endif /* WIN32 */
10705b261ecSmrg#include "misc.h"		/* for typedef of pointer */
10805b261ecSmrg#include "osdep.h"
10905b261ecSmrg#include <X11/Xpoll.h>
11005b261ecSmrg#include "opaque.h"
11105b261ecSmrg#include "dixstruct.h"
11205b261ecSmrg#include "xace.h"
11305b261ecSmrg
11405b261ecSmrg#define Pid_t pid_t
11505b261ecSmrg
11605b261ecSmrg#ifdef DNETCONN
11705b261ecSmrg#include <netdnet/dn.h>
11805b261ecSmrg#endif /* DNETCONN */
11905b261ecSmrg
12005b261ecSmrg#ifdef HAS_GETPEERUCRED
12105b261ecSmrg# include <ucred.h>
12205b261ecSmrg# include <zone.h>
12305b261ecSmrg#endif
12405b261ecSmrg
12505b261ecSmrg#ifdef XSERVER_DTRACE
12605b261ecSmrg# include <sys/types.h>
12705b261ecSmrgtypedef const char *string;
12805b261ecSmrg# ifndef HAS_GETPEERUCRED
12905b261ecSmrg#  define zoneid_t int
13005b261ecSmrg# endif
13105b261ecSmrg# include "../dix/Xserver-dtrace.h"
13205b261ecSmrg#endif
13305b261ecSmrg
13405b261ecSmrgstatic int lastfdesc;		/* maximum file descriptor */
13505b261ecSmrg
13605b261ecSmrgfd_set WellKnownConnections;	/* Listener mask */
13705b261ecSmrgfd_set EnabledDevices;		/* mask for input devices that are on */
13805b261ecSmrgfd_set AllSockets;		/* select on this */
13905b261ecSmrgfd_set AllClients;		/* available clients */
14005b261ecSmrgfd_set LastSelectMask;		/* mask returned from last select call */
14105b261ecSmrgfd_set ClientsWithInput;	/* clients with FULL requests in buffer */
14205b261ecSmrgfd_set ClientsWriteBlocked;	/* clients who cannot receive output */
14305b261ecSmrgfd_set OutputPending;		/* clients with reply/event data ready to go */
14405b261ecSmrgint MaxClients = 0;
14505b261ecSmrgBool NewOutputPending;		/* not yet attempted to write some new output */
14605b261ecSmrgBool AnyClientsWriteBlocked;	/* true if some client blocked on write */
14705b261ecSmrg
14805b261ecSmrgstatic Bool RunFromSmartParent;	/* send SIGUSR1 to parent process */
1496747b715SmrgBool PartialNetwork;	/* continue even if unable to bind all addrs */
15005b261ecSmrgstatic Pid_t ParentProcess;
15105b261ecSmrg
15205b261ecSmrgstatic Bool debug_conns = FALSE;
15305b261ecSmrg
15405b261ecSmrgfd_set IgnoredClientsWithInput;
15505b261ecSmrgstatic fd_set GrabImperviousClients;
15605b261ecSmrgstatic fd_set SavedAllClients;
15705b261ecSmrgstatic fd_set SavedAllSockets;
15805b261ecSmrgstatic fd_set SavedClientsWithInput;
1596747b715Smrgint GrabInProgress = 0;
16005b261ecSmrg
16105b261ecSmrg#if !defined(WIN32)
16205b261ecSmrgint *ConnectionTranslation = NULL;
16305b261ecSmrg#else
16405b261ecSmrg/*
16505b261ecSmrg * On NT fds are not between 0 and MAXSOCKS, they are unrelated, and there is
16605b261ecSmrg * not even a known maximum value, so use something quite arbitrary for now.
16705b261ecSmrg * Do storage is a hash table of size 256. Collisions are handled in a linked
16805b261ecSmrg * list.
16905b261ecSmrg */
17005b261ecSmrg
17105b261ecSmrg#undef MAXSOCKS
17205b261ecSmrg#define MAXSOCKS 500
17305b261ecSmrg#undef MAXSELECT
17405b261ecSmrg#define MAXSELECT 500
17505b261ecSmrg
17605b261ecSmrgstruct _ct_node {
17705b261ecSmrg    struct _ct_node *next;
17805b261ecSmrg    int key;
17905b261ecSmrg    int value;
18005b261ecSmrg};
18105b261ecSmrg
18205b261ecSmrgstruct _ct_node *ct_head[256];
18305b261ecSmrg
18405b261ecSmrgvoid InitConnectionTranslation(void)
18505b261ecSmrg{
1866747b715Smrg    memset(ct_head, 0, sizeof(ct_head));
18705b261ecSmrg}
18805b261ecSmrg
18905b261ecSmrgint GetConnectionTranslation(int conn)
19005b261ecSmrg{
19105b261ecSmrg    struct _ct_node *node = ct_head[conn & 0xff];
19205b261ecSmrg    while (node != NULL)
19305b261ecSmrg    {
19405b261ecSmrg        if (node->key == conn)
19505b261ecSmrg            return node->value;
19605b261ecSmrg        node = node->next;
19705b261ecSmrg    }
19805b261ecSmrg    return 0;
19905b261ecSmrg}
20005b261ecSmrg
20105b261ecSmrgvoid SetConnectionTranslation(int conn, int client)
20205b261ecSmrg{
20305b261ecSmrg    struct _ct_node **node = ct_head + (conn & 0xff);
20405b261ecSmrg    if (client == 0) /* remove entry */
20505b261ecSmrg    {
20605b261ecSmrg        while (*node != NULL)
20705b261ecSmrg        {
20805b261ecSmrg            if ((*node)->key == conn)
20905b261ecSmrg            {
21005b261ecSmrg                struct _ct_node *temp = *node;
21105b261ecSmrg                *node = (*node)->next;
21205b261ecSmrg                free(temp);
21305b261ecSmrg                return;
21405b261ecSmrg            }
21505b261ecSmrg            node = &((*node)->next);
21605b261ecSmrg        }
21705b261ecSmrg        return;
21805b261ecSmrg    } else
21905b261ecSmrg    {
22005b261ecSmrg        while (*node != NULL)
22105b261ecSmrg        {
22205b261ecSmrg            if ((*node)->key == conn)
22305b261ecSmrg            {
22405b261ecSmrg                (*node)->value = client;
22505b261ecSmrg                return;
22605b261ecSmrg            }
22705b261ecSmrg            node = &((*node)->next);
22805b261ecSmrg        }
2296747b715Smrg        *node = malloc(sizeof(struct _ct_node));
23005b261ecSmrg        (*node)->next = NULL;
23105b261ecSmrg        (*node)->key = conn;
23205b261ecSmrg        (*node)->value = client;
23305b261ecSmrg        return;
23405b261ecSmrg    }
23505b261ecSmrg}
23605b261ecSmrg
23705b261ecSmrgvoid ClearConnectionTranslation(void)
23805b261ecSmrg{
23905b261ecSmrg    unsigned i;
24005b261ecSmrg    for (i = 0; i < 256; i++)
24105b261ecSmrg    {
24205b261ecSmrg        struct _ct_node *node = ct_head[i];
24305b261ecSmrg        while (node != NULL)
24405b261ecSmrg        {
24505b261ecSmrg            struct _ct_node *temp = node;
24605b261ecSmrg            node = node->next;
2476747b715Smrg            free(temp);
24805b261ecSmrg        }
24905b261ecSmrg    }
25005b261ecSmrg}
25105b261ecSmrg#endif
25205b261ecSmrg
25305b261ecSmrgstatic XtransConnInfo 	*ListenTransConns = NULL;
25405b261ecSmrgstatic int	       	*ListenTransFds = NULL;
25505b261ecSmrgstatic int		ListenTransCount;
25605b261ecSmrg
25705b261ecSmrgstatic void ErrorConnMax(XtransConnInfo /* trans_conn */);
25805b261ecSmrg
25905b261ecSmrgstatic XtransConnInfo
26005b261ecSmrglookup_trans_conn (int fd)
26105b261ecSmrg{
26205b261ecSmrg    if (ListenTransFds)
26305b261ecSmrg    {
26405b261ecSmrg	int i;
26505b261ecSmrg	for (i = 0; i < ListenTransCount; i++)
26605b261ecSmrg	    if (ListenTransFds[i] == fd)
26705b261ecSmrg		return ListenTransConns[i];
26805b261ecSmrg    }
26905b261ecSmrg
2706747b715Smrg    return NULL;
27105b261ecSmrg}
27205b261ecSmrg
27305b261ecSmrg/* Set MaxClients and lastfdesc, and allocate ConnectionTranslation */
27405b261ecSmrg
27505b261ecSmrgvoid
27605b261ecSmrgInitConnectionLimits(void)
27705b261ecSmrg{
27805b261ecSmrg    lastfdesc = -1;
27905b261ecSmrg
28005b261ecSmrg#ifndef __CYGWIN__
28105b261ecSmrg
28205b261ecSmrg#if !defined(XNO_SYSCONF) && defined(_SC_OPEN_MAX)
28305b261ecSmrg    lastfdesc = sysconf(_SC_OPEN_MAX) - 1;
28405b261ecSmrg#endif
28505b261ecSmrg
28605b261ecSmrg#ifdef HAS_GETDTABLESIZE
28705b261ecSmrg    if (lastfdesc < 0)
28805b261ecSmrg	lastfdesc = getdtablesize() - 1;
28905b261ecSmrg#endif
29005b261ecSmrg
29105b261ecSmrg#ifdef _NFILE
29205b261ecSmrg    if (lastfdesc < 0)
29305b261ecSmrg	lastfdesc = _NFILE - 1;
29405b261ecSmrg#endif
29505b261ecSmrg
29605b261ecSmrg#endif /* __CYGWIN__ */
29705b261ecSmrg
29805b261ecSmrg    /* This is the fallback */
29905b261ecSmrg    if (lastfdesc < 0)
30005b261ecSmrg	lastfdesc = MAXSOCKS;
30105b261ecSmrg
30205b261ecSmrg    if (lastfdesc > MAXSELECT)
30305b261ecSmrg	lastfdesc = MAXSELECT;
30405b261ecSmrg
30505b261ecSmrg    if (lastfdesc > MAXCLIENTS)
30605b261ecSmrg    {
30705b261ecSmrg	lastfdesc = MAXCLIENTS;
30805b261ecSmrg	if (debug_conns)
30905b261ecSmrg	    ErrorF( "REACHED MAXIMUM CLIENTS LIMIT %d\n", MAXCLIENTS);
31005b261ecSmrg    }
31105b261ecSmrg    MaxClients = lastfdesc;
31205b261ecSmrg
31305b261ecSmrg#ifdef DEBUG
31405b261ecSmrg    ErrorF("InitConnectionLimits: MaxClients = %d\n", MaxClients);
31505b261ecSmrg#endif
31605b261ecSmrg
31705b261ecSmrg#if !defined(WIN32)
31805b261ecSmrg    if (!ConnectionTranslation)
31905b261ecSmrg        ConnectionTranslation = (int *)xnfalloc(sizeof(int)*(lastfdesc + 1));
32005b261ecSmrg#else
32105b261ecSmrg    InitConnectionTranslation();
32205b261ecSmrg#endif
32305b261ecSmrg}
32405b261ecSmrg
3254642e01fSmrg/*
3264642e01fSmrg * If SIGUSR1 was set to SIG_IGN when the server started, assume that either
3274642e01fSmrg *
3284642e01fSmrg *  a- The parent process is ignoring SIGUSR1
3294642e01fSmrg *
3304642e01fSmrg * or
3314642e01fSmrg *
3324642e01fSmrg *  b- The parent process is expecting a SIGUSR1
3334642e01fSmrg *     when the server is ready to accept connections
3344642e01fSmrg *
3354642e01fSmrg * In the first case, the signal will be harmless, in the second case,
3364642e01fSmrg * the signal will be quite useful.
3374642e01fSmrg */
3384642e01fSmrgstatic void
3394642e01fSmrgInitParentProcess(void)
3404642e01fSmrg{
3414642e01fSmrg#if !defined(WIN32)
3424642e01fSmrg    OsSigHandlerPtr handler;
3434642e01fSmrg    handler = OsSignal (SIGUSR1, SIG_IGN);
3444642e01fSmrg    if ( handler == SIG_IGN)
3454642e01fSmrg	RunFromSmartParent = TRUE;
3464642e01fSmrg    OsSignal(SIGUSR1, handler);
3474642e01fSmrg    ParentProcess = getppid ();
3484642e01fSmrg#endif
3494642e01fSmrg}
3504642e01fSmrg
3514642e01fSmrgvoid
3524642e01fSmrgNotifyParentProcess(void)
3534642e01fSmrg{
3544642e01fSmrg#if !defined(WIN32)
3554642e01fSmrg    if (RunFromSmartParent) {
3564642e01fSmrg	if (ParentProcess > 1) {
3574642e01fSmrg	    kill (ParentProcess, SIGUSR1);
3584642e01fSmrg	}
3594642e01fSmrg    }
3604642e01fSmrg#endif
3614642e01fSmrg}
36205b261ecSmrg
36305b261ecSmrg/*****************
36405b261ecSmrg * CreateWellKnownSockets
36505b261ecSmrg *    At initialization, create the sockets to listen on for new clients.
36605b261ecSmrg *****************/
36705b261ecSmrg
36805b261ecSmrgvoid
36905b261ecSmrgCreateWellKnownSockets(void)
37005b261ecSmrg{
37105b261ecSmrg    int		i;
37205b261ecSmrg    int		partial;
37305b261ecSmrg    char 	port[20];
37405b261ecSmrg
37505b261ecSmrg    FD_ZERO(&AllSockets);
37605b261ecSmrg    FD_ZERO(&AllClients);
37705b261ecSmrg    FD_ZERO(&LastSelectMask);
37805b261ecSmrg    FD_ZERO(&ClientsWithInput);
37905b261ecSmrg
38005b261ecSmrg#if !defined(WIN32)
38105b261ecSmrg    for (i=0; i<MaxClients; i++) ConnectionTranslation[i] = 0;
38205b261ecSmrg#else
38305b261ecSmrg    ClearConnectionTranslation();
38405b261ecSmrg#endif
38505b261ecSmrg
38605b261ecSmrg    FD_ZERO (&WellKnownConnections);
38705b261ecSmrg
38805b261ecSmrg    sprintf (port, "%d", atoi (display));
38905b261ecSmrg
39005b261ecSmrg    if ((_XSERVTransMakeAllCOTSServerListeners (port, &partial,
39105b261ecSmrg	&ListenTransCount, &ListenTransConns) >= 0) &&
39205b261ecSmrg	(ListenTransCount >= 1))
39305b261ecSmrg    {
39405b261ecSmrg	if (!PartialNetwork && partial)
39505b261ecSmrg	{
39605b261ecSmrg	    FatalError ("Failed to establish all listening sockets");
39705b261ecSmrg	}
39805b261ecSmrg	else
39905b261ecSmrg	{
4006747b715Smrg	    ListenTransFds = malloc(ListenTransCount * sizeof (int));
40105b261ecSmrg
40205b261ecSmrg	    for (i = 0; i < ListenTransCount; i++)
40305b261ecSmrg	    {
40405b261ecSmrg		int fd = _XSERVTransGetConnectionNumber (ListenTransConns[i]);
40505b261ecSmrg
40605b261ecSmrg		ListenTransFds[i] = fd;
40705b261ecSmrg		FD_SET (fd, &WellKnownConnections);
40805b261ecSmrg
40905b261ecSmrg		if (!_XSERVTransIsLocal (ListenTransConns[i]))
41005b261ecSmrg		{
41105b261ecSmrg		    DefineSelf (fd);
41205b261ecSmrg		}
41305b261ecSmrg	    }
41405b261ecSmrg	}
41505b261ecSmrg    }
41605b261ecSmrg
41705b261ecSmrg    if (!XFD_ANYSET (&WellKnownConnections))
41805b261ecSmrg        FatalError ("Cannot establish any listening sockets - Make sure an X server isn't already running");
41905b261ecSmrg#if !defined(WIN32)
42005b261ecSmrg    OsSignal (SIGPIPE, SIG_IGN);
42105b261ecSmrg    OsSignal (SIGHUP, AutoResetServer);
42205b261ecSmrg#endif
42305b261ecSmrg    OsSignal (SIGINT, GiveUp);
42405b261ecSmrg    OsSignal (SIGTERM, GiveUp);
42505b261ecSmrg    XFD_COPYSET (&WellKnownConnections, &AllSockets);
42605b261ecSmrg    ResetHosts(display);
4274642e01fSmrg
4284642e01fSmrg    InitParentProcess();
4294642e01fSmrg
43005b261ecSmrg#ifdef XDMCP
43105b261ecSmrg    XdmcpInit ();
43205b261ecSmrg#endif
43305b261ecSmrg}
43405b261ecSmrg
43505b261ecSmrgvoid
43605b261ecSmrgResetWellKnownSockets (void)
43705b261ecSmrg{
43805b261ecSmrg    int i;
43905b261ecSmrg
44005b261ecSmrg    ResetOsBuffers();
44105b261ecSmrg
44205b261ecSmrg    for (i = 0; i < ListenTransCount; i++)
44305b261ecSmrg    {
44405b261ecSmrg	int status = _XSERVTransResetListener (ListenTransConns[i]);
44505b261ecSmrg
44605b261ecSmrg	if (status != TRANS_RESET_NOOP)
44705b261ecSmrg	{
44805b261ecSmrg	    if (status == TRANS_RESET_FAILURE)
44905b261ecSmrg	    {
45005b261ecSmrg		/*
45105b261ecSmrg		 * ListenTransConns[i] freed by xtrans.
45205b261ecSmrg		 * Remove it from out list.
45305b261ecSmrg		 */
45405b261ecSmrg
45505b261ecSmrg		FD_CLR (ListenTransFds[i], &WellKnownConnections);
45605b261ecSmrg		ListenTransFds[i] = ListenTransFds[ListenTransCount - 1];
45705b261ecSmrg		ListenTransConns[i] = ListenTransConns[ListenTransCount - 1];
45805b261ecSmrg		ListenTransCount -= 1;
45905b261ecSmrg		i -= 1;
46005b261ecSmrg	    }
46105b261ecSmrg	    else if (status == TRANS_RESET_NEW_FD)
46205b261ecSmrg	    {
46305b261ecSmrg		/*
46405b261ecSmrg		 * A new file descriptor was allocated (the old one was closed)
46505b261ecSmrg		 */
46605b261ecSmrg
46705b261ecSmrg		int newfd = _XSERVTransGetConnectionNumber (ListenTransConns[i]);
46805b261ecSmrg
46905b261ecSmrg		FD_CLR (ListenTransFds[i], &WellKnownConnections);
47005b261ecSmrg		ListenTransFds[i] = newfd;
47105b261ecSmrg		FD_SET(newfd, &WellKnownConnections);
47205b261ecSmrg	    }
47305b261ecSmrg	}
47405b261ecSmrg    }
47505b261ecSmrg
47605b261ecSmrg    ResetAuthorization ();
47705b261ecSmrg    ResetHosts(display);
47805b261ecSmrg    /*
47905b261ecSmrg     * restart XDMCP
48005b261ecSmrg     */
48105b261ecSmrg#ifdef XDMCP
48205b261ecSmrg    XdmcpReset ();
48305b261ecSmrg#endif
48405b261ecSmrg}
48505b261ecSmrg
48605b261ecSmrgvoid
48705b261ecSmrgCloseWellKnownConnections(void)
48805b261ecSmrg{
48905b261ecSmrg    int i;
49005b261ecSmrg
49105b261ecSmrg    for (i = 0; i < ListenTransCount; i++)
49205b261ecSmrg	_XSERVTransClose (ListenTransConns[i]);
49305b261ecSmrg}
49405b261ecSmrg
49505b261ecSmrgstatic void
49605b261ecSmrgAuthAudit (ClientPtr client, Bool letin,
49705b261ecSmrg    struct sockaddr *saddr, int len,
49805b261ecSmrg    unsigned int proto_n, char *auth_proto, int auth_id)
49905b261ecSmrg{
50005b261ecSmrg    char addr[128];
50105b261ecSmrg    char *out = addr;
50205b261ecSmrg    char client_uid_string[64];
5034642e01fSmrg    LocalClientCredRec *lcc;
5044642e01fSmrg#ifdef XSERVER_DTRACE
50505b261ecSmrg    pid_t client_pid = -1;
50605b261ecSmrg    zoneid_t client_zid = -1;
50705b261ecSmrg#endif
50805b261ecSmrg
50905b261ecSmrg    if (!len)
51005b261ecSmrg        strcpy(out, "local host");
51105b261ecSmrg    else
51205b261ecSmrg	switch (saddr->sa_family)
51305b261ecSmrg	{
51405b261ecSmrg	case AF_UNSPEC:
51505b261ecSmrg#if defined(UNIXCONN) || defined(LOCALCONN)
51605b261ecSmrg	case AF_UNIX:
51705b261ecSmrg#endif
51805b261ecSmrg	    strcpy(out, "local host");
51905b261ecSmrg	    break;
52005b261ecSmrg#if defined(TCPCONN) || defined(STREAMSCONN) || defined(MNX_TCPCONN)
52105b261ecSmrg	case AF_INET:
52205b261ecSmrg	    sprintf(out, "IP %s",
52305b261ecSmrg		inet_ntoa(((struct sockaddr_in *) saddr)->sin_addr));
52405b261ecSmrg	    break;
52505b261ecSmrg#if defined(IPv6) && defined(AF_INET6)
52605b261ecSmrg	case AF_INET6: {
52705b261ecSmrg	    char ipaddr[INET6_ADDRSTRLEN];
52805b261ecSmrg	    inet_ntop(AF_INET6, &((struct sockaddr_in6 *) saddr)->sin6_addr,
52905b261ecSmrg	      ipaddr, sizeof(ipaddr));
53005b261ecSmrg	    sprintf(out, "IP %s", ipaddr);
53105b261ecSmrg	}
53205b261ecSmrg	    break;
53305b261ecSmrg#endif
53405b261ecSmrg#endif
53505b261ecSmrg#ifdef DNETCONN
53605b261ecSmrg	case AF_DECnet:
53705b261ecSmrg	    sprintf(out, "DN %s",
53805b261ecSmrg		    dnet_ntoa(&((struct sockaddr_dn *) saddr)->sdn_add));
53905b261ecSmrg	    break;
54005b261ecSmrg#endif
54105b261ecSmrg	default:
54205b261ecSmrg	    strcpy(out, "unknown address");
54305b261ecSmrg	}
54405b261ecSmrg
5454642e01fSmrg    if (GetLocalClientCreds(client, &lcc) != -1) {
5464642e01fSmrg	int slen; /* length written to client_uid_string */
5474642e01fSmrg
5484642e01fSmrg	strcpy(client_uid_string, " ( ");
5494642e01fSmrg	slen = 3;
5504642e01fSmrg
5514642e01fSmrg	if (lcc->fieldsSet & LCC_UID_SET) {
5524642e01fSmrg	    snprintf(client_uid_string + slen,
5534642e01fSmrg		     sizeof(client_uid_string) - slen,
5544642e01fSmrg		     "uid=%ld ", (long) lcc->euid);
5554642e01fSmrg	    slen = strlen(client_uid_string);
5564642e01fSmrg	}
5574642e01fSmrg
5584642e01fSmrg	if (lcc->fieldsSet & LCC_GID_SET) {
5594642e01fSmrg	    snprintf(client_uid_string + slen,
5604642e01fSmrg		     sizeof(client_uid_string) - slen,
5614642e01fSmrg		     "gid=%ld ", (long) lcc->egid);
5624642e01fSmrg	    slen = strlen(client_uid_string);
5634642e01fSmrg	}
5644642e01fSmrg
5654642e01fSmrg	if (lcc->fieldsSet & LCC_PID_SET) {
5664642e01fSmrg#ifdef XSERVER_DTRACE
5674642e01fSmrg	    client_pid = lcc->pid;
56805b261ecSmrg#endif
5694642e01fSmrg	    snprintf(client_uid_string + slen,
5704642e01fSmrg		     sizeof(client_uid_string) - slen,
5714642e01fSmrg		     "pid=%ld ", (long) lcc->pid);
5724642e01fSmrg	    slen = strlen(client_uid_string);
5734642e01fSmrg	}
5744642e01fSmrg
5754642e01fSmrg	if (lcc->fieldsSet & LCC_ZID_SET) {
5764642e01fSmrg#ifdef XSERVER_DTRACE
5774642e01fSmrg	    client_zid = lcc->zoneid;
5784642e01fSmrg#endif
5794642e01fSmrg	    snprintf(client_uid_string + slen,
5804642e01fSmrg		     sizeof(client_uid_string) - slen,
5814642e01fSmrg		     "zoneid=%ld ", (long) lcc->zoneid);
5824642e01fSmrg	    slen = strlen(client_uid_string);
5834642e01fSmrg	}
5844642e01fSmrg
5854642e01fSmrg	snprintf(client_uid_string + slen, sizeof(client_uid_string) - slen,
5864642e01fSmrg		 ")");
5874642e01fSmrg	FreeLocalClientCreds(lcc);
5884642e01fSmrg    }
58905b261ecSmrg    else {
59005b261ecSmrg	client_uid_string[0] = '\0';
59105b261ecSmrg    }
59205b261ecSmrg
59305b261ecSmrg#ifdef XSERVER_DTRACE
59405b261ecSmrg    XSERVER_CLIENT_AUTH(client->index, addr, client_pid, client_zid);
59505b261ecSmrg#endif
5964642e01fSmrg    if (auditTrailLevel > 1) {
59705b261ecSmrg      if (proto_n)
59805b261ecSmrg	AuditF("client %d %s from %s%s\n  Auth name: %.*s ID: %d\n",
59905b261ecSmrg	       client->index, letin ? "connected" : "rejected", addr,
60005b261ecSmrg	       client_uid_string, (int)proto_n, auth_proto, auth_id);
60105b261ecSmrg      else
60205b261ecSmrg	AuditF("client %d %s from %s%s\n",
60305b261ecSmrg	       client->index, letin ? "connected" : "rejected", addr,
60405b261ecSmrg	       client_uid_string);
60505b261ecSmrg
60605b261ecSmrg    }
60705b261ecSmrg}
60805b261ecSmrg
60905b261ecSmrgXID
61005b261ecSmrgAuthorizationIDOfClient(ClientPtr client)
61105b261ecSmrg{
61205b261ecSmrg    if (client->osPrivate)
61305b261ecSmrg	return ((OsCommPtr)client->osPrivate)->auth_id;
61405b261ecSmrg    else
61505b261ecSmrg	return None;
61605b261ecSmrg}
61705b261ecSmrg
61805b261ecSmrg
61905b261ecSmrg/*****************************************************************
62005b261ecSmrg * ClientAuthorized
62105b261ecSmrg *
62205b261ecSmrg *    Sent by the client at connection setup:
62305b261ecSmrg *                typedef struct _xConnClientPrefix {
62405b261ecSmrg *                   CARD8	byteOrder;
62505b261ecSmrg *                   BYTE	pad;
62605b261ecSmrg *                   CARD16	majorVersion, minorVersion;
62705b261ecSmrg *                   CARD16	nbytesAuthProto;
62805b261ecSmrg *                   CARD16	nbytesAuthString;
62905b261ecSmrg *                 } xConnClientPrefix;
63005b261ecSmrg *
63105b261ecSmrg *     	It is hoped that eventually one protocol will be agreed upon.  In the
63205b261ecSmrg *        mean time, a server that implements a different protocol than the
63305b261ecSmrg *        client expects, or a server that only implements the host-based
63405b261ecSmrg *        mechanism, will simply ignore this information.
63505b261ecSmrg *
63605b261ecSmrg *****************************************************************/
63705b261ecSmrg
6386747b715Smrgchar *
63905b261ecSmrgClientAuthorized(ClientPtr client,
64005b261ecSmrg    unsigned int proto_n, char *auth_proto,
64105b261ecSmrg    unsigned int string_n, char *auth_string)
64205b261ecSmrg{
64305b261ecSmrg    OsCommPtr 		priv;
64405b261ecSmrg    Xtransaddr		*from = NULL;
64505b261ecSmrg    int 		family;
64605b261ecSmrg    int			fromlen;
64705b261ecSmrg    XID	 		auth_id;
64805b261ecSmrg    char	 	*reason = NULL;
64905b261ecSmrg    XtransConnInfo	trans_conn;
65005b261ecSmrg
65105b261ecSmrg    priv = (OsCommPtr)client->osPrivate;
65205b261ecSmrg    trans_conn = priv->trans_conn;
65305b261ecSmrg
6544642e01fSmrg    /* Allow any client to connect without authorization on a launchd socket,
6554642e01fSmrg       because it is securely created -- this prevents a race condition on launch */
6564642e01fSmrg    if(trans_conn->flags & TRANS_NOXAUTH) {
6574642e01fSmrg        auth_id = (XID) 0L;
6584642e01fSmrg    } else {
6594642e01fSmrg        auth_id = CheckAuthorization (proto_n, auth_proto, string_n, auth_string, client, &reason);
6604642e01fSmrg    }
66105b261ecSmrg
66205b261ecSmrg    if (auth_id == (XID) ~0L)
66305b261ecSmrg    {
6644642e01fSmrg	if (_XSERVTransGetPeerAddr(trans_conn, &family, &fromlen, &from) != -1)
66505b261ecSmrg	{
66605b261ecSmrg	    if (InvalidHost ((struct sockaddr *) from, fromlen, client))
66705b261ecSmrg		AuthAudit(client, FALSE, (struct sockaddr *) from,
66805b261ecSmrg			  fromlen, proto_n, auth_proto, auth_id);
66905b261ecSmrg	    else
67005b261ecSmrg	    {
67105b261ecSmrg		auth_id = (XID) 0;
67205b261ecSmrg#ifdef XSERVER_DTRACE
67305b261ecSmrg		if ((auditTrailLevel > 1) || XSERVER_CLIENT_AUTH_ENABLED())
67405b261ecSmrg#else
67505b261ecSmrg		if (auditTrailLevel > 1)
67605b261ecSmrg#endif
67705b261ecSmrg		    AuthAudit(client, TRUE,
67805b261ecSmrg			(struct sockaddr *) from, fromlen,
67905b261ecSmrg			proto_n, auth_proto, auth_id);
68005b261ecSmrg	    }
68105b261ecSmrg
6826747b715Smrg	    free(from);
68305b261ecSmrg	}
68405b261ecSmrg
68505b261ecSmrg	if (auth_id == (XID) ~0L) {
68605b261ecSmrg	    if (reason)
68705b261ecSmrg		return reason;
68805b261ecSmrg	    else
68905b261ecSmrg		return "Client is not authorized to connect to Server";
69005b261ecSmrg	}
69105b261ecSmrg    }
69205b261ecSmrg#ifdef XSERVER_DTRACE
69305b261ecSmrg    else if ((auditTrailLevel > 1) || XSERVER_CLIENT_AUTH_ENABLED())
69405b261ecSmrg#else
69505b261ecSmrg    else if (auditTrailLevel > 1)
69605b261ecSmrg#endif
69705b261ecSmrg    {
69805b261ecSmrg	if (_XSERVTransGetPeerAddr (trans_conn,
69905b261ecSmrg	    &family, &fromlen, &from) != -1)
70005b261ecSmrg	{
70105b261ecSmrg	    AuthAudit(client, TRUE, (struct sockaddr *) from, fromlen,
70205b261ecSmrg		      proto_n, auth_proto, auth_id);
70305b261ecSmrg
7046747b715Smrg	    free(from);
70505b261ecSmrg	}
70605b261ecSmrg    }
70705b261ecSmrg    priv->auth_id = auth_id;
70805b261ecSmrg    priv->conn_time = 0;
70905b261ecSmrg
71005b261ecSmrg#ifdef XDMCP
71105b261ecSmrg    /* indicate to Xdmcp protocol that we've opened new client */
71205b261ecSmrg    XdmcpOpenDisplay(priv->fd);
71305b261ecSmrg#endif /* XDMCP */
71405b261ecSmrg
71505b261ecSmrg    XaceHook(XACE_AUTH_AVAIL, client, auth_id);
71605b261ecSmrg
71705b261ecSmrg    /* At this point, if the client is authorized to change the access control
71805b261ecSmrg     * list, we should getpeername() information, and add the client to
71905b261ecSmrg     * the selfhosts list.  It's not really the host machine, but the
72005b261ecSmrg     * true purpose of the selfhosts list is to see who may change the
72105b261ecSmrg     * access control list.
72205b261ecSmrg     */
72305b261ecSmrg    return((char *)NULL);
72405b261ecSmrg}
72505b261ecSmrg
72605b261ecSmrgstatic ClientPtr
72705b261ecSmrgAllocNewConnection (XtransConnInfo trans_conn, int fd, CARD32 conn_time)
72805b261ecSmrg{
72905b261ecSmrg    OsCommPtr	oc;
73005b261ecSmrg    ClientPtr	client;
73105b261ecSmrg
73205b261ecSmrg    if (
73305b261ecSmrg#ifndef WIN32
73405b261ecSmrg	fd >= lastfdesc
73505b261ecSmrg#else
73605b261ecSmrg	XFD_SETCOUNT(&AllClients) >= MaxClients
73705b261ecSmrg#endif
73805b261ecSmrg	)
73905b261ecSmrg	return NullClient;
7406747b715Smrg    oc = malloc(sizeof(OsCommRec));
74105b261ecSmrg    if (!oc)
74205b261ecSmrg	return NullClient;
74305b261ecSmrg    oc->trans_conn = trans_conn;
74405b261ecSmrg    oc->fd = fd;
74505b261ecSmrg    oc->input = (ConnectionInputPtr)NULL;
74605b261ecSmrg    oc->output = (ConnectionOutputPtr)NULL;
74705b261ecSmrg    oc->auth_id = None;
74805b261ecSmrg    oc->conn_time = conn_time;
74905b261ecSmrg    if (!(client = NextAvailableClient((pointer)oc)))
75005b261ecSmrg    {
7516747b715Smrg	free(oc);
75205b261ecSmrg	return NullClient;
75305b261ecSmrg    }
75405b261ecSmrg#if !defined(WIN32)
75505b261ecSmrg    ConnectionTranslation[fd] = client->index;
75605b261ecSmrg#else
75705b261ecSmrg    SetConnectionTranslation(fd, client->index);
75805b261ecSmrg#endif
75905b261ecSmrg    if (GrabInProgress)
76005b261ecSmrg    {
76105b261ecSmrg        FD_SET(fd, &SavedAllClients);
76205b261ecSmrg        FD_SET(fd, &SavedAllSockets);
76305b261ecSmrg    }
76405b261ecSmrg    else
76505b261ecSmrg    {
76605b261ecSmrg        FD_SET(fd, &AllClients);
76705b261ecSmrg        FD_SET(fd, &AllSockets);
76805b261ecSmrg    }
76905b261ecSmrg
77005b261ecSmrg#ifdef DEBUG
77105b261ecSmrg    ErrorF("AllocNewConnection: client index = %d, socket fd = %d\n",
77205b261ecSmrg	   client->index, fd);
77305b261ecSmrg#endif
77405b261ecSmrg#ifdef XSERVER_DTRACE
77505b261ecSmrg    XSERVER_CLIENT_CONNECT(client->index, fd);
77605b261ecSmrg#endif
77705b261ecSmrg
77805b261ecSmrg    return client;
77905b261ecSmrg}
78005b261ecSmrg
78105b261ecSmrg/*****************
78205b261ecSmrg * EstablishNewConnections
78305b261ecSmrg *    If anyone is waiting on listened sockets, accept them.
78405b261ecSmrg *    Returns a mask with indices of new clients.  Updates AllClients
78505b261ecSmrg *    and AllSockets.
78605b261ecSmrg *****************/
78705b261ecSmrg
78805b261ecSmrg/*ARGSUSED*/
78905b261ecSmrgBool
79005b261ecSmrgEstablishNewConnections(ClientPtr clientUnused, pointer closure)
79105b261ecSmrg{
79205b261ecSmrg    fd_set  readyconnections;     /* set of listeners that are ready */
79305b261ecSmrg    int curconn;                  /* fd of listener that's ready */
79405b261ecSmrg    register int newconn;         /* fd of new client */
79505b261ecSmrg    CARD32 connect_time;
79605b261ecSmrg    register int i;
79705b261ecSmrg    register ClientPtr client;
79805b261ecSmrg    register OsCommPtr oc;
79905b261ecSmrg    fd_set tmask;
80005b261ecSmrg
80105b261ecSmrg    XFD_ANDSET (&tmask, (fd_set*)closure, &WellKnownConnections);
80205b261ecSmrg    XFD_COPYSET(&tmask, &readyconnections);
80305b261ecSmrg    if (!XFD_ANYSET(&readyconnections))
80405b261ecSmrg	return TRUE;
80505b261ecSmrg    connect_time = GetTimeInMillis();
80605b261ecSmrg    /* kill off stragglers */
80705b261ecSmrg    for (i=1; i<currentMaxClients; i++)
80805b261ecSmrg    {
80905b261ecSmrg	if ((client = clients[i]))
81005b261ecSmrg	{
81105b261ecSmrg	    oc = (OsCommPtr)(client->osPrivate);
81205b261ecSmrg	    if ((oc && (oc->conn_time != 0) &&
81305b261ecSmrg		(connect_time - oc->conn_time) >= TimeOutValue) ||
81405b261ecSmrg		(client->noClientException != Success && !client->clientGone))
81505b261ecSmrg		CloseDownClient(client);
81605b261ecSmrg	}
81705b261ecSmrg    }
81805b261ecSmrg#ifndef WIN32
81905b261ecSmrg    for (i = 0; i < howmany(XFD_SETSIZE, NFDBITS); i++)
82005b261ecSmrg    {
82105b261ecSmrg      while (readyconnections.fds_bits[i])
82205b261ecSmrg#else
82305b261ecSmrg      for (i = 0; i < XFD_SETCOUNT(&readyconnections); i++)
82405b261ecSmrg#endif
82505b261ecSmrg      {
82605b261ecSmrg	XtransConnInfo trans_conn, new_trans_conn;
82705b261ecSmrg	int status;
82805b261ecSmrg
82905b261ecSmrg#ifndef WIN32
8306747b715Smrg	curconn = mffs (readyconnections.fds_bits[i]) - 1;
83105b261ecSmrg	readyconnections.fds_bits[i] &= ~((fd_mask)1 << curconn);
83205b261ecSmrg	curconn += (i * (sizeof(fd_mask)*8));
83305b261ecSmrg#else
83405b261ecSmrg	curconn = XFD_FD(&readyconnections, i);
83505b261ecSmrg#endif
83605b261ecSmrg
83705b261ecSmrg	if ((trans_conn = lookup_trans_conn (curconn)) == NULL)
83805b261ecSmrg	    continue;
83905b261ecSmrg
84005b261ecSmrg	if ((new_trans_conn = _XSERVTransAccept (trans_conn, &status)) == NULL)
84105b261ecSmrg	    continue;
84205b261ecSmrg
84305b261ecSmrg	newconn = _XSERVTransGetConnectionNumber (new_trans_conn);
84405b261ecSmrg
84505b261ecSmrg	if (newconn < lastfdesc)
84605b261ecSmrg	{
84705b261ecSmrg		int clientid;
84805b261ecSmrg#if !defined(WIN32)
84905b261ecSmrg  		clientid = ConnectionTranslation[newconn];
85005b261ecSmrg#else
85105b261ecSmrg  		clientid = GetConnectionTranslation(newconn);
85205b261ecSmrg#endif
85305b261ecSmrg		if(clientid && (client = clients[clientid]))
85405b261ecSmrg 			CloseDownClient(client);
85505b261ecSmrg	}
85605b261ecSmrg
85705b261ecSmrg	_XSERVTransSetOption(new_trans_conn, TRANS_NONBLOCKING, 1);
85805b261ecSmrg
85905b261ecSmrg	if (!AllocNewConnection (new_trans_conn, newconn, connect_time))
86005b261ecSmrg	{
86105b261ecSmrg	    ErrorConnMax(new_trans_conn);
86205b261ecSmrg	    _XSERVTransClose(new_trans_conn);
86305b261ecSmrg	}
8644642e01fSmrg
8654642e01fSmrg	if(trans_conn->flags & TRANS_NOXAUTH)
8664642e01fSmrg	    new_trans_conn->flags = new_trans_conn->flags | TRANS_NOXAUTH;
8674642e01fSmrg
86805b261ecSmrg      }
86905b261ecSmrg#ifndef WIN32
87005b261ecSmrg    }
87105b261ecSmrg#endif
87205b261ecSmrg    return TRUE;
87305b261ecSmrg}
87405b261ecSmrg
87505b261ecSmrg#define NOROOM "Maximum number of clients reached"
87605b261ecSmrg
87705b261ecSmrg/************
87805b261ecSmrg *   ErrorConnMax
87905b261ecSmrg *     Fail a connection due to lack of client or file descriptor space
88005b261ecSmrg ************/
88105b261ecSmrg
88205b261ecSmrgstatic void
88305b261ecSmrgErrorConnMax(XtransConnInfo trans_conn)
88405b261ecSmrg{
88505b261ecSmrg    int fd = _XSERVTransGetConnectionNumber (trans_conn);
88605b261ecSmrg    xConnSetupPrefix csp;
88705b261ecSmrg    char pad[3];
88805b261ecSmrg    struct iovec iov[3];
88905b261ecSmrg    char byteOrder = 0;
89005b261ecSmrg    int whichbyte = 1;
89105b261ecSmrg    struct timeval waittime;
89205b261ecSmrg    fd_set mask;
89305b261ecSmrg
89405b261ecSmrg    /* if these seems like a lot of trouble to go to, it probably is */
89505b261ecSmrg    waittime.tv_sec = BOTIMEOUT / MILLI_PER_SECOND;
89605b261ecSmrg    waittime.tv_usec = (BOTIMEOUT % MILLI_PER_SECOND) *
89705b261ecSmrg		       (1000000 / MILLI_PER_SECOND);
89805b261ecSmrg    FD_ZERO(&mask);
89905b261ecSmrg    FD_SET(fd, &mask);
90005b261ecSmrg    (void)Select(fd + 1, &mask, NULL, NULL, &waittime);
90105b261ecSmrg    /* try to read the byte-order of the connection */
90205b261ecSmrg    (void)_XSERVTransRead(trans_conn, &byteOrder, 1);
90305b261ecSmrg    if ((byteOrder == 'l') || (byteOrder == 'B'))
90405b261ecSmrg    {
90505b261ecSmrg	csp.success = xFalse;
90605b261ecSmrg	csp.lengthReason = sizeof(NOROOM) - 1;
90705b261ecSmrg	csp.length = (sizeof(NOROOM) + 2) >> 2;
90805b261ecSmrg	csp.majorVersion = X_PROTOCOL;
90905b261ecSmrg	csp.minorVersion = X_PROTOCOL_REVISION;
91005b261ecSmrg	if (((*(char *) &whichbyte) && (byteOrder == 'B')) ||
91105b261ecSmrg	    (!(*(char *) &whichbyte) && (byteOrder == 'l')))
91205b261ecSmrg	{
91305b261ecSmrg	    swaps(&csp.majorVersion, whichbyte);
91405b261ecSmrg	    swaps(&csp.minorVersion, whichbyte);
91505b261ecSmrg	    swaps(&csp.length, whichbyte);
91605b261ecSmrg	}
91705b261ecSmrg	iov[0].iov_len = sz_xConnSetupPrefix;
91805b261ecSmrg	iov[0].iov_base = (char *) &csp;
91905b261ecSmrg	iov[1].iov_len = csp.lengthReason;
92005b261ecSmrg	iov[1].iov_base = NOROOM;
92105b261ecSmrg	iov[2].iov_len = (4 - (csp.lengthReason & 3)) & 3;
92205b261ecSmrg	iov[2].iov_base = pad;
92305b261ecSmrg	(void)_XSERVTransWritev(trans_conn, iov, 3);
92405b261ecSmrg    }
92505b261ecSmrg}
92605b261ecSmrg
92705b261ecSmrg/************
92805b261ecSmrg *   CloseDownFileDescriptor:
92905b261ecSmrg *     Remove this file descriptor and it's I/O buffers, etc.
93005b261ecSmrg ************/
93105b261ecSmrg
93205b261ecSmrgstatic void
93305b261ecSmrgCloseDownFileDescriptor(OsCommPtr oc)
93405b261ecSmrg{
93505b261ecSmrg    int connection = oc->fd;
93605b261ecSmrg
93705b261ecSmrg    if (oc->trans_conn) {
93805b261ecSmrg	_XSERVTransDisconnect(oc->trans_conn);
93905b261ecSmrg	_XSERVTransClose(oc->trans_conn);
94005b261ecSmrg    }
94105b261ecSmrg#ifndef WIN32
94205b261ecSmrg    ConnectionTranslation[connection] = 0;
94305b261ecSmrg#else
94405b261ecSmrg    SetConnectionTranslation(connection, 0);
94505b261ecSmrg#endif
94605b261ecSmrg    FD_CLR(connection, &AllSockets);
94705b261ecSmrg    FD_CLR(connection, &AllClients);
94805b261ecSmrg    FD_CLR(connection, &ClientsWithInput);
94905b261ecSmrg    FD_CLR(connection, &GrabImperviousClients);
95005b261ecSmrg    if (GrabInProgress)
95105b261ecSmrg    {
95205b261ecSmrg	FD_CLR(connection, &SavedAllSockets);
95305b261ecSmrg	FD_CLR(connection, &SavedAllClients);
95405b261ecSmrg	FD_CLR(connection, &SavedClientsWithInput);
95505b261ecSmrg    }
95605b261ecSmrg    FD_CLR(connection, &ClientsWriteBlocked);
95705b261ecSmrg    if (!XFD_ANYSET(&ClientsWriteBlocked))
95805b261ecSmrg    	AnyClientsWriteBlocked = FALSE;
95905b261ecSmrg    FD_CLR(connection, &OutputPending);
96005b261ecSmrg}
96105b261ecSmrg
96205b261ecSmrg/*****************
96305b261ecSmrg * CheckConnections
96405b261ecSmrg *    Some connection has died, go find which one and shut it down
96505b261ecSmrg *    The file descriptor has been closed, but is still in AllClients.
96605b261ecSmrg *    If would truly be wonderful if select() would put the bogus
96705b261ecSmrg *    file descriptors in the exception mask, but nooooo.  So we have
96805b261ecSmrg *    to check each and every socket individually.
96905b261ecSmrg *****************/
97005b261ecSmrg
97105b261ecSmrgvoid
97205b261ecSmrgCheckConnections(void)
97305b261ecSmrg{
97405b261ecSmrg#ifndef WIN32
97505b261ecSmrg    fd_mask		mask;
97605b261ecSmrg#endif
97705b261ecSmrg    fd_set		tmask;
97805b261ecSmrg    int			curclient, curoff;
97905b261ecSmrg    int			i;
98005b261ecSmrg    struct timeval	notime;
98105b261ecSmrg    int r;
98205b261ecSmrg#ifdef WIN32
98305b261ecSmrg    fd_set savedAllClients;
98405b261ecSmrg#endif
98505b261ecSmrg
98605b261ecSmrg    notime.tv_sec = 0;
98705b261ecSmrg    notime.tv_usec = 0;
98805b261ecSmrg
98905b261ecSmrg#ifndef WIN32
99005b261ecSmrg    for (i=0; i<howmany(XFD_SETSIZE, NFDBITS); i++)
99105b261ecSmrg    {
99205b261ecSmrg	mask = AllClients.fds_bits[i];
99305b261ecSmrg        while (mask)
99405b261ecSmrg    	{
9956747b715Smrg	    curoff = mffs (mask) - 1;
99605b261ecSmrg	    curclient = curoff + (i * (sizeof(fd_mask)*8));
99705b261ecSmrg            FD_ZERO(&tmask);
99805b261ecSmrg            FD_SET(curclient, &tmask);
99905b261ecSmrg            do {
100005b261ecSmrg                r = Select (curclient + 1, &tmask, NULL, NULL, &notime);
100105b261ecSmrg            } while (r < 0 && (errno == EINTR || errno == EAGAIN));
100205b261ecSmrg            if (r < 0)
100305b261ecSmrg                if (ConnectionTranslation[curclient] > 0)
100405b261ecSmrg                    CloseDownClient(clients[ConnectionTranslation[curclient]]);
100505b261ecSmrg	    mask &= ~((fd_mask)1 << curoff);
100605b261ecSmrg	}
100705b261ecSmrg    }
100805b261ecSmrg#else
100905b261ecSmrg    XFD_COPYSET(&AllClients, &savedAllClients);
101005b261ecSmrg    for (i = 0; i < XFD_SETCOUNT(&savedAllClients); i++)
101105b261ecSmrg    {
101205b261ecSmrg	curclient = XFD_FD(&savedAllClients, i);
101305b261ecSmrg	FD_ZERO(&tmask);
101405b261ecSmrg	FD_SET(curclient, &tmask);
101505b261ecSmrg        do {
101605b261ecSmrg            r = Select (curclient + 1, &tmask, NULL, NULL, &notime);
101705b261ecSmrg        } while (r < 0 && (errno == EINTR || errno == EAGAIN));
101805b261ecSmrg	if (r < 0)
101905b261ecSmrg            if (GetConnectionTranslation(curclient) > 0)
102005b261ecSmrg                CloseDownClient(clients[GetConnectionTranslation(curclient)]);
102105b261ecSmrg    }
102205b261ecSmrg#endif
102305b261ecSmrg}
102405b261ecSmrg
102505b261ecSmrg
102605b261ecSmrg/*****************
102705b261ecSmrg * CloseDownConnection
102805b261ecSmrg *    Delete client from AllClients and free resources
102905b261ecSmrg *****************/
103005b261ecSmrg
103105b261ecSmrgvoid
103205b261ecSmrgCloseDownConnection(ClientPtr client)
103305b261ecSmrg{
103405b261ecSmrg    OsCommPtr oc = (OsCommPtr)client->osPrivate;
103505b261ecSmrg
10366747b715Smrg    if (FlushCallback)
10376747b715Smrg	CallCallbacks(&FlushCallback, NULL);
10386747b715Smrg
103905b261ecSmrg    if (oc->output && oc->output->count)
104005b261ecSmrg	FlushClient(client, oc, (char *)NULL, 0);
104105b261ecSmrg#ifdef XDMCP
104205b261ecSmrg    XdmcpCloseDisplay(oc->fd);
104305b261ecSmrg#endif
104405b261ecSmrg    CloseDownFileDescriptor(oc);
104505b261ecSmrg    FreeOsBuffers(oc);
10466747b715Smrg    free(client->osPrivate);
104705b261ecSmrg    client->osPrivate = (pointer)NULL;
104805b261ecSmrg    if (auditTrailLevel > 1)
104905b261ecSmrg	AuditF("client %d disconnected\n", client->index);
105005b261ecSmrg}
105105b261ecSmrg
10526747b715Smrgvoid
105305b261ecSmrgAddGeneralSocket(int fd)
105405b261ecSmrg{
105505b261ecSmrg    FD_SET(fd, &AllSockets);
105605b261ecSmrg    if (GrabInProgress)
105705b261ecSmrg	FD_SET(fd, &SavedAllSockets);
105805b261ecSmrg}
105905b261ecSmrg
10606747b715Smrgvoid
106105b261ecSmrgAddEnabledDevice(int fd)
106205b261ecSmrg{
106305b261ecSmrg    FD_SET(fd, &EnabledDevices);
106405b261ecSmrg    AddGeneralSocket(fd);
106505b261ecSmrg}
106605b261ecSmrg
10676747b715Smrgvoid
106805b261ecSmrgRemoveGeneralSocket(int fd)
106905b261ecSmrg{
107005b261ecSmrg    FD_CLR(fd, &AllSockets);
107105b261ecSmrg    if (GrabInProgress)
107205b261ecSmrg	FD_CLR(fd, &SavedAllSockets);
107305b261ecSmrg}
107405b261ecSmrg
10756747b715Smrgvoid
107605b261ecSmrgRemoveEnabledDevice(int fd)
107705b261ecSmrg{
107805b261ecSmrg    FD_CLR(fd, &EnabledDevices);
107905b261ecSmrg    RemoveGeneralSocket(fd);
108005b261ecSmrg}
108105b261ecSmrg
108205b261ecSmrg/*****************
108305b261ecSmrg * OnlyListenToOneClient:
108405b261ecSmrg *    Only accept requests from  one client.  Continue to handle new
108505b261ecSmrg *    connections, but don't take any protocol requests from the new
108605b261ecSmrg *    ones.  Note that if GrabInProgress is set, EstablishNewConnections
108705b261ecSmrg *    needs to put new clients into SavedAllSockets and SavedAllClients.
108805b261ecSmrg *    Note also that there is no timeout for this in the protocol.
108905b261ecSmrg *    This routine is "undone" by ListenToAllClients()
109005b261ecSmrg *****************/
109105b261ecSmrg
10924642e01fSmrgint
109305b261ecSmrgOnlyListenToOneClient(ClientPtr client)
109405b261ecSmrg{
109505b261ecSmrg    OsCommPtr oc = (OsCommPtr)client->osPrivate;
10964642e01fSmrg    int rc, connection = oc->fd;
10974642e01fSmrg
10984642e01fSmrg    rc = XaceHook(XACE_SERVER_ACCESS, client, DixGrabAccess);
10994642e01fSmrg    if (rc != Success)
11004642e01fSmrg	return rc;
110105b261ecSmrg
110205b261ecSmrg    if (! GrabInProgress)
110305b261ecSmrg    {
110405b261ecSmrg	XFD_COPYSET(&ClientsWithInput, &SavedClientsWithInput);
110505b261ecSmrg	XFD_ANDSET(&ClientsWithInput,
110605b261ecSmrg		       &ClientsWithInput, &GrabImperviousClients);
110705b261ecSmrg	if (FD_ISSET(connection, &SavedClientsWithInput))
110805b261ecSmrg	{
110905b261ecSmrg	    FD_CLR(connection, &SavedClientsWithInput);
111005b261ecSmrg	    FD_SET(connection, &ClientsWithInput);
111105b261ecSmrg	}
111205b261ecSmrg	XFD_UNSET(&SavedClientsWithInput, &GrabImperviousClients);
111305b261ecSmrg	XFD_COPYSET(&AllSockets, &SavedAllSockets);
111405b261ecSmrg	XFD_COPYSET(&AllClients, &SavedAllClients);
111505b261ecSmrg	XFD_UNSET(&AllSockets, &AllClients);
111605b261ecSmrg	XFD_ANDSET(&AllClients, &AllClients, &GrabImperviousClients);
111705b261ecSmrg	FD_SET(connection, &AllClients);
111805b261ecSmrg	XFD_ORSET(&AllSockets, &AllSockets, &AllClients);
111905b261ecSmrg	GrabInProgress = client->index;
112005b261ecSmrg    }
11214642e01fSmrg    return rc;
112205b261ecSmrg}
112305b261ecSmrg
112405b261ecSmrg/****************
112505b261ecSmrg * ListenToAllClients:
112605b261ecSmrg *    Undoes OnlyListentToOneClient()
112705b261ecSmrg ****************/
112805b261ecSmrg
112905b261ecSmrgvoid
113005b261ecSmrgListenToAllClients(void)
113105b261ecSmrg{
113205b261ecSmrg    if (GrabInProgress)
113305b261ecSmrg    {
113405b261ecSmrg	XFD_ORSET(&AllSockets, &AllSockets, &SavedAllSockets);
113505b261ecSmrg	XFD_ORSET(&AllClients, &AllClients, &SavedAllClients);
113605b261ecSmrg	XFD_ORSET(&ClientsWithInput, &ClientsWithInput, &SavedClientsWithInput);
113705b261ecSmrg	GrabInProgress = 0;
113805b261ecSmrg    }
113905b261ecSmrg}
114005b261ecSmrg
114105b261ecSmrg/****************
114205b261ecSmrg * IgnoreClient
114305b261ecSmrg *    Removes one client from input masks.
114405b261ecSmrg *    Must have cooresponding call to AttendClient.
114505b261ecSmrg ****************/
114605b261ecSmrg
11476747b715Smrgvoid
114805b261ecSmrgIgnoreClient (ClientPtr client)
114905b261ecSmrg{
115005b261ecSmrg    OsCommPtr oc = (OsCommPtr)client->osPrivate;
115105b261ecSmrg    int connection = oc->fd;
115205b261ecSmrg
11536747b715Smrg    client->ignoreCount++;
11546747b715Smrg    if (client->ignoreCount > 1)
11556747b715Smrg	return;
11566747b715Smrg
115705b261ecSmrg    isItTimeToYield = TRUE;
115805b261ecSmrg    if (!GrabInProgress || FD_ISSET(connection, &AllClients))
115905b261ecSmrg    {
116005b261ecSmrg    	if (FD_ISSET (connection, &ClientsWithInput))
116105b261ecSmrg	    FD_SET(connection, &IgnoredClientsWithInput);
116205b261ecSmrg    	else
116305b261ecSmrg	    FD_CLR(connection, &IgnoredClientsWithInput);
116405b261ecSmrg    	FD_CLR(connection, &ClientsWithInput);
116505b261ecSmrg    	FD_CLR(connection, &AllSockets);
116605b261ecSmrg    	FD_CLR(connection, &AllClients);
116705b261ecSmrg	FD_CLR(connection, &LastSelectMask);
116805b261ecSmrg    }
116905b261ecSmrg    else
117005b261ecSmrg    {
117105b261ecSmrg    	if (FD_ISSET (connection, &SavedClientsWithInput))
117205b261ecSmrg	    FD_SET(connection, &IgnoredClientsWithInput);
117305b261ecSmrg    	else
117405b261ecSmrg	    FD_CLR(connection, &IgnoredClientsWithInput);
117505b261ecSmrg	FD_CLR(connection, &SavedClientsWithInput);
117605b261ecSmrg	FD_CLR(connection, &SavedAllSockets);
117705b261ecSmrg	FD_CLR(connection, &SavedAllClients);
117805b261ecSmrg    }
117905b261ecSmrg}
118005b261ecSmrg
118105b261ecSmrg/****************
118205b261ecSmrg * AttendClient
118305b261ecSmrg *    Adds one client back into the input masks.
118405b261ecSmrg ****************/
118505b261ecSmrg
11866747b715Smrgvoid
118705b261ecSmrgAttendClient (ClientPtr client)
118805b261ecSmrg{
118905b261ecSmrg    OsCommPtr oc = (OsCommPtr)client->osPrivate;
119005b261ecSmrg    int connection = oc->fd;
11916747b715Smrg
11926747b715Smrg    client->ignoreCount--;
11936747b715Smrg    if (client->ignoreCount)
11946747b715Smrg	return;
11956747b715Smrg
119605b261ecSmrg    if (!GrabInProgress || GrabInProgress == client->index ||
119705b261ecSmrg	FD_ISSET(connection, &GrabImperviousClients))
119805b261ecSmrg    {
119905b261ecSmrg    	FD_SET(connection, &AllClients);
120005b261ecSmrg    	FD_SET(connection, &AllSockets);
120105b261ecSmrg	FD_SET(connection, &LastSelectMask);
120205b261ecSmrg    	if (FD_ISSET (connection, &IgnoredClientsWithInput))
120305b261ecSmrg	    FD_SET(connection, &ClientsWithInput);
120405b261ecSmrg    }
120505b261ecSmrg    else
120605b261ecSmrg    {
120705b261ecSmrg	FD_SET(connection, &SavedAllClients);
120805b261ecSmrg	FD_SET(connection, &SavedAllSockets);
120905b261ecSmrg	if (FD_ISSET(connection, &IgnoredClientsWithInput))
121005b261ecSmrg	    FD_SET(connection, &SavedClientsWithInput);
121105b261ecSmrg    }
121205b261ecSmrg}
121305b261ecSmrg
121405b261ecSmrg/* make client impervious to grabs; assume only executing client calls this */
121505b261ecSmrg
12164642e01fSmrgvoid
121705b261ecSmrgMakeClientGrabImpervious(ClientPtr client)
121805b261ecSmrg{
121905b261ecSmrg    OsCommPtr oc = (OsCommPtr)client->osPrivate;
122005b261ecSmrg    int connection = oc->fd;
122105b261ecSmrg
122205b261ecSmrg    FD_SET(connection, &GrabImperviousClients);
122305b261ecSmrg
122405b261ecSmrg    if (ServerGrabCallback)
122505b261ecSmrg    {
122605b261ecSmrg	ServerGrabInfoRec grabinfo;
122705b261ecSmrg	grabinfo.client = client;
122805b261ecSmrg	grabinfo.grabstate  = CLIENT_IMPERVIOUS;
122905b261ecSmrg	CallCallbacks(&ServerGrabCallback, &grabinfo);
123005b261ecSmrg    }
123105b261ecSmrg}
123205b261ecSmrg
123305b261ecSmrg/* make client pervious to grabs; assume only executing client calls this */
123405b261ecSmrg
12354642e01fSmrgvoid
123605b261ecSmrgMakeClientGrabPervious(ClientPtr client)
123705b261ecSmrg{
123805b261ecSmrg    OsCommPtr oc = (OsCommPtr)client->osPrivate;
123905b261ecSmrg    int connection = oc->fd;
124005b261ecSmrg
124105b261ecSmrg    FD_CLR(connection, &GrabImperviousClients);
124205b261ecSmrg    if (GrabInProgress && (GrabInProgress != client->index))
124305b261ecSmrg    {
124405b261ecSmrg	if (FD_ISSET(connection, &ClientsWithInput))
124505b261ecSmrg	{
124605b261ecSmrg	    FD_SET(connection, &SavedClientsWithInput);
124705b261ecSmrg	    FD_CLR(connection, &ClientsWithInput);
124805b261ecSmrg	}
124905b261ecSmrg	FD_CLR(connection, &AllSockets);
125005b261ecSmrg	FD_CLR(connection, &AllClients);
125105b261ecSmrg	isItTimeToYield = TRUE;
125205b261ecSmrg    }
125305b261ecSmrg
125405b261ecSmrg    if (ServerGrabCallback)
125505b261ecSmrg    {
125605b261ecSmrg	ServerGrabInfoRec grabinfo;
125705b261ecSmrg	grabinfo.client = client;
125805b261ecSmrg	grabinfo.grabstate  = CLIENT_PERVIOUS;
125905b261ecSmrg	CallCallbacks(&ServerGrabCallback, &grabinfo);
126005b261ecSmrg    }
126105b261ecSmrg}
126205b261ecSmrg
12634642e01fSmrg#ifdef XQUARTZ
12644642e01fSmrg/* Add a fd (from launchd) to our listeners */
12656747b715Smrgvoid ListenOnOpenFD(int fd, int noxauth) {
12664642e01fSmrg    char port[256];
12674642e01fSmrg    XtransConnInfo ciptr;
12686747b715Smrg    const char *display_env = getenv("DISPLAY");
12694642e01fSmrg
12706747b715Smrg    if(display_env && (strncmp(display_env, "/tmp/launch", 11) == 0)) {
12714642e01fSmrg        /* Make the path the launchd socket if our DISPLAY is set right */
12726747b715Smrg        strcpy(port, display_env);
12734642e01fSmrg    } else {
12744642e01fSmrg        /* Just some default so things don't break and die. */
12754642e01fSmrg        sprintf(port, ":%d", atoi(display));
12764642e01fSmrg    }
12774642e01fSmrg
12784642e01fSmrg    /* Make our XtransConnInfo
12794642e01fSmrg     * TRANS_SOCKET_LOCAL_INDEX = 5 from Xtrans.c
12804642e01fSmrg     */
12814642e01fSmrg    ciptr = _XSERVTransReopenCOTSServer(5, fd, port);
12824642e01fSmrg    if(ciptr == NULL) {
12834642e01fSmrg        ErrorF("Got NULL while trying to Reopen launchd port.\n");
12844642e01fSmrg        return;
12854642e01fSmrg    }
12864642e01fSmrg
12874642e01fSmrg    if(noxauth)
12884642e01fSmrg        ciptr->flags = ciptr->flags | TRANS_NOXAUTH;
12894642e01fSmrg
12904642e01fSmrg    /* Allocate space to store it */
12916747b715Smrg    ListenTransFds = (int *) realloc(ListenTransFds, (ListenTransCount + 1) * sizeof (int));
12926747b715Smrg    ListenTransConns = (XtransConnInfo *) realloc(ListenTransConns, (ListenTransCount + 1) * sizeof (XtransConnInfo));
12934642e01fSmrg
12944642e01fSmrg    /* Store it */
12954642e01fSmrg    ListenTransConns[ListenTransCount] = ciptr;
12964642e01fSmrg    ListenTransFds[ListenTransCount] = fd;
12974642e01fSmrg
12984642e01fSmrg    FD_SET(fd, &WellKnownConnections);
12994642e01fSmrg    FD_SET(fd, &AllSockets);
13004642e01fSmrg
13014642e01fSmrg    /* Increment the count */
13024642e01fSmrg    ListenTransCount++;
13034642e01fSmrg
13044642e01fSmrg    /* This *might* not be needed... /shrug */
13054642e01fSmrg    ResetAuthorization();
13064642e01fSmrg    ResetHosts(display);
13074642e01fSmrg#ifdef XDMCP
13084642e01fSmrg    XdmcpReset();
13094642e01fSmrg#endif
13104642e01fSmrg}
13114642e01fSmrg
13124642e01fSmrg#endif
1313