#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#ifdef WIN32
#include <X11/Xwinsock.h>
#endif
#include <X11/X.h>
#include <X11/Xproto.h>
#define XSERV_t
#define TRANS_SERVER
#define TRANS_REOPEN
#include <X11/Xtrans/Xtrans.h>
#include <X11/Xtrans/Xtransint.h>
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#ifndef WIN32
#include <sys/socket.h>
#if defined(TCPCONN) || defined(STREAMSCONN)
# include <netinet/in.h>
# include <arpa/inet.h>
# ifdef apollo
# ifndef NO_TCP_H
# include <netinet/tcp.h>
# endif
# else
# ifdef CSRG_BASED
# include <sys/param.h>
# endif
# include <netinet/tcp.h>
# endif
# include <arpa/inet.h>
#endif
#include <sys/uio.h>
#endif
#include "misc.h"
#include "osdep.h"
#include <X11/Xpoll.h>
#include "opaque.h"
#include "dixstruct.h"
#include "xace.h"
#define Pid_t pid_t
#ifdef HAS_GETPEERUCRED
# include <ucred.h>
# include <zone.h>
#endif
#ifdef XSERVER_DTRACE
# include <sys/types.h>
typedef const char *string;
# ifndef HAS_GETPEERUCRED
# define zoneid_t int
# endif
# include "../dix/Xserver-dtrace.h"
#endif
static int lastfdesc;
fd_set WellKnownConnections;
fd_set EnabledDevices;
fd_set AllSockets;
fd_set AllClients;
fd_set LastSelectMask;
fd_set ClientsWithInput;
fd_set ClientsWriteBlocked;
fd_set OutputPending;
int MaxClients = 0;
Bool NewOutputPending;
Bool AnyClientsWriteBlocked;
static Bool RunFromSmartParent;
Bool RunFromSigStopParent;
Bool PartialNetwork;
static Pid_t ParentProcess;
static Bool debug_conns = FALSE;
fd_set IgnoredClientsWithInput;
static fd_set GrabImperviousClients;
static fd_set SavedAllClients;
static fd_set SavedAllSockets;
static fd_set SavedClientsWithInput;
int GrabInProgress = 0;
#if !defined(WIN32)
int *ConnectionTranslation = NULL;
#else
#undef MAXSOCKS
#define MAXSOCKS 500
#undef MAXSELECT
#define MAXSELECT 500
struct _ct_node {
struct _ct_node *next;
int key;
int value;
};
struct _ct_node *ct_head[256];
void InitConnectionTranslation(void)
{
memset(ct_head, 0, sizeof(ct_head));
}
int GetConnectionTranslation(int conn)
{
struct _ct_node *node = ct_head[conn & 0xff];
while (node != NULL)
{
if (node->key == conn)
return node->value;
node = node->next;
}
return 0;
}
void SetConnectionTranslation(int conn, int client)
{
struct _ct_node **node = ct_head + (conn & 0xff);
if (client == 0)
{
while (*node != NULL)
{
if ((*node)->key == conn)
{
struct _ct_node *temp = *node;
*node = (*node)->next;
free(temp);
return;
}
node = &((*node)->next);
}
return;
} else
{
while (*node != NULL)
{
if ((*node)->key == conn)
{
(*node)->value = client;
return;
}
node = &((*node)->next);
}
*node = malloc(sizeof(struct _ct_node));
(*node)->next = NULL;
(*node)->key = conn;
(*node)->value = client;
return;
}
}
void ClearConnectionTranslation(void)
{
unsigned i;
for (i = 0; i < 256; i++)
{
struct _ct_node *node = ct_head[i];
while (node != NULL)
{
struct _ct_node *temp = node;
node = node->next;
free(temp);
}
}
}
#endif
static XtransConnInfo *ListenTransConns = NULL;
static int *ListenTransFds = NULL;
static int ListenTransCount;
static void ErrorConnMax(XtransConnInfo );
static XtransConnInfo
lookup_trans_conn (int fd)
{
if (ListenTransFds)
{
int i;
for (i = 0; i < ListenTransCount; i++)
if (ListenTransFds[i] == fd)
return ListenTransConns[i];
}
return NULL;
}
void
InitConnectionLimits(void)
{
lastfdesc = -1;
#ifndef __CYGWIN__
#if !defined(XNO_SYSCONF) && defined(_SC_OPEN_MAX)
lastfdesc = sysconf(_SC_OPEN_MAX) - 1;
#endif
#ifdef HAS_GETDTABLESIZE
if (lastfdesc < 0)
lastfdesc = getdtablesize() - 1;
#endif
#ifdef _NFILE
if (lastfdesc < 0)
lastfdesc = _NFILE - 1;
#endif
#endif
if (lastfdesc < 0)
lastfdesc = MAXSOCKS;
if (lastfdesc > MAXSELECT)
lastfdesc = MAXSELECT;
if (lastfdesc > MAXCLIENTS)
{
lastfdesc = MAXCLIENTS;
if (debug_conns)
ErrorF( "REACHED MAXIMUM CLIENTS LIMIT %d\n", MAXCLIENTS);
}
MaxClients = lastfdesc;
#ifdef DEBUG
ErrorF("InitConnectionLimits: MaxClients = %d\n", MaxClients);
#endif
#if !defined(WIN32)
if (!ConnectionTranslation)
ConnectionTranslation = (int *)xnfalloc(sizeof(int)*(lastfdesc + 1));
#else
InitConnectionTranslation();
#endif
}
static void
InitParentProcess(void)
{
#if !defined(WIN32)
OsSigHandlerPtr handler;
handler = OsSignal (SIGUSR1, SIG_IGN);
if ( handler == SIG_IGN)
RunFromSmartParent = TRUE;
OsSignal(SIGUSR1, handler);
ParentProcess = getppid ();
#endif
}
void
NotifyParentProcess(void)
{
#if !defined(WIN32)
if (RunFromSmartParent) {
if (ParentProcess > 1) {
kill (ParentProcess, SIGUSR1);
}
}
if (RunFromSigStopParent)
raise (SIGSTOP);
#endif
}
void
CreateWellKnownSockets(void)
{
int i;
int partial;
char port[20];
FD_ZERO(&AllSockets);
FD_ZERO(&AllClients);
FD_ZERO(&LastSelectMask);
FD_ZERO(&ClientsWithInput);
#if !defined(WIN32)
for (i=0; i<MaxClients; i++) ConnectionTranslation[i] = 0;
#else
ClearConnectionTranslation();
#endif
FD_ZERO (&WellKnownConnections);
sprintf (port, "%d", atoi (display));
if ((_XSERVTransMakeAllCOTSServerListeners (port, &partial,
&ListenTransCount, &ListenTransConns) >= 0) &&
(ListenTransCount >= 1))
{
if (!PartialNetwork && partial)
{
FatalError ("Failed to establish all listening sockets");
}
else
{
ListenTransFds = malloc(ListenTransCount * sizeof (int));
for (i = 0; i < ListenTransCount; i++)
{
int fd = _XSERVTransGetConnectionNumber (ListenTransConns[i]);
ListenTransFds[i] = fd;
FD_SET (fd, &WellKnownConnections);
if (!_XSERVTransIsLocal (ListenTransConns[i]))
{
DefineSelf (fd);
}
}
}
}
if (!XFD_ANYSET (&WellKnownConnections))
FatalError ("Cannot establish any listening sockets - Make sure an X server isn't already running");
#if !defined(WIN32)
OsSignal (SIGPIPE, SIG_IGN);
OsSignal (SIGHUP, AutoResetServer);
#endif
OsSignal (SIGINT, GiveUp);
OsSignal (SIGTERM, GiveUp);
XFD_COPYSET (&WellKnownConnections, &AllSockets);
ResetHosts(display);
InitParentProcess();
#ifdef XDMCP
XdmcpInit ();
#endif
}
void
ResetWellKnownSockets (void)
{
int i;
ResetOsBuffers();
for (i = 0; i < ListenTransCount; i++)
{
int status = _XSERVTransResetListener (ListenTransConns[i]);
if (status != TRANS_RESET_NOOP)
{
if (status == TRANS_RESET_FAILURE)
{
FD_CLR (ListenTransFds[i], &WellKnownConnections);
ListenTransFds[i] = ListenTransFds[ListenTransCount - 1];
ListenTransConns[i] = ListenTransConns[ListenTransCount - 1];
ListenTransCount -= 1;
i -= 1;
}
else if (status == TRANS_RESET_NEW_FD)
{
int newfd = _XSERVTransGetConnectionNumber (ListenTransConns[i]);
FD_CLR (ListenTransFds[i], &WellKnownConnections);
ListenTransFds[i] = newfd;
FD_SET(newfd, &WellKnownConnections);
}
}
}
ResetAuthorization ();
ResetHosts(display);
#ifdef XDMCP
XdmcpReset ();
#endif
}
void
CloseWellKnownConnections(void)
{
int i;
for (i = 0; i < ListenTransCount; i++)
_XSERVTransClose (ListenTransConns[i]);
}
static void
AuthAudit (ClientPtr client, Bool letin,
struct sockaddr *saddr, int len,
unsigned int proto_n, char *auth_proto, int auth_id)
{
char addr[128];
char *out = addr;
char client_uid_string[64];
LocalClientCredRec *lcc;
#ifdef XSERVER_DTRACE
pid_t client_pid = -1;
zoneid_t client_zid = -1;
#endif
if (!len)
strcpy(out, "local host");
else
switch (saddr->sa_family)
{
case AF_UNSPEC:
#if defined(UNIXCONN) || defined(LOCALCONN)
case AF_UNIX:
#endif
strcpy(out, "local host");
break;
#if defined(TCPCONN) || defined(STREAMSCONN)
case AF_INET:
sprintf(out, "IP %s",
inet_ntoa(((struct sockaddr_in *) saddr)->sin_addr));
break;
#if defined(IPv6) && defined(AF_INET6)
case AF_INET6: {
char ipaddr[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &((struct sockaddr_in6 *) saddr)->sin6_addr,
ipaddr, sizeof(ipaddr));
sprintf(out, "IP %s", ipaddr);
}
break;
#endif
#endif
default:
strcpy(out, "unknown address");
}
if (GetLocalClientCreds(client, &lcc) != -1) {
int slen;
strcpy(client_uid_string, " ( ");
slen = 3;
if (lcc->fieldsSet & LCC_UID_SET) {
snprintf(client_uid_string + slen,
sizeof(client_uid_string) - slen,
"uid=%ld ", (long) lcc->euid);
slen = strlen(client_uid_string);
}
if (lcc->fieldsSet & LCC_GID_SET) {
snprintf(client_uid_string + slen,
sizeof(client_uid_string) - slen,
"gid=%ld ", (long) lcc->egid);
slen = strlen(client_uid_string);
}
if (lcc->fieldsSet & LCC_PID_SET) {
#ifdef XSERVER_DTRACE
client_pid = lcc->pid;
#endif
snprintf(client_uid_string + slen,
sizeof(client_uid_string) - slen,
"pid=%ld ", (long) lcc->pid);
slen = strlen(client_uid_string);
}
if (lcc->fieldsSet & LCC_ZID_SET) {
#ifdef XSERVER_DTRACE
client_zid = lcc->zoneid;
#endif
snprintf(client_uid_string + slen,
sizeof(client_uid_string) - slen,
"zoneid=%ld ", (long) lcc->zoneid);
slen = strlen(client_uid_string);
}
snprintf(client_uid_string + slen, sizeof(client_uid_string) - slen,
")");
FreeLocalClientCreds(lcc);
}
else {
client_uid_string[0] = '\0';
}
#ifdef XSERVER_DTRACE
XSERVER_CLIENT_AUTH(client->index, addr, client_pid, client_zid);
#endif
if (auditTrailLevel > 1) {
if (proto_n)
AuditF("client %d %s from %s%s\n Auth name: %.*s ID: %d\n",
client->index, letin ? "connected" : "rejected", addr,
client_uid_string, (int)proto_n, auth_proto, auth_id);
else
AuditF("client %d %s from %s%s\n",
client->index, letin ? "connected" : "rejected", addr,
client_uid_string);
}
}
XID
AuthorizationIDOfClient(ClientPtr client)
{
if (client->osPrivate)
return ((OsCommPtr)client->osPrivate)->auth_id;
else
return None;
}
char *
ClientAuthorized(ClientPtr client,
unsigned int proto_n, char *auth_proto,
unsigned int string_n, char *auth_string)
{
OsCommPtr priv;
Xtransaddr *from = NULL;
int family;
int fromlen;
XID auth_id;
char *reason = NULL;
XtransConnInfo trans_conn;
priv = (OsCommPtr)client->osPrivate;
trans_conn = priv->trans_conn;
if(trans_conn->flags & TRANS_NOXAUTH) {
auth_id = (XID) 0L;
} else {
auth_id = CheckAuthorization (proto_n, auth_proto, string_n, auth_string, client, &reason);
}
if (auth_id == (XID) ~0L)
{
if (_XSERVTransGetPeerAddr(trans_conn, &family, &fromlen, &from) != -1)
{
if (InvalidHost ((struct sockaddr *) from, fromlen, client))
AuthAudit(client, FALSE, (struct sockaddr *) from,
fromlen, proto_n, auth_proto, auth_id);
else
{
auth_id = (XID) 0;
#ifdef XSERVER_DTRACE
if ((auditTrailLevel > 1) || XSERVER_CLIENT_AUTH_ENABLED())
#else
if (auditTrailLevel > 1)
#endif
AuthAudit(client, TRUE,
(struct sockaddr *) from, fromlen,
proto_n, auth_proto, auth_id);
}
free(from);
}
if (auth_id == (XID) ~0L) {
if (reason)
return reason;
else
return "Client is not authorized to connect to Server";
}
}
#ifdef XSERVER_DTRACE
else if ((auditTrailLevel > 1) || XSERVER_CLIENT_AUTH_ENABLED())
#else
else if (auditTrailLevel > 1)
#endif
{
if (_XSERVTransGetPeerAddr (trans_conn,
&family, &fromlen, &from) != -1)
{
AuthAudit(client, TRUE, (struct sockaddr *) from, fromlen,
proto_n, auth_proto, auth_id);
free(from);
}
}
priv->auth_id = auth_id;
priv->conn_time = 0;
#ifdef XDMCP
XdmcpOpenDisplay(priv->fd);
#endif
XaceHook(XACE_AUTH_AVAIL, client, auth_id);
return((char *)NULL);
}
static ClientPtr
AllocNewConnection (XtransConnInfo trans_conn, int fd, CARD32 conn_time)
{
OsCommPtr oc;
ClientPtr client;
if (
#ifndef WIN32
fd >= lastfdesc
#else
XFD_SETCOUNT(&AllClients) >= MaxClients
#endif
)
return NullClient;
oc = malloc(sizeof(OsCommRec));
if (!oc)
return NullClient;
oc->trans_conn = trans_conn;
oc->fd = fd;
oc->input = (ConnectionInputPtr)NULL;
oc->output = (ConnectionOutputPtr)NULL;
oc->auth_id = None;
oc->conn_time = conn_time;
if (!(client = NextAvailableClient((pointer)oc)))
{
free(oc);
return NullClient;
}
oc->local_client = ComputeLocalClient(client);
#if !defined(WIN32)
ConnectionTranslation[fd] = client->index;
#else
SetConnectionTranslation(fd, client->index);
#endif
if (GrabInProgress)
{
FD_SET(fd, &SavedAllClients);
FD_SET(fd, &SavedAllSockets);
}
else
{
FD_SET(fd, &AllClients);
FD_SET(fd, &AllSockets);
}
#ifdef DEBUG
ErrorF("AllocNewConnection: client index = %d, socket fd = %d\n",
client->index, fd);
#endif
#ifdef XSERVER_DTRACE
XSERVER_CLIENT_CONNECT(client->index, fd);
#endif
return client;
}
Bool
EstablishNewConnections(ClientPtr clientUnused, pointer closure)
{
fd_set readyconnections;
int curconn;
register int newconn;
CARD32 connect_time;
register int i;
register ClientPtr client;
register OsCommPtr oc;
fd_set tmask;
XFD_ANDSET (&tmask, (fd_set*)closure, &WellKnownConnections);
XFD_COPYSET(&tmask, &readyconnections);
if (!XFD_ANYSET(&readyconnections))
return TRUE;
connect_time = GetTimeInMillis();
for (i=1; i<currentMaxClients; i++)
{
if ((client = clients[i]))
{
oc = (OsCommPtr)(client->osPrivate);
if ((oc && (oc->conn_time != 0) &&
(connect_time - oc->conn_time) >= TimeOutValue) ||
(client->noClientException != Success && !client->clientGone))
CloseDownClient(client);
}
}
#ifndef WIN32
for (i = 0; i < howmany(XFD_SETSIZE, NFDBITS); i++)
{
while (readyconnections.fds_bits[i])
#else
for (i = 0; i < XFD_SETCOUNT(&readyconnections); i++)
#endif
{
XtransConnInfo trans_conn, new_trans_conn;
int status;
#ifndef WIN32
curconn = mffs (readyconnections.fds_bits[i]) - 1;
readyconnections.fds_bits[i] &= ~((fd_mask)1 << curconn);
curconn += (i * (sizeof(fd_mask)*8));
#else
curconn = XFD_FD(&readyconnections, i);
#endif
if ((trans_conn = lookup_trans_conn (curconn)) == NULL)
continue;
if ((new_trans_conn = _XSERVTransAccept (trans_conn, &status)) == NULL)
continue;
newconn = _XSERVTransGetConnectionNumber (new_trans_conn);
if (newconn < lastfdesc)
{
int clientid;
#if !defined(WIN32)
clientid = ConnectionTranslation[newconn];
#else
clientid = GetConnectionTranslation(newconn);
#endif
if(clientid && (client = clients[clientid]))
CloseDownClient(client);
}
_XSERVTransSetOption(new_trans_conn, TRANS_NONBLOCKING, 1);
if (!AllocNewConnection (new_trans_conn, newconn, connect_time))
{
ErrorConnMax(new_trans_conn);
_XSERVTransClose(new_trans_conn);
}
if(trans_conn->flags & TRANS_NOXAUTH)
new_trans_conn->flags = new_trans_conn->flags | TRANS_NOXAUTH;
}
#ifndef WIN32
}
#endif
return TRUE;
}
#define NOROOM "Maximum number of clients reached"
static void
ErrorConnMax(XtransConnInfo trans_conn)
{
int fd = _XSERVTransGetConnectionNumber (trans_conn);
xConnSetupPrefix csp;
char pad[3];
struct iovec iov[3];
char byteOrder = 0;
int whichbyte = 1;
struct timeval waittime;
fd_set mask;
waittime.tv_sec = BOTIMEOUT / MILLI_PER_SECOND;
waittime.tv_usec = (BOTIMEOUT % MILLI_PER_SECOND) *
(1000000 / MILLI_PER_SECOND);
FD_ZERO(&mask);
FD_SET(fd, &mask);
(void)Select(fd + 1, &mask, NULL, NULL, &waittime);
(void)_XSERVTransRead(trans_conn, &byteOrder, 1);
if ((byteOrder == 'l') || (byteOrder == 'B'))
{
csp.success = xFalse;
csp.lengthReason = sizeof(NOROOM) - 1;
csp.length = (sizeof(NOROOM) + 2) >> 2;
csp.majorVersion = X_PROTOCOL;
csp.minorVersion = X_PROTOCOL_REVISION;
if (((*(char *) &whichbyte) && (byteOrder == 'B')) ||
(!(*(char *) &whichbyte) && (byteOrder == 'l')))
{
swaps(&csp.majorVersion, whichbyte);
swaps(&csp.minorVersion, whichbyte);
swaps(&csp.length, whichbyte);
}
iov[0].iov_len = sz_xConnSetupPrefix;
iov[0].iov_base = (char *) &csp;
iov[1].iov_len = csp.lengthReason;
iov[1].iov_base = NOROOM;
iov[2].iov_len = (4 - (csp.lengthReason & 3)) & 3;
iov[2].iov_base = pad;
(void)_XSERVTransWritev(trans_conn, iov, 3);
}
}
static void
CloseDownFileDescriptor(OsCommPtr oc)
{
int connection = oc->fd;
if (oc->trans_conn) {
_XSERVTransDisconnect(oc->trans_conn);
_XSERVTransClose(oc->trans_conn);
}
#ifndef WIN32
ConnectionTranslation[connection] = 0;
#else
SetConnectionTranslation(connection, 0);
#endif
FD_CLR(connection, &AllSockets);
FD_CLR(connection, &AllClients);
FD_CLR(connection, &ClientsWithInput);
FD_CLR(connection, &GrabImperviousClients);
if (GrabInProgress)
{
FD_CLR(connection, &SavedAllSockets);
FD_CLR(connection, &SavedAllClients);
FD_CLR(connection, &SavedClientsWithInput);
}
FD_CLR(connection, &ClientsWriteBlocked);
if (!XFD_ANYSET(&ClientsWriteBlocked))
AnyClientsWriteBlocked = FALSE;
FD_CLR(connection, &OutputPending);
}
void
CheckConnections(void)
{
#ifndef WIN32
fd_mask mask;
#endif
fd_set tmask;
int curclient, curoff;
int i;
struct timeval notime;
int r;
#ifdef WIN32
fd_set savedAllClients;
#endif
notime.tv_sec = 0;
notime.tv_usec = 0;
#ifndef WIN32
for (i=0; i<howmany(XFD_SETSIZE, NFDBITS); i++)
{
mask = AllClients.fds_bits[i];
while (mask)
{
curoff = mffs (mask) - 1;
curclient = curoff + (i * (sizeof(fd_mask)*8));
FD_ZERO(&tmask);
FD_SET(curclient, &tmask);
do {
r = Select (curclient + 1, &tmask, NULL, NULL, ¬ime);
} while (r < 0 && (errno == EINTR || errno == EAGAIN));
if (r < 0)
if (ConnectionTranslation[curclient] > 0)
CloseDownClient(clients[ConnectionTranslation[curclient]]);
mask &= ~((fd_mask)1 << curoff);
}
}
#else
XFD_COPYSET(&AllClients, &savedAllClients);
for (i = 0; i < XFD_SETCOUNT(&savedAllClients); i++)
{
curclient = XFD_FD(&savedAllClients, i);
FD_ZERO(&tmask);
FD_SET(curclient, &tmask);
do {
r = Select (curclient + 1, &tmask, NULL, NULL, ¬ime);
} while (r < 0 && (errno == EINTR || errno == EAGAIN));
if (r < 0)
if (GetConnectionTranslation(curclient) > 0)
CloseDownClient(clients[GetConnectionTranslation(curclient)]);
}
#endif
}
void
CloseDownConnection(ClientPtr client)
{
OsCommPtr oc = (OsCommPtr)client->osPrivate;
if (FlushCallback)
CallCallbacks(&FlushCallback, NULL);
if (oc->output && oc->output->count)
FlushClient(client, oc, (char *)NULL, 0);
#ifdef XDMCP
XdmcpCloseDisplay(oc->fd);
#endif
CloseDownFileDescriptor(oc);
FreeOsBuffers(oc);
free(client->osPrivate);
client->osPrivate = (pointer)NULL;
if (auditTrailLevel > 1)
AuditF("client %d disconnected\n", client->index);
}
void
AddGeneralSocket(int fd)
{
FD_SET(fd, &AllSockets);
if (GrabInProgress)
FD_SET(fd, &SavedAllSockets);
}
void
AddEnabledDevice(int fd)
{
FD_SET(fd, &EnabledDevices);
AddGeneralSocket(fd);
}
void
RemoveGeneralSocket(int fd)
{
FD_CLR(fd, &AllSockets);
if (GrabInProgress)
FD_CLR(fd, &SavedAllSockets);
}
void
RemoveEnabledDevice(int fd)
{
FD_CLR(fd, &EnabledDevices);
RemoveGeneralSocket(fd);
}
int
OnlyListenToOneClient(ClientPtr client)
{
OsCommPtr oc = (OsCommPtr)client->osPrivate;
int rc, connection = oc->fd;
rc = XaceHook(XACE_SERVER_ACCESS, client, DixGrabAccess);
if (rc != Success)
return rc;
if (! GrabInProgress)
{
XFD_COPYSET(&ClientsWithInput, &SavedClientsWithInput);
XFD_ANDSET(&ClientsWithInput,
&ClientsWithInput, &GrabImperviousClients);
if (FD_ISSET(connection, &SavedClientsWithInput))
{
FD_CLR(connection, &SavedClientsWithInput);
FD_SET(connection, &ClientsWithInput);
}
XFD_UNSET(&SavedClientsWithInput, &GrabImperviousClients);
XFD_COPYSET(&AllSockets, &SavedAllSockets);
XFD_COPYSET(&AllClients, &SavedAllClients);
XFD_UNSET(&AllSockets, &AllClients);
XFD_ANDSET(&AllClients, &AllClients, &GrabImperviousClients);
FD_SET(connection, &AllClients);
XFD_ORSET(&AllSockets, &AllSockets, &AllClients);
GrabInProgress = client->index;
}
return rc;
}
void
ListenToAllClients(void)
{
if (GrabInProgress)
{
XFD_ORSET(&AllSockets, &AllSockets, &SavedAllSockets);
XFD_ORSET(&AllClients, &AllClients, &SavedAllClients);
XFD_ORSET(&ClientsWithInput, &ClientsWithInput, &SavedClientsWithInput);
GrabInProgress = 0;
}
}
void
IgnoreClient (ClientPtr client)
{
OsCommPtr oc = (OsCommPtr)client->osPrivate;
int connection = oc->fd;
client->ignoreCount++;
if (client->ignoreCount > 1)
return;
isItTimeToYield = TRUE;
if (!GrabInProgress || FD_ISSET(connection, &AllClients))
{
if (FD_ISSET (connection, &ClientsWithInput))
FD_SET(connection, &IgnoredClientsWithInput);
else
FD_CLR(connection, &IgnoredClientsWithInput);
FD_CLR(connection, &ClientsWithInput);
FD_CLR(connection, &AllSockets);
FD_CLR(connection, &AllClients);
FD_CLR(connection, &LastSelectMask);
}
else
{
if (FD_ISSET (connection, &SavedClientsWithInput))
FD_SET(connection, &IgnoredClientsWithInput);
else
FD_CLR(connection, &IgnoredClientsWithInput);
FD_CLR(connection, &SavedClientsWithInput);
FD_CLR(connection, &SavedAllSockets);
FD_CLR(connection, &SavedAllClients);
}
}
void
AttendClient (ClientPtr client)
{
OsCommPtr oc = (OsCommPtr)client->osPrivate;
int connection = oc->fd;
client->ignoreCount--;
if (client->ignoreCount)
return;
if (!GrabInProgress || GrabInProgress == client->index ||
FD_ISSET(connection, &GrabImperviousClients))
{
FD_SET(connection, &AllClients);
FD_SET(connection, &AllSockets);
FD_SET(connection, &LastSelectMask);
if (FD_ISSET (connection, &IgnoredClientsWithInput))
FD_SET(connection, &ClientsWithInput);
}
else
{
FD_SET(connection, &SavedAllClients);
FD_SET(connection, &SavedAllSockets);
if (FD_ISSET(connection, &IgnoredClientsWithInput))
FD_SET(connection, &SavedClientsWithInput);
}
}
void
MakeClientGrabImpervious(ClientPtr client)
{
OsCommPtr oc = (OsCommPtr)client->osPrivate;
int connection = oc->fd;
FD_SET(connection, &GrabImperviousClients);
if (ServerGrabCallback)
{
ServerGrabInfoRec grabinfo;
grabinfo.client = client;
grabinfo.grabstate = CLIENT_IMPERVIOUS;
CallCallbacks(&ServerGrabCallback, &grabinfo);
}
}
void
MakeClientGrabPervious(ClientPtr client)
{
OsCommPtr oc = (OsCommPtr)client->osPrivate;
int connection = oc->fd;
FD_CLR(connection, &GrabImperviousClients);
if (GrabInProgress && (GrabInProgress != client->index))
{
if (FD_ISSET(connection, &ClientsWithInput))
{
FD_SET(connection, &SavedClientsWithInput);
FD_CLR(connection, &ClientsWithInput);
}
FD_CLR(connection, &AllSockets);
FD_CLR(connection, &AllClients);
isItTimeToYield = TRUE;
}
if (ServerGrabCallback)
{
ServerGrabInfoRec grabinfo;
grabinfo.client = client;
grabinfo.grabstate = CLIENT_PERVIOUS;
CallCallbacks(&ServerGrabCallback, &grabinfo);
}
}
#ifdef XQUARTZ
void ListenOnOpenFD(int fd, int noxauth) {
char port[256];
XtransConnInfo ciptr;
const char *display_env = getenv("DISPLAY");
if(display_env && (strncmp(display_env, "/tmp/launch", 11) == 0)) {
strcpy(port, display_env);
} else {
sprintf(port, ":%d", atoi(display));
}
ciptr = _XSERVTransReopenCOTSServer(5, fd, port);
if(ciptr == NULL) {
ErrorF("Got NULL while trying to Reopen launchd port.\n");
return;
}
if(noxauth)
ciptr->flags = ciptr->flags | TRANS_NOXAUTH;
ListenTransFds = (int *) realloc(ListenTransFds, (ListenTransCount + 1) * sizeof (int));
ListenTransConns = (XtransConnInfo *) realloc(ListenTransConns, (ListenTransCount + 1) * sizeof (XtransConnInfo));
ListenTransConns[ListenTransCount] = ciptr;
ListenTransFds[ListenTransCount] = fd;
FD_SET(fd, &WellKnownConnections);
FD_SET(fd, &AllSockets);
ListenTransCount++;
ResetAuthorization();
ResetHosts(display);
#ifdef XDMCP
XdmcpReset();
#endif
}
#endif