aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/programs/Xserver/os
diff options
context:
space:
mode:
Diffstat (limited to 'nx-X11/programs/Xserver/os')
-rw-r--r--nx-X11/programs/Xserver/os/Imakefile262
-rw-r--r--nx-X11/programs/Xserver/os/WaitFor.c829
-rw-r--r--nx-X11/programs/Xserver/os/access.c2285
-rw-r--r--nx-X11/programs/Xserver/os/auth.c602
-rw-r--r--nx-X11/programs/Xserver/os/client.c397
-rw-r--r--nx-X11/programs/Xserver/os/connection.c1377
-rw-r--r--nx-X11/programs/Xserver/os/io.c1293
-rw-r--r--nx-X11/programs/Xserver/os/log.c779
-rw-r--r--nx-X11/programs/Xserver/os/mitauth.c197
-rw-r--r--nx-X11/programs/Xserver/os/oscolor.c1661
-rw-r--r--nx-X11/programs/Xserver/os/osdep.h313
-rw-r--r--nx-X11/programs/Xserver/os/osinit.c234
-rw-r--r--nx-X11/programs/Xserver/os/reallocarray.c43
-rw-r--r--nx-X11/programs/Xserver/os/rpcauth.c201
-rw-r--r--nx-X11/programs/Xserver/os/secauth.c203
-rw-r--r--nx-X11/programs/Xserver/os/strlcat.c57
-rw-r--r--nx-X11/programs/Xserver/os/strlcpy.c53
-rw-r--r--nx-X11/programs/Xserver/os/timingsafe_memcmp.c47
-rw-r--r--nx-X11/programs/Xserver/os/utils.c2260
-rw-r--r--nx-X11/programs/Xserver/os/xdmauth.c501
-rw-r--r--nx-X11/programs/Xserver/os/xdmcp.c1629
-rw-r--r--nx-X11/programs/Xserver/os/xprintf.c163
-rw-r--r--nx-X11/programs/Xserver/os/xstrans.c17
23 files changed, 15403 insertions, 0 deletions
diff --git a/nx-X11/programs/Xserver/os/Imakefile b/nx-X11/programs/Xserver/os/Imakefile
new file mode 100644
index 000000000..7932e32cd
--- /dev/null
+++ b/nx-X11/programs/Xserver/os/Imakefile
@@ -0,0 +1,262 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* nx-X11, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include <Server.tmpl>
+
+NULL =
+
+/*
+ * If you have any extra files to be put into the library, define them here.
+ */
+
+ZONEID_DEFINES = -UHAVE_GETZONEID
+
+#if NXLibraries
+
+NX_INCLUDES = -I../../../../nxcomp
+
+NX_DEFINES = -DNX_TRANS_SOCKET \
+ -DNX_TRANS_AUTH \
+ -DNX_TRANS_FOPEN \
+ -DNX_TRANS_SLEEP \
+ -DNX_TRANS_EXIT \
+ -DNX_TRANS_WAKEUP=1000 \
+ -DNXAGENT_SERVER \
+ $(NULL)
+
+# -DNX_TRANS_WARN \
+# -DNX_TRANS_INFO \
+# -DNX_TRANS_TEST \
+# -DNX_TRANS_DEBUG \
+
+#endif
+
+/*
+ * do not modify the following two definitions
+ */
+
+#ifndef OtherSources
+#define OtherSources
+#endif
+
+#ifndef OtherObjects
+#define OtherObjects
+#endif
+
+#if HasXdmAuth
+XDMAUTHDEFS = -DHASXDMAUTH
+XDMAUTHOBJS = xdmauth.o
+XDMAUTHSRCS = xdmauth.c
+#else
+XDMAUTHDEFS =
+XDMAUTHOBJS =
+XDMAUTHSCRS =
+#endif
+
+#if HasSecureRPC
+RPCDEFS = -DSECURE_RPC
+RPCOBJS = rpcauth.o
+RPCSRCS = rpcauth.c
+#else
+RPCDEFS =
+RPCOBJS =
+RPCSRCS =
+#endif
+
+#if HasBSD44Sockets
+ SOCK_DEFINES = -DBSD44SOCKETS
+#endif
+
+#if HasGetIfAddrs
+ IFADDRS_DEFINES = -DHAS_GETIFADDRS
+#endif
+
+#if !defined(DDXOsColor)
+COLOR_SRCS=oscolor.c
+COLOR_OBJS=oscolor.o
+#endif
+
+#if !HasSnprintf
+SNPRINTF_SRCS = snprintf.c
+SNPRINTF_OBJS = snprintf.o
+#endif
+
+#if !HasStrlcat
+STRLCAT_SRCS = strlcat.c strlcpy.c
+STRLCAT_OBJS = strlcat.o strlcpy.o
+#endif
+
+#if !HasReallocarray
+REALLOCARRAY_SRCS = reallocarray.c
+REALLOCARRAY_OBJS = reallocarray.o
+#endif
+
+#if HasGetpeerucred
+GETPEER_DEFINES = -DHAS_GETPEERUCRED
+#else
+# if HasGetpeereid
+GETPEER_DEFINES = -DHAS_GETPEEREID
+# endif
+#endif
+
+#if !HasTimingsafeMemcmp
+TMEMCMP_SRCS = timingsafe_memcmp.c
+TMEMCMP_OBJS = timingsafe_memcmp.o
+#endif
+
+BOOTSTRAPCFLAGS =
+ SRCS = WaitFor.c \
+ access.c \
+ client.c \
+ connection.c \
+ io.c \
+ $(COLOR_SRCS) \
+ osinit.c \
+ utils.c \
+ log.c \
+ auth.c \
+ mitauth.c \
+ secauth.c \
+ $(XDMAUTHSRCS) \
+ $(RPCSRCS) \
+ xdmcp.c \
+ OtherSources \
+ xstrans.c \
+ $(SNPRINTF_SRCS) \
+ $(STRLCAT_SRCS) \
+ $(REALLOCARRAY_SRCS) \
+ xprintf.c \
+ $(TMEMCMP_SRCS) \
+ $(NULL)
+
+ OBJS = WaitFor.o \
+ access.o \
+ client.o \
+ connection.o \
+ io.o \
+ $(COLOR_OBJS) \
+ osinit.o \
+ utils.o \
+ log.o \
+ auth.o \
+ mitauth.o \
+ secauth.o \
+ $(XDMAUTHOBJS) \
+ $(RPCOBJS) \
+ xdmcp.o \
+ OtherObjects \
+ xstrans.o \
+ $(SNPRINTF_OBJS) \
+ $(STRLCAT_OBJS) \
+ $(REALLOCARRAY_OBJS) \
+ xprintf.o \
+ $(TMEMCMP_OBJS) \
+ $(NULL)
+
+#if UseMemLeak
+ MEM_DEFINES = -DMEMBUG
+#endif
+ ADM_DEFINES = -DADMPATH=\"$(ADMDIR)/X\%smsgs\"
+ XDMCP_DEFINES = ServerXdmcpDefines
+ ERROR_DEFINES = ServerErrorDefines
+#if HasPam && HasPamMisc
+ PAM_DEFINES = -DUSE_PAM
+#endif
+ XTRANS_DEFINES = -DXTRANS_SEND_FDS=0
+
+ DEFINES = $(CONNECTION_FLAGS) \
+ $(MEM_DEFINES) \
+ $(XDMAUTHDEFS) \
+ $(RPCDEFS) \
+ $(SIGNAL_DEFINES) \
+ $(OS_DEFINES) \
+ $(GETPEER_DEFINES) \
+ $(RANDOM_DEFINES) \
+ $(BUGMSG) \
+ $(XTRANS_FAILDEFINES) \
+ $(XTRANS_DEFINES) \
+ $(NX_DEFINES) \
+ $(NULL)
+
+ INCLUDES = -I. \
+ -I../include \
+ -I$(XINCLUDESRC) \
+ -I$(EXTINCSRC) \
+ -I$(SERVERSRC)/Xext \
+ -I$(SERVERSRC)/render \
+ -I$(TOP)/lib/Xau \
+ $(NX_INCLUDES) \
+ `pkg-config --cflags-only-I pixman-1` \
+ $(NULL)
+
+ DEPEND_DEFINES = $(XDMCP_DEFINES) \
+ $(EXT_DEFINES) \
+ $(TRANS_INCLUDES) \
+ $(CONNECTION_FLAGS) \
+ $(GETPEER_DEFINES) \
+ DependDefines \
+ $(NULL)
+
+ LINTLIBS = ../dix/llib-ldix.ln
+
+#ifdef NEED_ALLOCA_FROM_LIBPW
+ PWLIB = /lib/libPW.a
+#endif /* NEED_ALLOCA_FROM_LIBPW */
+
+NormalLibraryObjectRule()
+NormalLibraryTarget(os,$(OBJS))
+LintLibraryTarget(os,$(SRCS))
+NormalLintTarget($(SRCS))
+
+#ifdef NEED_ALLOCA_FROM_LIBPW
+XCOMM
+XCOMM And this one is to get the version of alloca that lives in /lib/libPW.a
+XCOMM without getting all of the rest of the stuff in there.
+XCOMM
+alloca.o: $(PWLIB)
+ rm -f alloca.o
+ ar x $(PWLIB) alloca.o
+#endif /* NEED_ALLOCA_FROM_LIBPW */
+
+SpecialCObjectRule(access,$(ICONFIGFILES),$(XDMCP_DEFINES) $(SOCK_DEFINES) $(IFADDRS_DEFINES) $(ZONEID_DEFINES))
+SpecialCObjectRule(auth,$(ICONFIGFILES),$(XDMCP_DEFINES))
+SpecialCObjectRule(xdmauth,$(ICONFIGFILES),$(XDMCP_DEFINES))
+SpecialCObjectRule(xdmcp,$(ICONFIGFILES),$(SOCK_DEFINES) $(XDMCP_DEFINES))
+SpecialCObjectRule(connection,$(ICONFIGFILES),$(SOCK_DEFINES) $(XDMCP_DEFINES))
+SpecialCObjectRule(osinit,$(ICONFIGFILES),$(ADM_DEFINES))
+SpecialCObjectRule(WaitFor,$(ICONFIGFILES),$(EXT_DEFINES))
+SpecialCObjectRule(io,$(ICONFIGFILES),$(EXT_DEFINES))
+SpecialCObjectRule(utils,$(ICONFIGFILES),$(XDMCP_DEFINES) $(EXT_DEFINES) $(ERROR_DEFINES) $(PAM_DEFINES))
+#if defined(SparcArchitecture) && HasGcc && !HasGcc2
+oscolor.o: oscolor.c $(ICONFIGFILES)
+ $(RM) $@
+ cc -c $(CDEBUGFLAGS) $(ALLDEFINES) $*.c
+#endif
+
+#if !HasSnprintf
+LinkSourceFile(snprintf.c,$(LIBSRC)/misc)
+#endif
+
+DependTarget()
diff --git a/nx-X11/programs/Xserver/os/WaitFor.c b/nx-X11/programs/Xserver/os/WaitFor.c
new file mode 100644
index 000000000..76e5da5f2
--- /dev/null
+++ b/nx-X11/programs/Xserver/os/WaitFor.c
@@ -0,0 +1,829 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* nx-X11, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/***********************************************************
+
+Copyright 1987, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+
+/*****************************************************************
+ * OS Dependent input routines:
+ *
+ * WaitForSomething
+ * TimerForce, TimerSet, TimerCheck, TimerFree
+ *
+ *****************************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifdef WIN32
+#include <nx-X11/Xwinsock.h>
+#endif
+#include <nx-X11/Xos.h> /* for strings, fcntl, time */
+#include <errno.h>
+#include <stdio.h>
+#include <nx-X11/X.h>
+#include "misc.h"
+
+#include "osdep.h"
+#include <nx-X11/Xpoll.h>
+#include "dixstruct.h"
+#include "opaque.h"
+#ifdef DPMSExtension
+#include "dpmsproc.h"
+#endif
+
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_WAKEUP)
+
+static unsigned long startTimeInMillis;
+
+#endif
+
+#ifdef WIN32
+/* Error codes from windows sockets differ from fileio error codes */
+#undef EINTR
+#define EINTR WSAEINTR
+#undef EINVAL
+#define EINVAL WSAEINVAL
+#undef EBADF
+#define EBADF WSAENOTSOCK
+/* Windows select does not set errno. Use GetErrno as wrapper for
+ WSAGetLastError */
+#define GetErrno WSAGetLastError
+#else
+/* This is just a fallback to errno to hide the differences between unix and
+ Windows in the code */
+#define GetErrno() errno
+#endif
+
+/* modifications by raphael */
+int
+mffs(fd_mask mask)
+{
+ int i;
+
+ if (!mask) return 0;
+ i = 1;
+ while (!(mask & 1))
+ {
+ i++;
+ mask >>= 1;
+ }
+ return i;
+}
+
+#ifdef DPMSExtension
+#define DPMS_SERVER
+#include <nx-X11/extensions/dpms.h>
+#endif
+
+#ifdef XTESTEXT1
+/*
+ * defined in xtestext1dd.c
+ */
+extern int playback_on;
+#endif /* XTESTEXT1 */
+
+struct _OsTimerRec {
+ OsTimerPtr next;
+ CARD32 expires;
+ OsTimerCallback callback;
+ void * arg;
+};
+
+static void DoTimer(OsTimerPtr timer, CARD32 now, OsTimerPtr *prev);
+static OsTimerPtr timers = NULL;
+
+/*****************
+ * WaitForSomething:
+ * Make the server suspend until there is
+ * 1. data from clients or
+ * 2. input events available or
+ * 3. ddx notices something of interest (graphics
+ * queue ready, etc.) or
+ * 4. clients that have buffered replies/events are ready
+ *
+ * If the time between INPUT events is
+ * greater than ScreenSaverTime, the display is turned off (or
+ * saved, depending on the hardware). So, WaitForSomething()
+ * has to handle this also (that's why the select() has a timeout.
+ * For more info on ClientsWithInput, see ReadRequestFromClient().
+ * pClientsReady is an array to store ready client->index values into.
+ *****************/
+
+int
+WaitForSomething(int *pClientsReady)
+{
+ int i;
+ struct timeval waittime, *wt;
+ INT32 timeout = 0;
+ fd_set clientsReadable;
+ fd_set clientsWritable;
+ int curclient;
+ int selecterr;
+ int nready;
+ CARD32 now = 0;
+ Bool someReady = FALSE;
+ Bool someNotifyWriteReady = FALSE;
+
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+ fprintf(stderr, "WaitForSomething: Got called.\n");
+#endif
+
+ FD_ZERO(&clientsReadable);
+
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_WAKEUP)
+
+ startTimeInMillis = GetTimeInMillis();
+
+#endif
+
+ /* We need a while loop here to handle
+ crashed connections and the screen saver timeout */
+ while (1)
+ {
+ /* deal with any blocked jobs */
+ if (workQueue)
+ ProcessWorkQueue();
+ if (XFD_ANYSET (&ClientsWithInput))
+ {
+ someReady = TRUE;
+ waittime.tv_sec = 0;
+ waittime.tv_usec = 0;
+ wt = &waittime;
+ }
+ if (someReady)
+ {
+ XFD_COPYSET(&AllSockets, &LastSelectMask);
+ XFD_UNSET(&LastSelectMask, &ClientsWithInput);
+ }
+ else
+ {
+ wt = NULL;
+ if (timers)
+ {
+ now = GetTimeInMillis();
+ timeout = timers->expires - now;
+ if (timeout < 0)
+ timeout = 0;
+ waittime.tv_sec = timeout / MILLI_PER_SECOND;
+ waittime.tv_usec = (timeout % MILLI_PER_SECOND) *
+ (1000000 / MILLI_PER_SECOND);
+ wt = &waittime;
+ }
+ XFD_COPYSET(&AllSockets, &LastSelectMask);
+ }
+ SmartScheduleStopTimer ();
+
+ BlockHandler((void *)&wt, (void *)&LastSelectMask);
+ if (NewOutputPending)
+ FlushAllOutput();
+#ifdef XTESTEXT1
+ /* XXX how does this interact with new write block handling? */
+ if (playback_on) {
+ wt = &waittime;
+ XTestComputeWaitTime (&waittime);
+ }
+#endif /* XTESTEXT1 */
+
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_WAKEUP)
+
+ /*
+ * If caller has marked the first element of pClientsReady[],
+ * bail out of select after a short timeout. We need this to
+ * let the NX agent remove the splash screen when the timeout
+ * is expired. A better option would be to use the existing
+ * screen-saver timeout but it can be modified by clients, so
+ * we would need a special handling. This hack is trivial and
+ * keeps WaitForSomething() backward compatible with the exis-
+ * ting servers.
+ */
+
+ if (pClientsReady[0] == -1)
+ {
+ unsigned long timeoutInMillis;
+
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_WAKEUP) && defined(NX_TRANS_DEBUG)
+ fprintf(stderr, "WaitForSomething: pClientsReady[0] is [%d], pClientsReady[1] is [%d].\n",
+ pClientsReady[0], pClientsReady[1]);
+#endif
+
+ timeoutInMillis = GetTimeInMillis();
+
+ if (timeoutInMillis - startTimeInMillis >= NX_TRANS_WAKEUP)
+ {
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_WAKEUP) && defined(NX_TRANS_DEBUG)
+ fprintf(stderr, "WaitForSomething: Returning 0 because of wakeup timeout.\n");
+#endif
+ return 0;
+ }
+
+ timeoutInMillis = NX_TRANS_WAKEUP - (timeoutInMillis - startTimeInMillis);
+
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_WAKEUP) && defined(NX_TRANS_DEBUG)
+ fprintf(stderr, "WaitForSomething: Milliseconds to next wakeup are %ld.\n",
+ timeoutInMillis);
+#endif
+ if (wt == NULL || (wt -> tv_sec * MILLI_PER_SECOND +
+ wt -> tv_usec / MILLI_PER_SECOND) > timeoutInMillis)
+ {
+ if ((waittime.tv_sec * MILLI_PER_SECOND +
+ waittime.tv_usec / MILLI_PER_SECOND) > timeoutInMillis)
+ {
+ waittime.tv_sec = timeoutInMillis / MILLI_PER_SECOND;
+ waittime.tv_usec = (timeoutInMillis * MILLI_PER_SECOND) %
+ (MILLI_PER_SECOND * 1000);
+ wt = &waittime;
+ }
+
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_WAKEUP) && defined(NX_TRANS_DEBUG)
+ fprintf(stderr, "WaitForSomething: Next wakeup timeout set to %ld milliseconds.\n",
+ (waittime.tv_sec * MILLI_PER_SECOND) +
+ (waittime.tv_usec / MILLI_PER_SECOND));
+#endif
+ }
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_WAKEUP) && defined(NX_TRANS_DEBUG)
+ else
+ {
+ fprintf(stderr, "WaitForSomething: Using existing timeout of %ld milliseconds.\n",
+ (waittime.tv_sec * MILLI_PER_SECOND) +
+ (waittime.tv_usec / MILLI_PER_SECOND));
+ }
+#endif
+ }
+#endif
+
+ /* keep this check close to select() call to minimize race */
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+ if (dispatchException)
+ {
+ i = -1;
+
+ fprintf(stderr, "WaitForSomething: Value of dispatchException is true. Set i = -1.\n");
+ }
+#else
+ if (dispatchException)
+ i = -1;
+#endif
+ else if (AnyWritesPending)
+ {
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+ if (wt == NULL)
+ {
+ fprintf(stderr, "WaitForSomething: Executing select with LastSelectMask and "
+ "clientsWritable and null timeout.\n");
+ }
+ else
+ {
+ fprintf(stderr, "WaitForSomething: Executing select with LastSelectMask, "
+ "clientsWritable, %ld secs and %ld usecs.\n",
+ wt -> tv_sec, wt -> tv_usec);
+ }
+#endif
+ XFD_COPYSET(&ClientsWriteBlocked, &LastSelectWriteMask);
+ XFD_ORSET(&LastSelectWriteMask, &NotifyWriteFds, &LastSelectWriteMask);
+ i = Select(MaxClients, &LastSelectMask, &LastSelectWriteMask, NULL, wt);
+ }
+ else
+ {
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+ if (wt == NULL)
+ {
+ fprintf(stderr, "WaitForSomething: Executing select with LastSelectMask and null timeout.\n");
+ }
+ else
+ {
+ fprintf(stderr, "WaitForSomething: Executing select with LastSelectMask, %ld secs and %ld usecs.\n",
+ wt -> tv_sec, wt -> tv_usec);
+ }
+#endif
+ i = Select (MaxClients, &LastSelectMask, NULL, NULL, wt);
+ }
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+ fprintf(stderr, "WaitForSomething: Bailed out with i = [%d] and errno = [%d].\n", i, errno);
+
+ if (i < 0)
+ {
+ fprintf(stderr, "WaitForSomething: Error is [%s].\n", strerror(errno));
+ }
+#endif
+ selecterr = GetErrno();
+ WakeupHandler(i, (void *)&LastSelectMask);
+#ifdef XTESTEXT1
+ if (playback_on) {
+ i = XTestProcessInputAction (i, &waittime);
+ }
+#endif /* XTESTEXT1 */
+ SmartScheduleStartTimer ();
+
+ if (i <= 0) /* An error or timeout occurred */
+ {
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+ if (dispatchException)
+ {
+ fprintf(stderr, "WaitForSomething: Returning 0 because of (dispatchException).\n");
+ return 0;
+ }
+#else
+ if (dispatchException)
+ return 0;
+#endif
+ if (i < 0)
+ {
+ if (selecterr == EBADF) /* Some client disconnected */
+ {
+ CheckConnections ();
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+ if (! XFD_ANYSET (&AllClients))
+ {
+ fprintf(stderr, "WaitForSomething: Returning 0 because of (! XFD_ANYSET (&AllClients)).\n");
+ return 0;
+ }
+#else
+ if (! XFD_ANYSET (&AllClients))
+ return 0;
+#endif
+ }
+ else if (selecterr == EINVAL)
+ {
+ FatalError("WaitForSomething(): select: errno=%d\n",
+ selecterr);
+ }
+ else if (selecterr != EINTR)
+ {
+ ErrorF("WaitForSomething(): select: errno=%d\n",
+ selecterr);
+ }
+ }
+ else if (someReady)
+ {
+ /*
+ * If no-one else is home, bail quickly
+ */
+ XFD_COPYSET(&ClientsWithInput, &LastSelectMask);
+ XFD_COPYSET(&ClientsWithInput, &clientsReadable);
+ break;
+ }
+#if defined(NX_TRANS_SOCKET)
+ if (*checkForInput[0] != *checkForInput[1])
+ {
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+ fprintf(stderr, "WaitForSomething: Returning 0 because of (*checkForInput[0] != *checkForInput[1]).\n");
+#endif
+ return 0;
+ }
+#else
+ if (*checkForInput[0] != *checkForInput[1])
+ return 0;
+#endif
+
+ if (timers)
+ {
+ int expired = 0;
+ now = GetTimeInMillis();
+ if ((int) (timers->expires - now) <= 0)
+ expired = 1;
+
+ while (timers && (int) (timers->expires - now) <= 0)
+ DoTimer(timers, now, &timers);
+
+ if (expired)
+ return 0;
+ }
+ }
+ else
+ {
+ fd_set tmp_set;
+
+ if (*checkForInput[0] == *checkForInput[1]) {
+ if (timers)
+ {
+ int expired = 0;
+ now = GetTimeInMillis();
+ if ((int) (timers->expires - now) <= 0)
+ expired = 1;
+
+ while (timers && (int) (timers->expires - now) <= 0)
+ DoTimer(timers, now, &timers);
+
+ if (expired)
+ return 0;
+ }
+ }
+ if (someReady)
+ XFD_ORSET(&LastSelectMask, &ClientsWithInput, &LastSelectMask);
+ if (AnyWritesPending) {
+ XFD_ANDSET(&clientsWritable, &LastSelectWriteMask, &ClientsWriteBlocked);
+ if (XFD_ANYSET(&clientsWritable)) {
+ NewOutputPending = TRUE;
+ XFD_ORSET(&OutputPending, &clientsWritable, &OutputPending);
+ XFD_UNSET(&ClientsWriteBlocked, &clientsWritable);
+ if (!XFD_ANYSET(&ClientsWriteBlocked) && NumNotifyWriteFd == 0)
+ AnyWritesPending = FALSE;
+ }
+ if (NumNotifyWriteFd != 0) {
+ XFD_ANDSET(&tmp_set, &LastSelectWriteMask, &NotifyWriteFds);
+ if (XFD_ANYSET(&tmp_set))
+ someNotifyWriteReady = TRUE;
+ }
+ }
+
+ XFD_ANDSET(&clientsReadable, &LastSelectMask, &AllClients);
+
+ XFD_ANDSET(&tmp_set, &LastSelectMask, &NotifyReadFds);
+ if (XFD_ANYSET(&tmp_set) || someNotifyWriteReady)
+ HandleNotifyFds();
+
+ if (XFD_ANYSET (&clientsReadable))
+ break;
+#ifdef WIN32
+ /* Windows keyboard and mouse events are added to the input queue
+ in Block- and WakupHandlers. There is no device to check if
+ data is ready. So check here if new input is available */
+#if defined(NX_TRANS_SOCKET)
+ if (*checkForInput[0] != *checkForInput[1])
+ {
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+ fprintf(stderr, "WaitForSomething: Returning 0 because of (*checkForInput[0] != *checkForInput[1]).\n");
+#endif
+ return 0;
+ }
+#else
+ if (*checkForInput[0] != *checkForInput[1])
+ return 0;
+#endif
+#endif
+ }
+ }
+
+ nready = 0;
+ if (XFD_ANYSET (&clientsReadable))
+ {
+#ifndef WIN32
+ for (i=0; i<howmany(XFD_SETSIZE, NFDBITS); i++)
+ {
+ while (clientsReadable.fds_bits[i])
+ {
+ int client_index;
+
+ curclient = ffs (clientsReadable.fds_bits[i]) - 1;
+ client_index = /* raphael: modified */
+ ConnectionTranslation[curclient + (i * (sizeof(fd_mask) * 8))];
+#else
+ fd_set savedClientsReadable;
+ XFD_COPYSET(&clientsReadable, &savedClientsReadable);
+ for (i = 0; i < XFD_SETCOUNT(&savedClientsReadable); i++)
+ {
+ int client_priority, client_index;
+
+ curclient = XFD_FD(&savedClientsReadable, i);
+ client_index = GetConnectionTranslation(curclient);
+#endif
+ pClientsReady[nready++] = client_index;
+#ifndef WIN32
+ clientsReadable.fds_bits[i] &= ~(((fd_mask)1L) << curclient);
+ }
+#else
+ FD_CLR(curclient, &clientsReadable);
+#endif
+ }
+ }
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG)
+ fprintf(stderr, "WaitForSomething: Returning nready.\n");
+#endif
+ return nready;
+}
+
+#if 0
+/*
+ * This is not always a macro.
+ */
+ANYSET(FdMask *src)
+{
+ int i;
+
+ for (i=0; i<mskcnt; i++)
+ if (src[ i ])
+ return (TRUE);
+ return (FALSE);
+}
+#endif
+
+
+static void
+DoTimer(OsTimerPtr timer, CARD32 now, OsTimerPtr *prev)
+{
+ CARD32 newTime;
+
+ *prev = timer->next;
+ timer->next = NULL;
+ newTime = (*timer->callback)(timer, now, timer->arg);
+ if (newTime)
+ TimerSet(timer, 0, newTime, timer->callback, timer->arg);
+}
+
+OsTimerPtr
+TimerSet(OsTimerPtr timer, int flags, CARD32 millis,
+ OsTimerCallback func, void * arg)
+{
+ register OsTimerPtr *prev;
+ CARD32 now = GetTimeInMillis();
+
+ if (!timer)
+ {
+ timer = (OsTimerPtr)malloc(sizeof(struct _OsTimerRec));
+ if (!timer)
+ return NULL;
+ }
+ else
+ {
+ for (prev = &timers; *prev; prev = &(*prev)->next)
+ {
+ if (*prev == timer)
+ {
+ *prev = timer->next;
+ if (flags & TimerForceOld)
+ (void)(*timer->callback)(timer, now, timer->arg);
+ break;
+ }
+ }
+ }
+ if (!millis)
+ return timer;
+ if (!(flags & TimerAbsolute))
+ millis += now;
+ timer->expires = millis;
+ timer->callback = func;
+ timer->arg = arg;
+ if ((int) (millis - now) <= 0)
+ {
+ timer->next = NULL;
+ millis = (*timer->callback)(timer, now, timer->arg);
+ if (!millis)
+ return timer;
+ }
+ for (prev = &timers;
+ *prev && (int) ((*prev)->expires - millis) <= 0;
+ prev = &(*prev)->next)
+ ;
+ timer->next = *prev;
+ *prev = timer;
+ return timer;
+}
+
+Bool
+TimerForce(OsTimerPtr timer)
+{
+ OsTimerPtr *prev;
+
+ for (prev = &timers; *prev; prev = &(*prev)->next)
+ {
+ if (*prev == timer)
+ {
+ DoTimer(timer, GetTimeInMillis(), prev);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
+void
+TimerCancel(OsTimerPtr timer)
+{
+ OsTimerPtr *prev;
+
+ if (!timer)
+ return;
+ for (prev = &timers; *prev; prev = &(*prev)->next)
+ {
+ if (*prev == timer)
+ {
+ *prev = timer->next;
+ break;
+ }
+ }
+}
+
+void
+TimerFree(OsTimerPtr timer)
+{
+ if (!timer)
+ return;
+ TimerCancel(timer);
+ free(timer);
+}
+
+void
+TimerCheck(void)
+{
+ CARD32 now = GetTimeInMillis();
+
+ while (timers && (int) (timers->expires - now) <= 0)
+ DoTimer(timers, now, &timers);
+}
+
+void
+TimerInit(void)
+{
+ OsTimerPtr timer;
+
+ while ((timer = timers))
+ {
+ timers = timer->next;
+ free(timer);
+ }
+}
+
+static CARD32
+ScreenSaverTimeoutExpire(OsTimerPtr timer,CARD32 now,void * arg)
+{
+ INT32 timeout = now - lastDeviceEventTime.milliseconds;
+
+ if (timeout < ScreenSaverTime) {
+ return ScreenSaverTime - timeout;
+ }
+
+ ResetOsBuffers(); /* not ideal, but better than nothing */
+ SaveScreens(SCREEN_SAVER_ON, ScreenSaverActive);
+
+#ifdef DPMSExtension
+ if (ScreenSaverInterval > 0 && DPMSPowerLevel == DPMSModeOn)
+#else
+ if (ScreenSaverInterval > 0)
+#endif /* DPMSExtension */
+ return ScreenSaverInterval;
+
+ return 0;
+}
+
+static OsTimerPtr ScreenSaverTimer = NULL;
+
+void
+FreeScreenSaverTimer(void)
+{
+ if (ScreenSaverTimer) {
+ TimerFree(ScreenSaverTimer);
+ ScreenSaverTimer = NULL;
+ }
+}
+
+void
+SetScreenSaverTimer(void)
+{
+ if (ScreenSaverTime > 0) {
+ ScreenSaverTimer = TimerSet(ScreenSaverTimer, 0, ScreenSaverTime,
+ ScreenSaverTimeoutExpire, NULL);
+ } else if (ScreenSaverTimer) {
+ FreeScreenSaverTimer();
+ }
+}
+
+#ifdef DPMSExtension
+
+static OsTimerPtr DPMSStandbyTimer = NULL;
+static OsTimerPtr DPMSSuspendTimer = NULL;
+static OsTimerPtr DPMSOffTimer = NULL;
+
+static CARD32
+DPMSStandbyTimerExpire(OsTimerPtr timer,CARD32 now,void * arg)
+{
+ INT32 timeout = now - lastDeviceEventTime.milliseconds;
+
+ if (timeout < DPMSStandbyTime) {
+ return DPMSStandbyTime - timeout;
+ }
+ if (DPMSPowerLevel < DPMSModeStandby) {
+ if (DPMSEnabled)
+ DPMSSet(DPMSModeStandby);
+ }
+ return DPMSStandbyTime;
+}
+
+static CARD32
+DPMSSuspendTimerExpire(OsTimerPtr timer,CARD32 now,void * arg)
+{
+ INT32 timeout = now - lastDeviceEventTime.milliseconds;
+
+ if (timeout < DPMSSuspendTime) {
+ return DPMSSuspendTime - timeout;
+ }
+ if (DPMSPowerLevel < DPMSModeSuspend) {
+ if (DPMSEnabled)
+ DPMSSet(DPMSModeSuspend);
+ }
+ return DPMSSuspendTime;
+}
+
+static CARD32
+DPMSOffTimerExpire(OsTimerPtr timer,CARD32 now,void * arg)
+{
+ INT32 timeout = now - lastDeviceEventTime.milliseconds;
+
+ if (timeout < DPMSOffTime) {
+ return DPMSOffTime - timeout;
+ }
+ if (DPMSPowerLevel < DPMSModeOff) {
+ if (DPMSEnabled)
+ DPMSSet(DPMSModeOff);
+ }
+ return DPMSOffTime;
+}
+
+void
+FreeDPMSTimers(void)
+{
+ if (DPMSStandbyTimer) {
+ TimerFree(DPMSStandbyTimer);
+ DPMSStandbyTimer = NULL;
+ }
+ if (DPMSSuspendTimer) {
+ TimerFree(DPMSSuspendTimer);
+ DPMSSuspendTimer = NULL;
+ }
+ if (DPMSOffTimer) {
+ TimerFree(DPMSOffTimer);
+ DPMSOffTimer = NULL;
+ }
+}
+
+void
+SetDPMSTimers(void)
+{
+ if (!DPMSEnabled)
+ return;
+
+ DPMSStandbyTimer = TimerSet(DPMSStandbyTimer, 0, DPMSStandbyTime,
+ DPMSStandbyTimerExpire, NULL);
+ DPMSSuspendTimer = TimerSet(DPMSSuspendTimer, 0, DPMSSuspendTime,
+ DPMSSuspendTimerExpire, NULL);
+ DPMSOffTimer = TimerSet(DPMSOffTimer, 0, DPMSOffTime,
+ DPMSOffTimerExpire, NULL);
+}
+#endif
diff --git a/nx-X11/programs/Xserver/os/access.c b/nx-X11/programs/Xserver/os/access.c
new file mode 100644
index 000000000..d8d035ade
--- /dev/null
+++ b/nx-X11/programs/Xserver/os/access.c
@@ -0,0 +1,2285 @@
+/***********************************************************
+
+Copyright 1987, 1998 The Open Group
+Copyright 2004 Sun Microsystems, Inc.
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
+INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
+FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
+X Window System is a trademark of The Open Group.
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifdef WIN32
+#include <nx-X11/Xwinsock.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#define XSERV_t
+#define TRANS_SERVER
+#define TRANS_REOPEN
+#include <nx-X11/Xtrans/Xtrans.h>
+#include <nx-X11/Xauth.h>
+#include <nx-X11/X.h>
+#include <nx-X11/Xproto.h>
+#include "misc.h"
+#include "site.h"
+#include <errno.h>
+#include <sys/types.h>
+#ifndef WIN32
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <ctype.h>
+
+#if defined(TCPCONN) || defined(ISC) || defined(__SCO__)
+#include <netinet/in.h>
+#endif /* TCPCONN || ISC || __SCO__ */
+
+#ifdef HAS_GETPEERUCRED
+# include <ucred.h>
+# ifdef sun
+# include <zone.h>
+# endif
+#endif
+
+#if defined(SVR4) || (defined(SYSV) && defined(i386)) || defined(__GNU__)
+# include <sys/utsname.h>
+#endif
+#if defined(SYSV) && defined(i386)
+# include <sys/stream.h>
+# ifdef ISC
+# include <sys/stropts.h>
+# include <sys/sioctl.h>
+# endif /* ISC */
+#endif
+#ifdef __GNU__
+#undef SIOCGIFCONF
+#include <netdb.h>
+#else /*!__GNU__*/
+# include <net/if.h>
+#endif /*__GNU__ */
+
+#ifdef SVR4
+#include <sys/sockio.h>
+#include <sys/stropts.h>
+#endif
+
+#include <netdb.h>
+
+#ifdef CSRG_BASED
+#include <sys/param.h>
+#if (BSD >= 199103)
+#define VARIABLE_IFREQ
+#endif
+#endif
+
+#ifdef BSD44SOCKETS
+#ifndef VARIABLE_IFREQ
+#define VARIABLE_IFREQ
+#endif
+#endif
+
+#ifdef HAS_GETIFADDRS
+#include <ifaddrs.h>
+#endif
+
+/* Solaris provides an extended interface SIOCGLIFCONF. Other systems
+ * may have this as well, but the code has only been tested on Solaris
+ * so far, so we only enable it there. Other platforms may be added as
+ * needed.
+ *
+ * Test for Solaris commented out -- TSI @ UQV 2003.06.13
+ */
+#ifdef SIOCGLIFCONF
+/* #if defined(sun) */
+#define USE_SIOCGLIFCONF
+/* #endif */
+#endif
+
+#endif /* WIN32 */
+
+#ifndef PATH_MAX
+#include <sys/param.h>
+#ifndef PATH_MAX
+#ifdef MAXPATHLEN
+#define PATH_MAX MAXPATHLEN
+#else
+#define PATH_MAX 1024
+#endif
+#endif
+#endif
+
+#ifdef __SCO__
+/* The system defined value is wrong. MAXPATHLEN is set in sco5.cf. */
+#undef PATH_MAX
+#endif
+
+#define X_INCLUDE_NETDB_H
+#include <nx-X11/Xos_r.h>
+
+#include "dixstruct.h"
+#include "osdep.h"
+
+#ifdef XCSECURITY
+#define _SECURITY_SERVER
+#include <nx-X11/extensions/security.h>
+#endif
+
+#ifndef PATH_MAX
+#ifdef MAXPATHLEN
+#define PATH_MAX MAXPATHLEN
+#else
+#define PATH_MAX 1024
+#endif
+#endif
+
+Bool defeatAccessControl = FALSE;
+
+#define acmp(a1, a2, len) memcmp((char *)(a1), (char *)(a2), len)
+#define acopy(a1, a2, len) memmove((char *)(a2), (char *)(a1), len)
+#define addrEqual(fam, address, length, host) \
+ ((fam) == (host)->family &&\
+ (length) == (host)->len &&\
+ !acmp (address, (host)->addr, length))
+
+static int ConvertAddr(struct sockaddr * /*saddr*/,
+ int * /*len*/,
+ void ** /*addr*/);
+
+static int CheckAddr(int /*family*/,
+ void * /*pAddr*/,
+ unsigned /*length*/);
+
+static Bool NewHost(int /*family*/,
+ void * /*addr*/,
+ int /*len*/,
+ int /* addingLocalHosts */);
+
+/* XFree86 bug #156: To keep track of which hosts were explicitly requested in
+ /etc/X<display>.hosts, we've added a requested field to the HOST struct,
+ and a LocalHostRequested variable. These default to FALSE, but are set
+ to TRUE in ResetHosts when reading in /etc/X<display>.hosts. They are
+ checked in DisableLocalHost(), which is called to disable the default
+ local host entries when stronger authentication is turned on. */
+
+typedef struct _host {
+ short family;
+ short len;
+ unsigned char *addr;
+ struct _host *next;
+ int requested;
+} HOST;
+
+#define MakeHost(h,l) (h)=(HOST *) malloc(sizeof *(h)+(l));\
+ if (h) { \
+ (h)->addr=(unsigned char *) ((h) + 1);\
+ (h)->requested = FALSE; \
+ }
+#define FreeHost(h) free(h)
+static HOST *selfhosts = NULL;
+static HOST *validhosts = NULL;
+static int AccessEnabled = DEFAULT_ACCESS_CONTROL;
+static int LocalHostEnabled = FALSE;
+static int LocalHostRequested = FALSE;
+static int UsingXdmcp = FALSE;
+
+/* FamilyServerInterpreted implementation */
+static Bool siAddrMatch(int family, void * addr, int len, HOST *host,
+ ClientPtr client);
+static int siCheckAddr(const char *addrString, int length);
+static void siTypesInitialize(void);
+
+/*
+ * called when authorization is not enabled to add the
+ * local host to the access list
+ */
+
+void
+EnableLocalHost (void)
+{
+ if (!UsingXdmcp)
+ {
+ LocalHostEnabled = TRUE;
+ AddLocalHosts ();
+ }
+}
+
+/*
+ * called when authorization is enabled to keep us secure
+ */
+void
+DisableLocalHost (void)
+{
+ HOST *self;
+
+ if (!LocalHostRequested) /* Fix for XFree86 bug #156 */
+ LocalHostEnabled = FALSE;
+ for (self = selfhosts; self; self = self->next) {
+ if (!self->requested) /* Fix for XFree86 bug #156 */
+ (void) RemoveHost ((ClientPtr)NULL, self->family, self->len, (void *)self->addr);
+ }
+}
+
+/*
+ * called at init time when XDMCP will be used; xdmcp always
+ * adds local hosts manually when needed
+ */
+
+void
+AccessUsingXdmcp (void)
+{
+ UsingXdmcp = TRUE;
+ LocalHostEnabled = FALSE;
+}
+
+
+#if ((defined(SVR4) && !defined(SCO325) && !defined(sun) && !defined(NCR)) || defined(ISC)) && defined(SIOCGIFCONF) && !defined(USE_SIOCGLIFCONF)
+
+/* Deal with different SIOCGIFCONF ioctl semantics on these OSs */
+
+static int
+ifioctl (int fd, int cmd, char *arg)
+{
+ struct strioctl ioc;
+ int ret;
+
+ bzero((char *) &ioc, sizeof(ioc));
+ ioc.ic_cmd = cmd;
+ ioc.ic_timout = 0;
+ if (cmd == SIOCGIFCONF)
+ {
+ ioc.ic_len = ((struct ifconf *) arg)->ifc_len;
+ ioc.ic_dp = ((struct ifconf *) arg)->ifc_buf;
+#ifdef ISC
+ /* SIOCGIFCONF is somewhat brain damaged on ISC. The argument
+ * buffer must contain the ifconf structure as header. Ifc_req
+ * is also not a pointer but a one element array of ifreq
+ * structures. On return this array is extended by enough
+ * ifreq fields to hold all interfaces. The return buffer length
+ * is placed in the buffer header.
+ */
+ ((struct ifconf *) ioc.ic_dp)->ifc_len =
+ ioc.ic_len - sizeof(struct ifconf);
+#endif
+ }
+ else
+ {
+ ioc.ic_len = sizeof(struct ifreq);
+ ioc.ic_dp = arg;
+ }
+ ret = ioctl(fd, I_STR, (char *) &ioc);
+ if (ret >= 0 && cmd == SIOCGIFCONF)
+#ifdef SVR4
+ ((struct ifconf *) arg)->ifc_len = ioc.ic_len;
+#endif
+#ifdef ISC
+ {
+ ((struct ifconf *) arg)->ifc_len =
+ ((struct ifconf *)ioc.ic_dp)->ifc_len;
+ ((struct ifconf *) arg)->ifc_buf =
+ (caddr_t)((struct ifconf *)ioc.ic_dp)->ifc_req;
+ }
+#endif
+ return(ret);
+}
+#else /* Case sun, SCO325 NCR and others */
+#define ifioctl ioctl
+#endif /* ((SVR4 && !sun !SCO325 !NCR) || ISC) && SIOCGIFCONF */
+
+/*
+ * DefineSelf (fd):
+ *
+ * Define this host for access control. Find all the hosts the OS knows about
+ * for this fd and add them to the selfhosts list.
+ */
+
+#ifdef WINTCP /* NCR Wollongong based TCP */
+
+#include <sys/un.h>
+#include <stropts.h>
+#include <tiuser.h>
+
+#include <sys/stream.h>
+#include <net/if.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/in.h>
+#include <netinet/in_var.h>
+
+void
+DefineSelf (int fd)
+{
+ /*
+ * The Wolongong drivers used by NCR SVR4/MP-RAS don't understand the
+ * socket IO calls that most other drivers seem to like. Because of
+ * this, this routine must be special cased for NCR. Eventually,
+ * this will be cleared up.
+ */
+
+ struct ipb ifnet;
+ struct in_ifaddr ifaddr;
+ struct strioctl str;
+ unsigned char *addr;
+ register HOST *host;
+ int family, len;
+
+ if ((fd = open ("/dev/ip", O_RDWR, 0 )) < 0)
+ Error ("Getting interface configuration (1)");
+
+ /* Indicate that we want to start at the begining */
+ ifnet.ib_next = (struct ipb *) 1;
+
+ while (ifnet.ib_next)
+ {
+ str.ic_cmd = IPIOC_GETIPB;
+ str.ic_timout = 0;
+ str.ic_len = sizeof (struct ipb);
+ str.ic_dp = (char *) &ifnet;
+
+ if (ioctl (fd, (int) I_STR, (char *) &str) < 0)
+ {
+ close (fd);
+ Error ("Getting interface configuration (2)");
+ }
+
+ ifaddr.ia_next = (struct in_ifaddr *) ifnet.if_addrlist;
+ str.ic_cmd = IPIOC_GETINADDR;
+ str.ic_timout = 0;
+ str.ic_len = sizeof (struct in_ifaddr);
+ str.ic_dp = (char *) &ifaddr;
+
+ if (ioctl (fd, (int) I_STR, (char *) &str) < 0)
+ {
+ close (fd);
+ Error ("Getting interface configuration (3)");
+ }
+
+ len = sizeof(struct sockaddr_in);
+ family = ConvertAddr (IA_SIN(&ifaddr), &len, (void **)&addr);
+ if (family == -1 || family == FamilyLocal)
+ continue;
+ for (host = selfhosts;
+ host && !addrEqual (family, addr, len, host);
+ host = host->next)
+ ;
+ if (host)
+ continue;
+ MakeHost(host,len)
+ if (host)
+ {
+ host->family = family;
+ host->len = len;
+ acopy(addr, host->addr, len);
+ host->next = selfhosts;
+ selfhosts = host;
+ }
+#ifdef XDMCP
+ {
+ struct sockaddr broad_addr;
+
+ /*
+ * If this isn't an Internet Address, don't register it.
+ */
+ if (family != FamilyInternet)
+ continue;
+
+ /*
+ * Ignore 'localhost' entries as they're not useful
+ * on the other end of the wire.
+ */
+ if (len == 4 &&
+ addr[0] == 127 && addr[1] == 0 &&
+ addr[2] == 0 && addr[3] == 1)
+ continue;
+
+ /*
+ * Ignore '0.0.0.0' entries as they are
+ * returned by some OSes for unconfigured NICs but they are
+ * not useful on the other end of the wire.
+ */
+ if (len == 4 &&
+ addr[0] == 0 && addr[1] == 0 &&
+ addr[2] == 0 && addr[3] == 0)
+ continue;
+
+ XdmcpRegisterConnection (family, (char *)addr, len);
+
+
+#define IA_BROADADDR(ia) ((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_broadaddr))
+
+ XdmcpRegisterBroadcastAddress (
+ (struct sockaddr_in *) IA_BROADADDR(&ifaddr));
+
+#undef IA_BROADADDR
+ }
+#endif /* XDMCP */
+ }
+
+ close(fd);
+
+ /*
+ * add something of FamilyLocalHost
+ */
+ for (host = selfhosts;
+ host && !addrEqual(FamilyLocalHost, "", 0, host);
+ host = host->next);
+ if (!host)
+ {
+ MakeHost(host, 0);
+ if (host)
+ {
+ host->family = FamilyLocalHost;
+ host->len = 0;
+ acopy("", host->addr, 0);
+ host->next = selfhosts;
+ selfhosts = host;
+ }
+ }
+}
+
+#else /* WINTCP */
+
+#if !defined(SIOCGIFCONF)
+void
+DefineSelf (int fd)
+{
+#if !defined(TCPCONN) && !defined(UNIXCONN)
+ return;
+#else
+ register int n;
+ int len;
+ caddr_t addr;
+ int family;
+ register HOST *host;
+
+#ifndef WIN32
+ struct utsname name;
+#else
+ struct {
+ char nodename[512];
+ } name;
+#endif
+
+ register struct hostent *hp;
+
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in in;
+#if defined(IPv6) && defined(AF_INET6)
+ struct sockaddr_in6 in6;
+#endif
+ } saddr;
+
+ struct sockaddr_in *inetaddr;
+ struct sockaddr_in6 *inet6addr;
+ struct sockaddr_in broad_addr;
+#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
+ _Xgethostbynameparams hparams;
+#endif
+
+ /* Why not use gethostname()? Well, at least on my system, I've had to
+ * make an ugly kernel patch to get a name longer than 8 characters, and
+ * uname() lets me access to the whole string (it smashes release, you
+ * see), whereas gethostname() kindly truncates it for me.
+ */
+#ifndef WIN32
+ uname(&name);
+#else
+ gethostname(name.nodename, sizeof(name.nodename));
+#endif
+
+ hp = _XGethostbyname(name.nodename, hparams);
+ if (hp != NULL)
+ {
+ saddr.sa.sa_family = hp->h_addrtype;
+ switch (hp->h_addrtype) {
+ case AF_INET:
+ inetaddr = (struct sockaddr_in *) (&(saddr.sa));
+ acopy ( hp->h_addr, &(inetaddr->sin_addr), hp->h_length);
+ len = sizeof(saddr.sa);
+ break;
+#if defined(IPv6) && defined(AF_INET6)
+ case AF_INET6:
+ inet6addr = (struct sockaddr_in6 *) (&(saddr.sa));
+ acopy ( hp->h_addr, &(inet6addr->sin6_addr), hp->h_length);
+ len = sizeof(saddr.in6);
+ break;
+#endif
+ default:
+ goto DefineLocalHost;
+ }
+ family = ConvertAddr ( &(saddr.sa), &len, (void **)&addr);
+ if ( family != -1 && family != FamilyLocal )
+ {
+ for (host = selfhosts;
+ host && !addrEqual (family, addr, len, host);
+ host = host->next) ;
+ if (!host)
+ {
+ /* add this host to the host list. */
+ MakeHost(host,len)
+ if (host)
+ {
+ host->family = family;
+ host->len = len;
+ acopy ( addr, host->addr, len);
+ host->next = selfhosts;
+ selfhosts = host;
+ }
+#ifdef XDMCP
+ /*
+ * If this is an Internet Address, but not the localhost
+ * address (127.0.0.1), nor the bogus address (0.0.0.0),
+ * register it.
+ */
+ if (family == FamilyInternet &&
+ !(len == 4 &&
+ ((addr[0] == 127 && addr[1] == 0 &&
+ addr[2] == 0 && addr[3] == 1) ||
+ (addr[0] == 0 && addr[1] == 0 &&
+ addr[2] == 0 && addr[3] == 0)))
+ )
+ {
+ XdmcpRegisterConnection (family, (char *)addr, len);
+ broad_addr = *inetaddr;
+ ((struct sockaddr_in *) &broad_addr)->sin_addr.s_addr =
+ htonl (INADDR_BROADCAST);
+ XdmcpRegisterBroadcastAddress ((struct sockaddr_in *)
+ &broad_addr);
+ }
+#if defined(IPv6) && defined(AF_INET6)
+ else if (family == FamilyInternet6 &&
+ !(IN6_IS_ADDR_LOOPBACK((struct in6_addr *)addr)))
+ {
+ XdmcpRegisterConnection (family, (char *)addr, len);
+ }
+#endif
+
+#endif /* XDMCP */
+ }
+ }
+ }
+ /*
+ * now add a host of family FamilyLocalHost...
+ */
+DefineLocalHost:
+ for (host = selfhosts;
+ host && !addrEqual(FamilyLocalHost, "", 0, host);
+ host = host->next);
+ if (!host)
+ {
+ MakeHost(host, 0);
+ if (host)
+ {
+ host->family = FamilyLocalHost;
+ host->len = 0;
+ acopy("", host->addr, 0);
+ host->next = selfhosts;
+ selfhosts = host;
+ }
+ }
+#endif /* !TCPCONN && !UNIXCONN */
+}
+
+#else
+
+#ifdef USE_SIOCGLIFCONF
+#define ifr_type struct lifreq
+#else
+#define ifr_type struct ifreq
+#endif
+
+#ifdef VARIABLE_IFREQ
+#define ifr_size(p) (sizeof (struct ifreq) + \
+ (p->ifr_addr.sa_len > sizeof (p->ifr_addr) ? \
+ p->ifr_addr.sa_len - sizeof (p->ifr_addr) : 0))
+#define ifraddr_size(a) (a.sa_len)
+#else
+#define ifr_size(p) (sizeof (ifr_type))
+#define ifraddr_size(a) (sizeof (a))
+#endif
+
+#if defined(DEF_SELF_DEBUG) || (defined(IPv6) && defined(AF_INET6))
+#include <arpa/inet.h>
+#endif
+
+#if defined(IPv6) && defined(AF_INET6)
+static void
+in6_fillscopeid(struct sockaddr_in6 *sin6)
+{
+#if defined(__KAME__)
+ if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
+ sin6->sin6_scope_id =
+ ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]);
+ sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = 0;
+ }
+#endif
+}
+#endif
+
+void
+DefineSelf (int fd)
+{
+#ifndef HAS_GETIFADDRS
+ char buf[2048], *cp, *cplim;
+ void * bufptr = buf;
+#ifdef USE_SIOCGLIFCONF
+ struct lifconf ifc;
+ register struct lifreq *ifr;
+#ifdef SIOCGLIFNUM
+ struct lifnum ifn;
+#endif
+#else
+ struct ifconf ifc;
+ register struct ifreq *ifr;
+#endif
+#else
+ struct ifaddrs * ifap, *ifr;
+#endif
+ int len;
+ unsigned char * addr;
+ int family;
+ register HOST *host;
+
+#ifndef HAS_GETIFADDRS
+
+ len = sizeof(buf);
+
+#ifdef USE_SIOCGLIFCONF
+
+#ifdef SIOCGLIFNUM
+ ifn.lifn_family = AF_UNSPEC;
+ ifn.lifn_flags = 0;
+ if (ioctl (fd, SIOCGLIFNUM, (char *) &ifn) < 0)
+ Error ("Getting interface count");
+ if (len < (ifn.lifn_count * sizeof(struct lifreq))) {
+ len = ifn.lifn_count * sizeof(struct lifreq);
+ bufptr = malloc(len);
+ }
+#endif
+
+ ifc.lifc_family = AF_UNSPEC;
+ ifc.lifc_flags = 0;
+ ifc.lifc_len = len;
+ ifc.lifc_buf = bufptr;
+
+#define IFC_IOCTL_REQ SIOCGLIFCONF
+#define IFC_IFC_REQ ifc.lifc_req
+#define IFC_IFC_LEN ifc.lifc_len
+#define IFR_IFR_ADDR ifr->lifr_addr
+#define IFR_IFR_NAME ifr->lifr_name
+
+#else /* Use SIOCGIFCONF */
+ ifc.ifc_len = len;
+ ifc.ifc_buf = bufptr;
+
+#define IFC_IOCTL_REQ SIOCGIFCONF
+#ifdef ISC
+#define IFC_IFC_REQ (struct ifreq *) ifc.ifc_buf
+#else
+#define IFC_IFC_REQ ifc.ifc_req
+#endif /* ISC */
+#define IFC_IFC_LEN ifc.ifc_len
+#define IFR_IFR_ADDR ifr->ifr_addr
+#define IFR_IFR_NAME ifr->ifr_name
+#endif
+
+ if (ifioctl (fd, IFC_IOCTL_REQ, (void *) &ifc) < 0)
+ Error ("Getting interface configuration (4)");
+
+ cplim = (char *) IFC_IFC_REQ + IFC_IFC_LEN;
+
+ for (cp = (char *) IFC_IFC_REQ; cp < cplim; cp += ifr_size (ifr))
+ {
+ ifr = (ifr_type *) cp;
+ len = ifraddr_size (IFR_IFR_ADDR);
+ family = ConvertAddr ((struct sockaddr *) &IFR_IFR_ADDR,
+ &len, (void **)&addr);
+ if (family == -1 || family == FamilyLocal)
+ continue;
+#if defined(IPv6) && defined(AF_INET6)
+ if (family == FamilyInternet6)
+ in6_fillscopeid((struct sockaddr_in6 *)&IFR_IFR_ADDR);
+#endif
+#ifdef DEF_SELF_DEBUG
+ if (family == FamilyInternet)
+ ErrorF("Xserver: DefineSelf(): ifname = %s, addr = %d.%d.%d.%d\n",
+ IFR_IFR_NAME, addr[0], addr[1], addr[2], addr[3]);
+#if defined(IPv6) && defined(AF_INET6)
+ else if (family == FamilyInternet6) {
+ char cp[INET6_ADDRSTRLEN] = "";
+ inet_ntop(AF_INET6, addr, cp, sizeof(cp));
+ ErrorF("Xserver: DefineSelf(): ifname = %s, addr = %s\n",
+ IFR_IFR_NAME, cp);
+ }
+#endif
+#endif /* DEF_SELF_DEBUG */
+ for (host = selfhosts;
+ host && !addrEqual (family, addr, len, host);
+ host = host->next)
+ ;
+ if (host)
+ continue;
+ MakeHost(host,len)
+ if (host)
+ {
+ host->family = family;
+ host->len = len;
+ acopy(addr, host->addr, len);
+ host->next = selfhosts;
+ selfhosts = host;
+ }
+#ifdef XDMCP
+ {
+#ifdef USE_SIOCGLIFCONF
+ struct sockaddr_storage broad_addr;
+#else
+ struct sockaddr broad_addr;
+#endif
+
+ /*
+ * If this isn't an Internet Address, don't register it.
+ */
+ if (family != FamilyInternet
+#if defined(IPv6) && defined(AF_INET6)
+ && family != FamilyInternet6
+#endif
+ )
+ continue;
+
+ /*
+ * ignore 'localhost' entries as they're not useful
+ * on the other end of the wire
+ */
+ if (family == FamilyInternet &&
+ addr[0] == 127 && addr[1] == 0 &&
+ addr[2] == 0 && addr[3] == 1)
+ continue;
+#if defined(IPv6) && defined(AF_INET6)
+ else if (family == FamilyInternet6 &&
+ IN6_IS_ADDR_LOOPBACK((struct in6_addr *)addr))
+ continue;
+#endif
+
+ /*
+ * Ignore '0.0.0.0' entries as they are
+ * returned by some OSes for unconfigured NICs but they are
+ * not useful on the other end of the wire.
+ */
+ if (len == 4 &&
+ addr[0] == 0 && addr[1] == 0 &&
+ addr[2] == 0 && addr[3] == 0)
+ continue;
+
+ XdmcpRegisterConnection (family, (char *)addr, len);
+
+#if defined(IPv6) && defined(AF_INET6)
+ /* IPv6 doesn't support broadcasting, so we drop out here */
+ if (family == FamilyInternet6)
+ continue;
+#endif
+
+ broad_addr = IFR_IFR_ADDR;
+
+ ((struct sockaddr_in *) &broad_addr)->sin_addr.s_addr =
+ htonl (INADDR_BROADCAST);
+#if defined(USE_SIOCGLIFCONF) && defined(SIOCGLIFBRDADDR)
+ {
+ struct lifreq broad_req;
+
+ broad_req = *ifr;
+ if (ioctl (fd, SIOCGLIFFLAGS, (char *) &broad_req) != -1 &&
+ (broad_req.lifr_flags & IFF_BROADCAST) &&
+ (broad_req.lifr_flags & IFF_UP)
+ )
+ {
+ broad_req = *ifr;
+ if (ioctl (fd, SIOCGLIFBRDADDR, &broad_req) != -1)
+ broad_addr = broad_req.lifr_broadaddr;
+ else
+ continue;
+ }
+ else
+ continue;
+ }
+
+#elif defined(SIOCGIFBRDADDR)
+ {
+ struct ifreq broad_req;
+
+ broad_req = *ifr;
+ if (ifioctl (fd, SIOCGIFFLAGS, (void *) &broad_req) != -1 &&
+ (broad_req.ifr_flags & IFF_BROADCAST) &&
+ (broad_req.ifr_flags & IFF_UP)
+ )
+ {
+ broad_req = *ifr;
+ if (ifioctl (fd, SIOCGIFBRDADDR, (void *) &broad_req) != -1)
+ broad_addr = broad_req.ifr_addr;
+ else
+ continue;
+ }
+ else
+ continue;
+ }
+#endif /* SIOCGIFBRDADDR */
+#ifdef DEF_SELF_DEBUG
+ ErrorF("Xserver: DefineSelf(): ifname = %s, baddr = %s\n",
+ IFR_IFR_NAME,
+ inet_ntoa(((struct sockaddr_in *) &broad_addr)->sin_addr));
+#endif /* DEF_SELF_DEBUG */
+ XdmcpRegisterBroadcastAddress ((struct sockaddr_in *) &broad_addr);
+ }
+#endif /* XDMCP */
+ }
+ if (bufptr != buf)
+ free(bufptr);
+#else /* HAS_GETIFADDRS */
+ if (getifaddrs(&ifap) < 0) {
+ ErrorF("Warning: getifaddrs returns %s\n", strerror(errno));
+ return;
+ }
+ for (ifr = ifap; ifr != NULL; ifr = ifr->ifa_next) {
+ if (!ifr->ifa_addr)
+ continue;
+ len = sizeof(*(ifr->ifa_addr));
+ family = ConvertAddr(ifr->ifa_addr, &len, (void **)&addr);
+ if (family == -1 || family == FamilyLocal)
+ continue;
+#if defined(IPv6) && defined(AF_INET6)
+ if (family == FamilyInternet6)
+ in6_fillscopeid((struct sockaddr_in6 *)ifr->ifa_addr);
+#endif
+
+#ifdef DEF_SELF_DEBUG
+ if (family == FamilyInternet)
+ ErrorF("Xserver: DefineSelf(): ifname = %s, addr = %d.%d.%d.%d\n",
+ ifr->ifa_name, addr[0], addr[1], addr[2], addr[3]);
+#if defined(IPv6) && defined(AF_INET6)
+ else if (family == FamilyInternet6) {
+ char cp[INET6_ADDRSTRLEN];
+
+ inet_ntop(AF_INET6, addr, cp, sizeof(cp));
+ ErrorF("Xserver: DefineSelf(): ifname = %s addr = %s\n",
+ ifr->ifa_name, cp);
+ }
+#endif
+#endif /* DEF_SELF_DEBUG */
+ for (host = selfhosts;
+ host != NULL && !addrEqual(family, addr, len, host);
+ host = host->next)
+ ;
+ if (host != NULL)
+ continue;
+ MakeHost(host, len);
+ if (host != NULL) {
+ host->family = family;
+ host->len = len;
+ acopy(addr, host->addr, len);
+ host->next = selfhosts;
+ selfhosts = host;
+ }
+#ifdef XDMCP
+ {
+ struct sockaddr broad_addr;
+ /*
+ * If this isn't an Internet Address, don't register it.
+ */
+ if (family != FamilyInternet
+#if defined(IPv6) && defined(AF_INET6)
+ && family != FamilyInternet6
+#endif
+ )
+ continue;
+
+ /*
+ * ignore 'localhost' entries as they're not useful
+ * on the other end of the wire
+ */
+ if (ifr->ifa_flags & IFF_LOOPBACK)
+ continue;
+
+ if (family == FamilyInternet &&
+ addr[0] == 127 && addr[1] == 0 &&
+ addr[2] == 0 && addr[3] == 1)
+ continue;
+
+ /*
+ * Ignore '0.0.0.0' entries as they are
+ * returned by some OSes for unconfigured NICs but they are
+ * not useful on the other end of the wire.
+ */
+ if (len == 4 &&
+ addr[0] == 0 && addr[1] == 0 &&
+ addr[2] == 0 && addr[3] == 0)
+ continue;
+#if defined(IPv6) && defined(AF_INET6)
+ else if (family == FamilyInternet6 &&
+ IN6_IS_ADDR_LOOPBACK((struct in6_addr *)addr))
+ continue;
+#endif
+ XdmcpRegisterConnection(family, (char *)addr, len);
+#if defined(IPv6) && defined(AF_INET6)
+ if (family == FamilyInternet6)
+ /* IPv6 doesn't support broadcasting, so we drop out here */
+ continue;
+#endif
+ if ((ifr->ifa_flags & IFF_BROADCAST) &&
+ (ifr->ifa_flags & IFF_UP))
+ broad_addr = *ifr->ifa_broadaddr;
+ else
+ continue;
+#ifdef DEF_SELF_DEBUG
+ ErrorF("Xserver: DefineSelf(): ifname = %s, baddr = %s\n",
+ ifr->ifa_name,
+ inet_ntoa(((struct sockaddr_in *) &broad_addr)->sin_addr));
+#endif /* DEF_SELF_DEBUG */
+ XdmcpRegisterBroadcastAddress((struct sockaddr_in *)
+ &broad_addr);
+ }
+#endif /* XDMCP */
+
+ } /* for */
+ freeifaddrs(ifap);
+#endif /* HAS_GETIFADDRS */
+
+ /*
+ * add something of FamilyLocalHost
+ */
+ for (host = selfhosts;
+ host && !addrEqual(FamilyLocalHost, "", 0, host);
+ host = host->next);
+ if (!host)
+ {
+ MakeHost(host, 0);
+ if (host)
+ {
+ host->family = FamilyLocalHost;
+ host->len = 0;
+ acopy("", host->addr, 0);
+ host->next = selfhosts;
+ selfhosts = host;
+ }
+ }
+}
+#endif /* !SIOCGIFCONF */
+#endif /* WINTCP */
+
+#ifdef XDMCP
+void
+AugmentSelf(void * from, int len)
+{
+ int family;
+ void * addr;
+ register HOST *host;
+
+ family = ConvertAddr(from, &len, (void **)&addr);
+ if (family == -1 || family == FamilyLocal)
+ return;
+ for (host = selfhosts; host; host = host->next)
+ {
+ if (addrEqual(family, addr, len, host))
+ return;
+ }
+ MakeHost(host,len)
+ if (!host)
+ return;
+ host->family = family;
+ host->len = len;
+ acopy(addr, host->addr, len);
+ host->next = selfhosts;
+ selfhosts = host;
+}
+#endif
+
+void
+AddLocalHosts (void)
+{
+ HOST *self;
+
+ for (self = selfhosts; self; self = self->next)
+ /* Fix for XFree86 bug #156: pass addingLocal = TRUE to
+ * NewHost to tell that we are adding the default local
+ * host entries and not to flag the entries as being
+ * explicitely requested */
+ (void) NewHost (self->family, self->addr, self->len, TRUE);
+}
+
+/* Reset access control list to initial hosts */
+void
+ResetHosts (char *display)
+{
+ register HOST *host;
+ char lhostname[120], ohostname[120];
+ char *hostname = ohostname;
+ char fname[PATH_MAX + 1];
+ int fnamelen;
+ FILE *fd;
+ char *ptr;
+ int i, hostlen;
+#if (defined(TCPCONN) && (!defined(IPv6) || !defined(AF_INET6)))
+ union {
+ struct sockaddr sa;
+#if defined(TCPCONN)
+ struct sockaddr_in in;
+#endif /* TCPCONN */
+ } saddr;
+#endif
+ int family = 0;
+ void *addr = NULL;
+ int len;
+
+ siTypesInitialize();
+ AccessEnabled = defeatAccessControl ? FALSE : DEFAULT_ACCESS_CONTROL;
+ LocalHostEnabled = FALSE;
+ while ((host = validhosts) != 0)
+ {
+ validhosts = host->next;
+ FreeHost (host);
+ }
+
+#define ETC_HOST_PREFIX "/etc/X"
+#define ETC_HOST_SUFFIX ".hosts"
+ fnamelen = strlen(ETC_HOST_PREFIX) + strlen(ETC_HOST_SUFFIX) +
+ strlen(display) + 1;
+ if (fnamelen > sizeof(fname))
+ FatalError("Display name `%s' is too long\n", display);
+ sprintf(fname, ETC_HOST_PREFIX "%s" ETC_HOST_SUFFIX, display);
+
+ if ((fd = fopen (fname, "r")) != 0)
+ {
+ while (fgets (ohostname, sizeof (ohostname), fd))
+ {
+ family = FamilyWild;
+ if (*ohostname == '#')
+ continue;
+ if ((ptr = strchr(ohostname, '\n')) != 0)
+ *ptr = 0;
+ hostlen = strlen(ohostname) + 1;
+ for (i = 0; i < hostlen; i++)
+ lhostname[i] = tolower(ohostname[i]);
+ hostname = ohostname;
+ if (!strncmp("local:", lhostname, 6))
+ {
+ family = FamilyLocalHost;
+ NewHost(family, "", 0, FALSE);
+ LocalHostRequested = TRUE; /* Fix for XFree86 bug #156 */
+ }
+#if defined(TCPCONN)
+ else if (!strncmp("inet:", lhostname, 5))
+ {
+ family = FamilyInternet;
+ hostname = ohostname + 5;
+ }
+#if defined(IPv6) && defined(AF_INET6)
+ else if (!strncmp("inet6:", lhostname, 6))
+ {
+ family = FamilyInternet6;
+ hostname = ohostname + 6;
+ }
+#endif
+#endif
+#ifdef SECURE_RPC
+ else if (!strncmp("nis:", lhostname, 4))
+ {
+ family = FamilyNetname;
+ hostname = ohostname + 4;
+ }
+#endif
+ else if (!strncmp("si:", lhostname, 3))
+ {
+ family = FamilyServerInterpreted;
+ hostname = ohostname + 3;
+ hostlen -= 3;
+ }
+
+
+ if (family == FamilyServerInterpreted)
+ {
+ len = siCheckAddr(hostname, hostlen);
+ if (len >= 0) {
+ NewHost(family, hostname, len, FALSE);
+ }
+ }
+ else
+#ifdef SECURE_RPC
+ if ((family == FamilyNetname) || (strchr(hostname, '@')))
+ {
+ SecureRPCInit ();
+ (void) NewHost (FamilyNetname, hostname, strlen (hostname), FALSE);
+ }
+ else
+#endif /* SECURE_RPC */
+#if defined(TCPCONN)
+ {
+#if defined(IPv6) && defined(AF_INET6)
+ if ( (family == FamilyInternet) || (family == FamilyInternet6) ||
+ (family == FamilyWild) )
+ {
+ struct addrinfo *addresses;
+ struct addrinfo *a;
+ int f;
+
+ if (getaddrinfo(hostname, NULL, NULL, &addresses) == 0) {
+ for (a = addresses ; a != NULL ; a = a->ai_next) {
+ len = a->ai_addrlen;
+ f = ConvertAddr(a->ai_addr,&len,(void **)&addr);
+ if (addr && ((family == f) ||
+ ((family == FamilyWild) && (f != -1)))) {
+ NewHost(f, addr, len, FALSE);
+ }
+ }
+ freeaddrinfo(addresses);
+ }
+ }
+#else
+#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
+ _Xgethostbynameparams hparams;
+#endif
+ register struct hostent *hp;
+
+ /* host name */
+ if ((family == FamilyInternet &&
+ ((hp = _XGethostbyname(hostname, hparams)) != 0)) ||
+ ((hp = _XGethostbyname(hostname, hparams)) != 0))
+ {
+ saddr.sa.sa_family = hp->h_addrtype;
+ len = sizeof(saddr.sa);
+ if ((family = ConvertAddr (&saddr.sa, &len, (void **)&addr)) != -1)
+ {
+#ifdef h_addr /* new 4.3bsd version of gethostent */
+ char **list;
+
+ /* iterate over the addresses */
+ for (list = hp->h_addr_list; *list; list++)
+ (void) NewHost (family, (void *)*list, len, FALSE);
+#else
+ (void) NewHost (family, (void *)hp->h_addr, len, FALSE);
+#endif
+ }
+ }
+#endif /* IPv6 */
+ }
+#endif /* TCPCONN */
+ family = FamilyWild;
+ }
+ fclose (fd);
+ }
+}
+
+/* Is client on the local host */
+Bool
+ComputeLocalClient(ClientPtr client)
+{
+ int alen, family, notused;
+ Xtransaddr *from = NULL;
+ void *addr;
+ register HOST *host;
+ OsCommPtr oc = (OsCommPtr) client->osPrivate;
+
+ if (!oc->trans_conn)
+ return FALSE;
+
+#ifdef XCSECURITY
+ /* untrusted clients can't change host access */
+ if (client->trustLevel != XSecurityClientTrusted)
+ {
+ SecurityAudit("client %d attempted to change host access\n",
+ client->index);
+ return FALSE;
+ }
+#endif
+ if (!_XSERVTransGetPeerAddr (oc->trans_conn, &notused, &alen, &from))
+ {
+ family = ConvertAddr ((struct sockaddr *) from,
+ &alen, (void **)&addr);
+ if (family == -1)
+ {
+ free(from);
+ return FALSE;
+ }
+ if (family == FamilyLocal)
+ {
+ free(from);
+ return TRUE;
+ }
+ for (host = selfhosts; host; host = host->next)
+ {
+ if (addrEqual (family, addr, alen, host)) {
+ free(from);
+ return TRUE;
+ }
+ }
+ free(from);
+ }
+ return FALSE;
+}
+
+/*
+ * Return the uid and gid of a connected local client
+ *
+ * Used by XShm to test access rights to shared memory segments
+ */
+int
+LocalClientCred(ClientPtr client, int *pUid, int *pGid)
+{
+ LocalClientCredRec *lcc;
+ int ret = GetLocalClientCreds(client, &lcc);
+
+ if (ret == 0) {
+#ifdef HAVE_GETZONEID /* only local if in the same zone */
+ if ((lcc->fieldsSet & LCC_ZID_SET) && (lcc->zoneid != getzoneid())) {
+ FreeLocalClientCreds(lcc);
+ return -1;
+ }
+#endif
+ if ((lcc->fieldsSet & LCC_UID_SET) && (pUid != NULL))
+ *pUid = lcc->euid;
+ if ((lcc->fieldsSet & LCC_GID_SET) && (pGid != NULL))
+ *pGid = lcc->egid;
+ FreeLocalClientCreds(lcc);
+ }
+ return ret;
+}
+
+/*
+ * Return the uid and all gids of a connected local client
+ * Allocates a LocalClientCredRec - caller must call FreeLocalClientCreds
+ *
+ * Used by localuser & localgroup ServerInterpreted access control forms below
+ * Used by AuthAudit to log where local connections came from
+ */
+int
+GetLocalClientCreds(ClientPtr client, LocalClientCredRec **lccp)
+{
+#if defined(HAS_GETPEEREID) || defined(HAS_GETPEERUCRED) || defined(SO_PEERCRED)
+ int fd;
+ XtransConnInfo ci;
+ LocalClientCredRec *lcc;
+#ifdef HAS_GETPEEREID
+ uid_t uid;
+ gid_t gid;
+#elif defined(HAS_GETPEERUCRED)
+ ucred_t *peercred = NULL;
+ const gid_t *gids;
+#elif defined(SO_PEERCRED)
+ struct ucred peercred;
+ socklen_t so_len = sizeof(peercred);
+#endif
+
+ if (client == NULL)
+ return -1;
+ ci = ((OsCommPtr)client->osPrivate)->trans_conn;
+#if !(defined(sun) && defined(HAS_GETPEERUCRED))
+ /* Most implementations can only determine peer credentials for Unix
+ * domain sockets - Solaris getpeerucred can work with a bit more, so
+ * we just let it tell us if the connection type is supported or not
+ */
+ if (!_XSERVTransIsLocal(ci)) {
+ return -1;
+ }
+#endif
+
+ *lccp = calloc(1, sizeof(LocalClientCredRec));
+ if (*lccp == NULL)
+ return -1;
+ lcc = *lccp;
+
+ fd = _XSERVTransGetConnectionNumber(ci);
+#ifdef HAS_GETPEEREID
+ if (getpeereid(fd, &uid, &gid) == -1) {
+ FreeLocalClientCreds(lcc);
+ return -1;
+ }
+ lcc->euid = uid;
+ lcc->egid = gid;
+ lcc->fieldsSet = LCC_UID_SET | LCC_GID_SET;
+ return 0;
+#elif defined(HAS_GETPEERUCRED)
+ if (getpeerucred(fd, &peercred) < 0) {
+ FreeLocalClientCreds(lcc);
+ return -1;
+ lcc->euid = ucred_geteuid(peercred);
+ if (lcc->euid != -1)
+ lcc->fieldsSet |= LCC_UID_SET;
+ lcc->egid = ucred_getegid(peercred);
+ if (lcc->egid != -1)
+ lcc->fieldsSet |= LCC_GID_SET;
+ lcc->pid = ucred_getpid(peercred);
+ if (lcc->pid != -1)
+ lcc->fieldsSet |= LCC_PID_SET;
+#ifdef HAVE_GETZONEID
+ lcc->zoneid = ucred_getzoneid(peercred);
+ if (lcc->zoneid != -1)
+ lcc->fieldsSet |= LCC_ZID_SET;
+#endif
+ lcc->nSuppGids = ucred_getgroups(peercred, &gids);
+ if (lcc->nSuppGids > 0) {
+ lcc->pSuppGids = calloc((lcc->nSuppGids), sizeof(int));
+ if (lcc->pSuppGids == NULL) {
+ lcc->nSuppGids = 0;
+ } else {
+ int i;
+ for (i = 0 ; i < lcc->nSuppGids; i++) {
+ (lcc->pSuppGids)[i] = (int) gids[i];
+ }
+ }
+ } else {
+ lcc->nSuppGids = 0;
+ }
+ ucred_free(peercred);
+ return 0;
+#elif defined(SO_PEERCRED)
+ if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) == -1) {
+ FreeLocalClientCreds(lcc);
+ return -1;
+ }
+ lcc->euid = peercred.uid;
+ lcc->egid = peercred.gid;
+ lcc->pid = peercred.pid;
+ lcc->fieldsSet = LCC_UID_SET | LCC_GID_SET | LCC_PID_SET;
+ return 0;
+#endif
+#else
+ /* No system call available to get the credentials of the peer */
+#define NO_LOCAL_CLIENT_CRED
+ return -1;
+#endif
+}
+
+void
+FreeLocalClientCreds(LocalClientCredRec *lcc)
+{
+ if (lcc != NULL) {
+ if (lcc->nSuppGids > 0) {
+ free(lcc->pSuppGids);
+ }
+ free(lcc);
+ }
+}
+
+static Bool
+AuthorizedClient(ClientPtr client)
+{
+ if (!client || defeatAccessControl)
+ return TRUE;
+ return client->local ? Success : BadAccess;
+}
+
+/* Add a host to the access control list. This is the external interface
+ * called from the dispatcher */
+
+int
+AddHost (ClientPtr client,
+ int family,
+ unsigned length, /* of bytes in pAddr */
+ void *pAddr)
+{
+ int len;
+
+ if (!AuthorizedClient(client))
+ return(BadAccess);
+ switch (family) {
+ case FamilyLocalHost:
+ len = length;
+ LocalHostEnabled = TRUE;
+ break;
+#ifdef SECURE_RPC
+ case FamilyNetname:
+ len = length;
+ SecureRPCInit ();
+ break;
+#endif
+ case FamilyInternet:
+#if defined(IPv6) && defined(AF_INET6)
+ case FamilyInternet6:
+#endif
+ case FamilyChaos:
+ case FamilyServerInterpreted:
+ if ((len = CheckAddr (family, pAddr, length)) < 0)
+ {
+ client->errorValue = length;
+ return (BadValue);
+ }
+ break;
+ case FamilyLocal:
+ default:
+ client->errorValue = family;
+ return (BadValue);
+ }
+ if (NewHost (family, pAddr, len, FALSE))
+ return Success;
+ return BadAlloc;
+}
+
+Bool
+ForEachHostInFamily (int family,
+ Bool (*func)(
+ unsigned char * /* addr */,
+ short /* len */,
+ void * /* closure */),
+ void * closure)
+{
+ HOST *host;
+
+ for (host = validhosts; host; host = host->next)
+ if (family == host->family && func (host->addr, host->len, closure))
+ return TRUE;
+ return FALSE;
+}
+
+/* Add a host to the access control list. This is the internal interface
+ * called when starting or resetting the server */
+static Bool
+NewHost (int family,
+ void *addr,
+ int len,
+ int addingLocalHosts)
+{
+ register HOST *host;
+
+ for (host = validhosts; host; host = host->next)
+ {
+ if (addrEqual (family, addr, len, host))
+ return TRUE;
+ }
+ if (!addingLocalHosts) { /* Fix for XFree86 bug #156 */
+ for (host = selfhosts; host; host = host->next) {
+ if (addrEqual (family, addr, len, host)) {
+ host->requested = TRUE;
+ break;
+ }
+ }
+ }
+ MakeHost(host,len)
+ if (!host)
+ return FALSE;
+ host->family = family;
+ host->len = len;
+ acopy(addr, host->addr, len);
+ host->next = validhosts;
+ validhosts = host;
+ return TRUE;
+}
+
+/* Remove a host from the access control list */
+
+int
+RemoveHost (
+ ClientPtr client,
+ int family,
+ unsigned length, /* of bytes in pAddr */
+ void *pAddr)
+{
+ int len;
+ register HOST *host, **prev;
+
+ if (!AuthorizedClient(client))
+ return(BadAccess);
+ switch (family) {
+ case FamilyLocalHost:
+ len = length;
+ LocalHostEnabled = FALSE;
+ break;
+#ifdef SECURE_RPC
+ case FamilyNetname:
+ len = length;
+ break;
+#endif
+ case FamilyInternet:
+#if defined(IPv6) && defined(AF_INET6)
+ case FamilyInternet6:
+#endif
+ case FamilyChaos:
+ case FamilyServerInterpreted:
+ if ((len = CheckAddr (family, pAddr, length)) < 0)
+ {
+ client->errorValue = length;
+ return(BadValue);
+ }
+ break;
+ case FamilyLocal:
+ default:
+ client->errorValue = family;
+ return(BadValue);
+ }
+ for (prev = &validhosts;
+ (host = *prev) && (!addrEqual (family, pAddr, len, host));
+ prev = &host->next)
+ ;
+ if (host)
+ {
+ *prev = host->next;
+ FreeHost (host);
+ }
+ return (Success);
+}
+
+/* Get all hosts in the access control list */
+int
+GetHosts (
+ void * *data,
+ int *pnHosts,
+ int *pLen,
+ BOOL *pEnabled)
+{
+ int len;
+ register int n = 0;
+ register unsigned char *ptr;
+ register HOST *host;
+ int nHosts = 0;
+
+ *pEnabled = AccessEnabled ? EnableAccess : DisableAccess;
+ for (host = validhosts; host; host = host->next)
+ {
+ nHosts++;
+ n += (((host->len + 3) >> 2) << 2) + sizeof(xHostEntry);
+ /* Could check for INT_MAX, but in reality having more than 1mb of
+ hostnames in the access list is ridiculous */
+ if (n >= 1024*1024)
+ break;
+ }
+ if (n)
+ {
+ *data = ptr = (void *) malloc (n);
+ if (!ptr)
+ {
+ return(BadAlloc);
+ }
+ for (host = validhosts; host; host = host->next)
+ {
+ len = host->len;
+ if ((ptr + sizeof(xHostEntry) + len) > ((unsigned char *) *data + n))
+ break;
+ ((xHostEntry *)ptr)->family = host->family;
+ ((xHostEntry *)ptr)->length = len;
+ ptr += sizeof(xHostEntry);
+ acopy (host->addr, ptr, len);
+ ptr += ((len + 3) >> 2) << 2;
+ }
+ } else {
+ *data = NULL;
+ }
+ *pnHosts = nHosts;
+ *pLen = n;
+ return(Success);
+}
+
+/* Check for valid address family and length, and return address length. */
+
+/*ARGSUSED*/
+static int
+CheckAddr (
+ int family,
+ void * pAddr,
+ unsigned length)
+{
+ int len;
+
+ switch (family)
+ {
+#if defined(TCPCONN)
+ case FamilyInternet:
+ if (length == sizeof (struct in_addr))
+ len = length;
+ else
+ len = -1;
+ break;
+#if defined(IPv6) && defined(AF_INET6)
+ case FamilyInternet6:
+ if (length == sizeof (struct in6_addr))
+ len = length;
+ else
+ len = -1;
+ break;
+#endif
+#endif
+ case FamilyServerInterpreted:
+ len = siCheckAddr(pAddr, length);
+ break;
+ default:
+ len = -1;
+ }
+ return (len);
+}
+
+/* Check if a host is not in the access control list.
+ * Returns 1 if host is invalid, 0 if we've found it. */
+
+int
+InvalidHost (
+ register struct sockaddr *saddr,
+ int len,
+ ClientPtr client)
+{
+ int family;
+ void *addr = NULL;
+ register HOST *selfhost, *host;
+
+ if (!AccessEnabled) /* just let them in */
+ return(0);
+ family = ConvertAddr (saddr, &len, (void **)&addr);
+ if (family == -1)
+ return 1;
+ if (family == FamilyLocal)
+ {
+ if (!LocalHostEnabled)
+ {
+ /*
+ * check to see if any local address is enabled. This
+ * implicitly enables local connections.
+ */
+ for (selfhost = selfhosts; selfhost; selfhost=selfhost->next)
+ {
+ for (host = validhosts; host; host=host->next)
+ {
+ if (addrEqual (selfhost->family, selfhost->addr,
+ selfhost->len, host))
+ return 0;
+ }
+ }
+ } else
+ return 0;
+ }
+ for (host = validhosts; host; host = host->next)
+ {
+ if ((host->family == FamilyServerInterpreted)) {
+ if (siAddrMatch (family, addr, len, host, client)) {
+ return (0);
+ }
+ } else {
+ if (addr && addrEqual (family, addr, len, host))
+ return (0);
+ }
+
+ }
+ return (1);
+}
+
+static int
+ConvertAddr (
+ register struct sockaddr *saddr,
+ int *len,
+ void **addr)
+{
+ if (*len == 0)
+ return (FamilyLocal);
+ switch (saddr->sa_family)
+ {
+ case AF_UNSPEC:
+#if defined(UNIXCONN) || defined(LOCALCONN)
+ case AF_UNIX:
+#endif
+ return FamilyLocal;
+#if defined(TCPCONN)
+ case AF_INET:
+#ifdef WIN32
+ if (16777343 == *(long*)&((struct sockaddr_in *) saddr)->sin_addr)
+ return FamilyLocal;
+#endif
+ *len = sizeof (struct in_addr);
+ *addr = (void *) &(((struct sockaddr_in *) saddr)->sin_addr);
+ return FamilyInternet;
+#if defined(IPv6) && defined(AF_INET6)
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *) saddr;
+ if (IN6_IS_ADDR_V4MAPPED(&(saddr6->sin6_addr))) {
+ *len = sizeof (struct in_addr);
+ *addr = (void *) &(saddr6->sin6_addr.s6_addr[12]);
+ return FamilyInternet;
+ } else {
+ *len = sizeof (struct in6_addr);
+ *addr = (void *) &(saddr6->sin6_addr);
+ return FamilyInternet6;
+ }
+ }
+#endif
+#endif
+#ifdef CHAOSCONN
+ case AF_CHAOS:
+ {
+ not implemented
+ }
+ return FamilyChaos;
+#endif
+ default:
+ return -1;
+ }
+}
+
+int
+ChangeAccessControl(
+ ClientPtr client,
+ int fEnabled)
+{
+ if (!AuthorizedClient(client))
+ return BadAccess;
+ AccessEnabled = fEnabled;
+ return Success;
+}
+
+/* returns FALSE if xhost + in effect, else TRUE */
+int
+GetAccessControl(void)
+{
+ return AccessEnabled;
+}
+
+/*****************************************************************************
+ * FamilyServerInterpreted host entry implementation
+ *
+ * Supports an extensible system of host types which the server can interpret
+ * See the IPv6 extensions to the X11 protocol spec for the definition.
+ *
+ * Currently supported schemes:
+ *
+ * hostname - hostname as defined in IETF RFC 2396
+ * ipv6 - IPv6 literal address as defined in IETF RFC's 3513 and <TBD>
+ *
+ * See xc/doc/specs/SIAddresses for formal definitions of each type.
+ */
+
+/* These definitions and the siTypeAdd function could be exported in the
+ * future to enable loading additional host types, but that was not done for
+ * the initial implementation.
+ */
+typedef Bool (*siAddrMatchFunc)(int family, void * addr, int len,
+ const char *siAddr, int siAddrlen, ClientPtr client, void *siTypePriv);
+typedef int (*siCheckAddrFunc)(const char *addrString, int length,
+ void *siTypePriv);
+
+struct siType {
+ struct siType * next;
+ const char * typeName;
+ siAddrMatchFunc addrMatch;
+ siCheckAddrFunc checkAddr;
+ void * typePriv; /* Private data for type routines */
+};
+
+static struct siType *siTypeList;
+
+static int
+siTypeAdd(const char *typeName, siAddrMatchFunc addrMatch,
+ siCheckAddrFunc checkAddr, void *typePriv)
+{
+ struct siType *s, *p;
+
+ if ((typeName == NULL) || (addrMatch == NULL) || (checkAddr == NULL))
+ return BadValue;
+
+ for (s = siTypeList, p = NULL; s != NULL ; p = s, s = s->next) {
+ if (strcmp(typeName, s->typeName) == 0) {
+ s->addrMatch = addrMatch;
+ s->checkAddr = checkAddr;
+ s->typePriv = typePriv;
+ return Success;
+ }
+ }
+
+ s = (struct siType *) malloc(sizeof(struct siType));
+ if (s == NULL)
+ return BadAlloc;
+
+ if (p == NULL)
+ siTypeList = s;
+ else
+ p->next = s;
+
+ s->next = NULL;
+ s->typeName = typeName;
+ s->addrMatch = addrMatch;
+ s->checkAddr = checkAddr;
+ s->typePriv = typePriv;
+ return Success;
+}
+
+/* Checks to see if a host matches a server-interpreted host entry */
+static Bool
+siAddrMatch(int family, void * addr, int len, HOST *host, ClientPtr client)
+{
+ Bool matches = FALSE;
+ struct siType *s;
+ const char *valueString;
+ int addrlen;
+
+ valueString = (const char *) memchr(host->addr, '\0', host->len);
+ if (valueString != NULL) {
+ for (s = siTypeList; s != NULL ; s = s->next) {
+ if (strcmp((char *) host->addr, s->typeName) == 0) {
+ addrlen = host->len - (strlen((char *)host->addr) + 1);
+ matches = s->addrMatch(family, addr, len,
+ valueString + 1, addrlen, client, s->typePriv);
+ break;
+ }
+ }
+#ifdef FAMILY_SI_DEBUG
+ ErrorF(
+ "Xserver: siAddrMatch(): type = %s, value = %*.*s -- %s\n",
+ host->addr, addrlen, addrlen, valueString + 1,
+ (matches) ? "accepted" : "rejected");
+#endif
+ }
+ return matches;
+}
+
+static int
+siCheckAddr(const char *addrString, int length)
+{
+ const char *valueString;
+ int addrlen, typelen;
+ int len = -1;
+ struct siType *s;
+
+ /* Make sure there is a \0 byte inside the specified length
+ to separate the address type from the address value. */
+ valueString = (const char *) memchr(addrString, '\0', length);
+ if (valueString != NULL) {
+ /* Make sure the first string is a recognized address type,
+ * and the second string is a valid address of that type.
+ */
+ typelen = strlen(addrString) + 1;
+ addrlen = length - typelen;
+
+ for (s = siTypeList; s != NULL ; s = s->next) {
+ if (strcmp(addrString, s->typeName) == 0) {
+ len = s->checkAddr(valueString + 1, addrlen, s->typePriv);
+ if (len >= 0) {
+ len += typelen;
+ }
+ break;
+ }
+ }
+#ifdef FAMILY_SI_DEBUG
+ {
+ const char *resultMsg;
+
+ if (s == NULL) {
+ resultMsg = "type not registered";
+ } else {
+ if (len == -1)
+ resultMsg = "rejected";
+ else
+ resultMsg = "accepted";
+ }
+
+ ErrorF("Xserver: siCheckAddr(): type = %s, value = %*.*s, len = %d -- %s\n",
+ addrString, addrlen, addrlen, valueString + 1, len, resultMsg);
+ }
+#endif
+ }
+ return len;
+}
+
+
+/***
+ * Hostname server-interpreted host type
+ *
+ * Stored as hostname string, explicitly defined to be resolved ONLY
+ * at access check time, to allow for hosts with dynamic addresses
+ * but static hostnames, such as found in some DHCP & mobile setups.
+ *
+ * Hostname must conform to IETF RFC 2396 sec. 3.2.2, which defines it as:
+ * hostname = *( domainlabel "." ) toplabel [ "." ]
+ * domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
+ * toplabel = alpha | alpha *( alphanum | "-" ) alphanum
+ */
+
+#ifdef NI_MAXHOST
+# define SI_HOSTNAME_MAXLEN NI_MAXHOST
+#else
+# ifdef MAXHOSTNAMELEN
+# define SI_HOSTNAME_MAXLEN MAXHOSTNAMELEN
+# else
+# define SI_HOSTNAME_MAXLEN 256
+# endif
+#endif
+
+static Bool
+siHostnameAddrMatch(int family, void * addr, int len,
+ const char *siAddr, int siAddrLen, ClientPtr client, void *typePriv)
+{
+ Bool res = FALSE;
+
+/* Currently only supports checking against IPv4 & IPv6 connections, but
+ * support for other address families, such as DECnet, could be added if
+ * desired.
+ */
+#if defined(IPv6) && defined(AF_INET6)
+ if ((family == FamilyInternet) || (family == FamilyInternet6)) {
+ char hostname[SI_HOSTNAME_MAXLEN];
+ struct addrinfo *addresses;
+ struct addrinfo *a;
+ int f, hostaddrlen;
+ void * hostaddr = NULL;
+
+ if (siAddrLen >= sizeof(hostname))
+ return FALSE;
+
+ strncpy(hostname, siAddr, siAddrLen);
+ hostname[siAddrLen] = '\0';
+
+ if (getaddrinfo(hostname, NULL, NULL, &addresses) == 0) {
+ for (a = addresses ; a != NULL ; a = a->ai_next) {
+ hostaddrlen = a->ai_addrlen;
+ f = ConvertAddr(a->ai_addr,&hostaddrlen,&hostaddr);
+ if ((f == family) && (len == hostaddrlen) && hostaddr &&
+ (acmp (addr, hostaddr, len) == 0) ) {
+ res = TRUE;
+ break;
+ }
+ }
+ freeaddrinfo(addresses);
+ }
+ }
+#else /* IPv6 not supported, use gethostbyname instead for IPv4 */
+ if (family == FamilyInternet) {
+ register struct hostent *hp;
+#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
+ _Xgethostbynameparams hparams;
+#endif
+ char hostname[SI_HOSTNAME_MAXLEN];
+ int f, hostaddrlen;
+ void * hostaddr;
+ const char **addrlist;
+
+ if (siAddrLen >= sizeof(hostname))
+ return FALSE;
+
+ strncpy(hostname, siAddr, siAddrLen);
+ hostname[siAddrLen] = '\0';
+
+ if ((hp = _XGethostbyname(hostname, hparams)) != NULL) {
+#ifdef h_addr /* new 4.3bsd version of gethostent */
+ /* iterate over the addresses */
+ for (addrlist = hp->h_addr_list; *addrlist; addrlist++)
+#else
+ addrlist = &hp->h_addr;
+#endif
+ {
+ struct sockaddr_in sin;
+
+ sin.sin_family = hp->h_addrtype;
+ acopy ( *addrlist, &(sin.sin_addr), hp->h_length);
+ hostaddrlen = sizeof(sin);
+ f = ConvertAddr ((struct sockaddr *)&sin,
+ &hostaddrlen, &hostaddr);
+ if ((f == family) && (len == hostaddrlen) &&
+ (acmp (addr, hostaddr, len) == 0) ) {
+ res = TRUE;
+ break;
+ }
+ }
+ }
+ }
+#endif
+ return res;
+}
+
+
+static int
+siHostnameCheckAddr(const char *valueString, int length, void *typePriv)
+{
+ /* Check conformance of hostname to RFC 2396 sec. 3.2.2 definition.
+ * We do not use ctype functions here to avoid locale-specific
+ * character sets. Hostnames must be pure ASCII.
+ */
+ int len = length;
+ int i;
+ Bool dotAllowed = FALSE;
+ Bool dashAllowed = FALSE;
+
+ if ((length <= 0) || (length >= SI_HOSTNAME_MAXLEN)) {
+ len = -1;
+ } else {
+ for (i = 0; i < length; i++) {
+ char c = valueString[i];
+
+ if (c == 0x2E) { /* '.' */
+ if (dotAllowed == FALSE) {
+ len = -1;
+ break;
+ } else {
+ dotAllowed = FALSE;
+ dashAllowed = FALSE;
+ }
+ } else if (c == 0x2D) { /* '-' */
+ if (dashAllowed == FALSE) {
+ len = -1;
+ break;
+ } else {
+ dotAllowed = FALSE;
+ }
+ } else if (((c >= 0x30) && (c <= 0x3A)) /* 0-9 */ ||
+ ((c >= 0x61) && (c <= 0x7A)) /* a-z */ ||
+ ((c >= 0x41) && (c <= 0x5A)) /* A-Z */) {
+ dotAllowed = TRUE;
+ dashAllowed = TRUE;
+ } else { /* Invalid character */
+ len = -1;
+ break;
+ }
+ }
+ }
+ return len;
+}
+
+#if defined(IPv6) && defined(AF_INET6)
+/***
+ * "ipv6" server interpreted type
+ *
+ * Currently supports only IPv6 literal address as specified in IETF RFC 3513
+ *
+ * Once draft-ietf-ipv6-scoping-arch-00.txt becomes an RFC, support will be
+ * added for the scoped address format it specifies.
+ */
+
+/* Maximum length of an IPv6 address string - increase when adding support
+ * for scoped address qualifiers. Includes room for trailing NUL byte.
+ */
+#define SI_IPv6_MAXLEN INET6_ADDRSTRLEN
+
+static Bool
+siIPv6AddrMatch(int family, void * addr, int len,
+ const char *siAddr, int siAddrlen, ClientPtr client, void *typePriv)
+{
+ struct in6_addr addr6;
+ char addrbuf[SI_IPv6_MAXLEN];
+
+ if ((family != FamilyInternet6) || (len != sizeof(addr6)))
+ return FALSE;
+
+ memcpy(addrbuf, siAddr, siAddrlen);
+ addrbuf[siAddrlen] = '\0';
+
+ if (inet_pton(AF_INET6, addrbuf, &addr6) != 1) {
+ perror("inet_pton");
+ return FALSE;
+ }
+
+ if (memcmp(addr, &addr6, len) == 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+static int
+siIPv6CheckAddr(const char *addrString, int length, void *typePriv)
+{
+ int len;
+
+ /* Minimum length is 3 (smallest legal address is "::1") */
+ if (length < 3) {
+ /* Address is too short! */
+ len = -1;
+ } else if (length >= SI_IPv6_MAXLEN) {
+ /* Address is too long! */
+ len = -1;
+ } else {
+ /* Assume inet_pton is sufficient validation */
+ struct in6_addr addr6;
+ char addrbuf[SI_IPv6_MAXLEN];
+
+ memcpy(addrbuf, addrString, length);
+ addrbuf[length] = '\0';
+
+ if (inet_pton(AF_INET6, addrbuf, &addr6) != 1) {
+ perror("inet_pton");
+ len = -1;
+ } else {
+ len = length;
+ }
+ }
+ return len;
+}
+#endif /* IPv6 */
+
+#if !defined(NO_LOCAL_CLIENT_CRED)
+/***
+ * "localuser" & "localgroup" server interpreted types
+ *
+ * Allows local connections from a given local user or group
+ */
+
+#include <pwd.h>
+#include <grp.h>
+
+#define LOCAL_USER 1
+#define LOCAL_GROUP 2
+
+typedef struct {
+ int credType;
+} siLocalCredPrivRec, *siLocalCredPrivPtr;
+
+static siLocalCredPrivRec siLocalUserPriv = { LOCAL_USER };
+static siLocalCredPrivRec siLocalGroupPriv = { LOCAL_GROUP };
+
+static Bool
+siLocalCredGetId(const char *addr, int len, siLocalCredPrivPtr lcPriv, int *id)
+{
+ Bool parsedOK = FALSE;
+ char *addrbuf = malloc(len + 1);
+
+ if (addrbuf == NULL) {
+ return FALSE;
+ }
+
+ memcpy(addrbuf, addr, len);
+ addrbuf[len] = '\0';
+
+ if (addr[0] == '#') { /* numeric id */
+ char *cp;
+ errno = 0;
+ *id = strtol(addrbuf + 1, &cp, 0);
+ if ((errno == 0) && (cp != (addrbuf+1))) {
+ parsedOK = TRUE;
+ }
+ } else { /* non-numeric name */
+ if (lcPriv->credType == LOCAL_USER) {
+ struct passwd *pw = getpwnam(addrbuf);
+
+ if (pw != NULL) {
+ *id = (int) pw->pw_uid;
+ parsedOK = TRUE;
+ }
+ } else { /* group */
+ struct group *gr = getgrnam(addrbuf);
+
+ if (gr != NULL) {
+ *id = (int) gr->gr_gid;
+ parsedOK = TRUE;
+ }
+ }
+ }
+
+ free(addrbuf);
+ return parsedOK;
+}
+
+static Bool
+siLocalCredAddrMatch(int family, void * addr, int len,
+ const char *siAddr, int siAddrlen, ClientPtr client, void *typePriv)
+{
+ int siAddrId;
+ LocalClientCredRec *lcc;
+ siLocalCredPrivPtr lcPriv = (siLocalCredPrivPtr) typePriv;
+
+ if (GetLocalClientCreds(client, &lcc) == -1) {
+ return FALSE;
+ }
+
+#ifdef HAVE_GETZONEID /* Ensure process is in the same zone */
+ if ((lcc->fieldsSet & LCC_ZID_SET) && (lcc->zoneid != getzoneid())) {
+ FreeLocalClientCreds(lcc);
+ return FALSE;
+ }
+#endif
+
+ if (siLocalCredGetId(siAddr, siAddrlen, lcPriv, &siAddrId) == FALSE) {
+ FreeLocalClientCreds(lcc);
+ return FALSE;
+ }
+
+ if (lcPriv->credType == LOCAL_USER) {
+ if ((lcc->fieldsSet & LCC_UID_SET) && (lcc->euid == siAddrId)) {
+ FreeLocalClientCreds(lcc);
+ return TRUE;
+ }
+ } else {
+ if ((lcc->fieldsSet & LCC_GID_SET) && (lcc->egid == siAddrId)) {
+ FreeLocalClientCreds(lcc);
+ return TRUE;
+ }
+ if (lcc->pSuppGids != NULL) {
+ int i;
+
+ for (i = 0 ; i < lcc->nSuppGids; i++) {
+ if (lcc->pSuppGids[i] == siAddrId) {
+ FreeLocalClientCreds(lcc);
+ return TRUE;
+ }
+ }
+ }
+ }
+ FreeLocalClientCreds(lcc);
+ return FALSE;
+}
+
+static int
+siLocalCredCheckAddr(const char *addrString, int length, void *typePriv)
+{
+ int len = length;
+ int id;
+
+ if (siLocalCredGetId(addrString, length,
+ (siLocalCredPrivPtr)typePriv, &id) == FALSE) {
+ len = -1;
+ }
+ return len;
+}
+#endif /* localuser */
+
+static void
+siTypesInitialize(void)
+{
+ siTypeAdd("hostname", siHostnameAddrMatch, siHostnameCheckAddr, NULL);
+#if defined(IPv6) && defined(AF_INET6)
+ siTypeAdd("ipv6", siIPv6AddrMatch, siIPv6CheckAddr, NULL);
+#endif
+#if !defined(NO_LOCAL_CLIENT_CRED)
+ siTypeAdd("localuser", siLocalCredAddrMatch, siLocalCredCheckAddr,
+ &siLocalUserPriv);
+ siTypeAdd("localgroup", siLocalCredAddrMatch, siLocalCredCheckAddr,
+ &siLocalGroupPriv);
+#endif
+}
diff --git a/nx-X11/programs/Xserver/os/auth.c b/nx-X11/programs/Xserver/os/auth.c
new file mode 100644
index 000000000..84bc5c3c6
--- /dev/null
+++ b/nx-X11/programs/Xserver/os/auth.c
@@ -0,0 +1,602 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* nx-X11, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+
+Copyright 1988, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+
+/*
+ * authorization hooks for the server
+ * Author: Keith Packard, MIT X Consortium
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+# include <nx-X11/X.h>
+# include <nx-X11/Xauth.h>
+# include "misc.h"
+# include "osdep.h"
+# include "dixstruct.h"
+# include <sys/types.h>
+# include <sys/stat.h>
+#ifdef XCSECURITY
+#define _SECURITY_SERVER
+# include <nx-X11/extensions/security.h>
+#endif
+#ifdef WIN32
+#include <nx-X11/Xw32defs.h>
+#endif
+
+struct protocol {
+ unsigned short name_length;
+ char *name;
+ AuthAddCFunc Add; /* new authorization data */
+ AuthCheckFunc Check; /* verify client authorization data */
+ AuthRstCFunc Reset; /* delete all authorization data entries */
+ AuthToIDFunc ToID; /* convert cookie to ID */
+ AuthFromIDFunc FromID; /* convert ID to cookie */
+ AuthRemCFunc Remove; /* remove a specific cookie */
+#ifdef XCSECURITY
+ AuthGenCFunc Generate;
+#endif
+};
+
+static struct protocol protocols[] = {
+{ (unsigned short) 18, "MIT-MAGIC-COOKIE-1",
+ MitAddCookie, MitCheckCookie, MitResetCookie,
+ MitToID, MitFromID, MitRemoveCookie,
+#ifdef XCSECURITY
+ MitGenerateCookie
+#endif
+},
+#ifdef HASXDMAUTH
+{ (unsigned short) 19, "XDM-AUTHORIZATION-1",
+ XdmAddCookie, XdmCheckCookie, XdmResetCookie,
+ XdmToID, XdmFromID, XdmRemoveCookie,
+#ifdef XCSECURITY
+ NULL
+#endif
+},
+#endif
+#ifdef SECURE_RPC
+{ (unsigned short) 9, "SUN-DES-1",
+ SecureRPCAdd, SecureRPCCheck, SecureRPCReset,
+ SecureRPCToID, SecureRPCFromID,SecureRPCRemove,
+#ifdef XCSECURITY
+ NULL
+#endif
+},
+#endif
+#ifdef XCSECURITY
+{ (unsigned short) XSecurityAuthorizationNameLen,
+ XSecurityAuthorizationName,
+ NULL, AuthSecurityCheck, NULL,
+ NULL, NULL, NULL,
+ NULL
+},
+#endif
+};
+
+# define NUM_AUTHORIZATION (sizeof (protocols) /\
+ sizeof (struct protocol))
+
+/*
+ * Initialize all classes of authorization by reading the
+ * specified authorization file
+ */
+
+static char *authorization_file = (char *)NULL;
+
+static Bool ShouldLoadAuth = TRUE;
+
+void
+InitAuthorization (char *file_name)
+{
+#ifdef __sun
+ char * envBuffer;
+#endif
+ authorization_file = file_name;
+#ifdef NX_TRANS_AUTH
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "InitAuthorization: Going to propagate auth file '%s' to the environment.\n",
+ authorization_file);
+#endif
+#ifdef __sun
+ envBuffer = malloc(15+strlen(authorization_file));
+ sprintf(envBuffer,"NX_XAUTHORITY=%s",authorization_file);
+ putenv(envBuffer);
+#else
+ setenv("NX_XAUTHORITY", authorization_file, 1);
+#endif
+#endif
+
+}
+
+static int
+LoadAuthorization (void)
+{
+ FILE *f;
+ Xauth *auth;
+ int i;
+ int count = 0;
+
+ ShouldLoadAuth = FALSE;
+ if (!authorization_file)
+ return 0;
+
+#ifdef NX_TRANS_AUTH
+
+ /*
+ * We think that the way LoadAuthorization() is working is wrong.
+ * It doesn't reset the list of stored authorizations before reading
+ * the new cookies. Our take is that if a new auth file is to be
+ * read, the only cookies that are to be accepted are those that are
+ * in the new file, not those in the file -plus- those that have
+ * been in the file in the past. Furthermore, if the list can't be
+ * read or it is empty, it should assume that it ignores which co-
+ * okies are valid and thus it should disable any access. Your mile-
+ * age can vary. A less draconian approach could be to leave the old
+ * cookies if the file can't be read and remove them only if the
+ * file is empty.
+ *
+ * Adding the cookies without removing the old values for the same
+ * protocol has an important implication. If an user shares the co-
+ * okie with somebody and later wants to revoke the access to the
+ * display, changing the cookie will not work. This is especially
+ * important with NX. For security reasons, after reconnecting the
+ * session to a different display, it is advisable to generate a
+ * new set of cookies, but doing that it is useless with the current
+ * code, as the old cookies are going to be still accepted. On the
+ * same topic, consider that once an user has got access to the X
+ * server, he/she can freely enable host authentication from any
+ * host, so the safe behaviour should be to reset the host based
+ * authenthication at least at reconnection, and keep as valid only
+ * the cookies that are actually in the file. This behaviour would
+ * surely break many applications, among them a SSH connection run
+ * inside a NX session, as ssh -X reads the cookie for the display
+ * only at session startup and does not read the cookies again
+ * when the auth file is changed.
+ *
+ * Another bug (or feature, depending on how you want to consider
+ * it) is that if the authority file contains entries for different
+ * displays (as it is the norm when the authority file is the default
+ * .Xauthority in the user's home), the server will match -any- of
+ * the cookies, even cookies that are not for its own display. This
+ * means that you have be careful when passing an authority file to
+ * nxagent or Xnest and maybe keep separate files for letting nxagent
+ * find the cookie to be used to connect to the remote display and
+ * for letting it find what cookies to accept. If the file is the
+ * same, clients will be able to connect to nxagent with both the
+ * cookies.
+ */
+
+#ifdef NX_TRANS_AUTH_RESET
+
+ #ifdef NX_TRANS_TEST
+ fprintf(stderr, "LoadAuthorization: Resetting authorization info.\n");
+ #endif
+
+ for (i = 0; i < NUM_AUTHORIZATION; i++) {
+ if (protocols[i].Reset) {
+ (*protocols[i].Reset) ();
+ }
+ }
+
+#endif
+
+#endif /* #ifdef NX_TRANS_AUTH */
+
+ f = Fopen (authorization_file, "r");
+ if (!f)
+ return -1;
+
+ while ((auth = XauReadAuth (f)) != 0) {
+ for (i = 0; i < NUM_AUTHORIZATION; i++) {
+ if (protocols[i].name_length == auth->name_length &&
+ memcmp (protocols[i].name, auth->name, (int) auth->name_length) == 0 &&
+ protocols[i].Add)
+ {
+#ifdef NX_TRANS_AUTH
+
+ #ifdef NX_TRANS_TEST
+ fprintf(stderr, "LoadAuthorization: Adding new record from file [%s].\n",
+ authorization_file);
+ #endif
+
+#endif
+ ++count;
+ (*protocols[i].Add) (auth->data_length, auth->data,
+ FakeClientID(0));
+ }
+ }
+ XauDisposeAuth (auth);
+ }
+
+#ifdef NX_TRANS_AUTH
+
+ if (count == 0)
+ {
+ fprintf(stderr, "Warning: No authorization record could be read from file '%s'.\n",
+ authorization_file);
+
+ fprintf(stderr, "Warning: Please, create a valid authorization cookie using the command\n"
+ "Warning: 'xauth -f %s add <display> MIT-MAGIC-COOKIE-1 <cookie>'.\n",
+ authorization_file);
+ }
+
+#endif
+
+#ifdef NX_TRANS_AUTH
+ if (Fclose (f) != 0)
+ {
+ /*
+ * If the Fclose() fails, for example because of a signal,
+ * it's advisable to return the number of protocols read,
+ * if any, or otherwise the server would believe that no
+ * cookie is valid and eventually fall back to host based
+ * authentication. Note anyway that the new code in Check-
+ * Authorization() doesn't care the return value and gives
+ * a chance to the function to check the file at the next
+ * connection.
+ */
+
+ if (count > 0)
+ {
+ return count;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+#else
+ Fclose (f);
+#endif
+ return count;
+}
+
+#ifdef XDMCP
+/*
+ * XdmcpInit calls this function to discover all authorization
+ * schemes supported by the display
+ */
+void
+RegisterAuthorizations (void)
+{
+ int i;
+
+ for (i = 0; i < NUM_AUTHORIZATION; i++)
+ XdmcpRegisterAuthorization (protocols[i].name,
+ (int)protocols[i].name_length);
+}
+#endif
+
+XID
+CheckAuthorization (
+ unsigned int name_length,
+ char *name,
+ unsigned int data_length,
+ char *data,
+ ClientPtr client,
+ char **reason) /* failure message. NULL for default msg */
+{
+ int i;
+ struct stat buf;
+ static time_t lastmod = 0;
+
+ #ifndef NX_TRANS_AUTH
+ static Bool loaded = FALSE;
+ #endif
+
+ if (!authorization_file || stat(authorization_file, &buf))
+ {
+ if (lastmod != 0) {
+ lastmod = 0;
+ ShouldLoadAuth = TRUE; /* stat lost, so force reload */
+ }
+ }
+ else if (buf.st_mtime > lastmod)
+ {
+ lastmod = buf.st_mtime;
+ ShouldLoadAuth = TRUE;
+ }
+ if (ShouldLoadAuth)
+ {
+ int loadauth = LoadAuthorization();
+
+ /*
+ * If the authorization file has at least one entry for this server,
+ * disable local host access. (loadauth > 0)
+ *
+ * If there are zero entries (either initially or when the
+ * authorization file is later reloaded), or if a valid
+ * authorization file was never loaded, enable local host access.
+ * (loadauth == 0 || !loaded)
+ *
+ * If the authorization file was loaded initially (with valid
+ * entries for this server), and reloading it later fails, don't
+ * change anything. (loadauth == -1 && loaded)
+ */
+
+#ifdef NX_TRANS_AUTH
+
+ /*
+ * The implementation of CheckAuthorization() was changed. The way
+ * the auth file was handled previously was questionable and could
+ * open the way to a vast array of security problems. There might be
+ * ways for an attacker to prevent the server from reading the file
+ * and it was enough for the server to fail reading the file once
+ * (because of a not blocked signal, for example) to leave the dis-
+ * play open to all the users running a session on the same terminal
+ * server.
+ *
+ * In NX we want to have only two cases: either we have to check an
+ * authorization file or we don't. In the first case we need to do our
+ * best to read the file at any new client access and never fall back
+ * to host based authentication. Falling back to local host access has
+ * no way back, as it will always take precedence over the auth cookie
+ * (unless the user explicitly disables, one by one, all the rules
+ * allowing local access, if and only if he/she becomes aware of the
+ * problem). In the second case we assume that user doesn't care secu-
+ * rity and so allow unrestricted access from the local machine.
+ */
+
+ #ifdef NX_TRANS_TEST
+ fprintf(stderr, "CheckAuthorization: Going to set authorization with loadauth [%d].\n",
+ loadauth);
+ #endif
+
+ if (authorization_file)
+ {
+ #ifdef NX_TRANS_TEST
+ fprintf(stderr, "CheckAuthorization: Disabling local host access.\n");
+ #endif
+
+ DisableLocalHost();
+ }
+ else
+ {
+ /*
+ * Enable host-based authentication only if
+ * the authorization file was not specified
+ * either on the command line or in the env-
+ * ironment.
+ */
+
+ #ifdef NX_TRANS_TEST
+ fprintf(stderr, "CheckAuthorization: Enabling local host access.\n");
+ #endif
+
+ EnableLocalHost();
+ }
+
+ /*
+ * Avoid the 'unused variable' warning.
+ */
+
+ loadauth = loadauth;
+
+#else /* #ifdef NX_TRANS_AUTH */
+
+ if (loadauth > 0)
+ {
+ DisableLocalHost(); /* got at least one */
+ loaded = TRUE;
+ }
+ else if (loadauth == 0 || !loaded)
+ EnableLocalHost ();
+
+#endif /* #ifdef NX_TRANS_AUTH */
+ }
+ if (name_length) {
+ for (i = 0; i < NUM_AUTHORIZATION; i++) {
+ if (protocols[i].name_length == name_length &&
+ memcmp (protocols[i].name, name, (int) name_length) == 0)
+ {
+ return (*protocols[i].Check) (data_length, data, client, reason);
+ }
+ *reason = "Protocol not supported by server\n";
+ }
+ } else *reason = "No protocol specified\n";
+ return (XID) ~0L;
+}
+
+void
+ResetAuthorization (void)
+{
+ int i;
+
+ for (i = 0; i < NUM_AUTHORIZATION; i++)
+ if (protocols[i].Reset)
+ (*protocols[i].Reset)();
+ ShouldLoadAuth = TRUE;
+}
+
+XID
+AuthorizationToID (
+ unsigned short name_length,
+ char *name,
+ unsigned short data_length,
+ char *data)
+{
+ int i;
+
+ for (i = 0; i < NUM_AUTHORIZATION; i++) {
+ if (protocols[i].name_length == name_length &&
+ memcmp (protocols[i].name, name, (int) name_length) == 0 &&
+ protocols[i].ToID)
+ {
+ return (*protocols[i].ToID) (data_length, data);
+ }
+ }
+ return (XID) ~0L;
+}
+
+int
+AuthorizationFromID (
+ XID id,
+ unsigned short *name_lenp,
+ char **namep,
+ unsigned short *data_lenp,
+ char **datap)
+{
+ int i;
+
+ for (i = 0; i < NUM_AUTHORIZATION; i++) {
+ if (protocols[i].FromID &&
+ (*protocols[i].FromID) (id, data_lenp, datap)) {
+ *name_lenp = protocols[i].name_length;
+ *namep = protocols[i].name;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int
+RemoveAuthorization (
+ unsigned short name_length,
+ char *name,
+ unsigned short data_length,
+ char *data)
+{
+ int i;
+
+ for (i = 0; i < NUM_AUTHORIZATION; i++) {
+ if (protocols[i].name_length == name_length &&
+ memcmp (protocols[i].name, name, (int) name_length) == 0 &&
+ protocols[i].Remove)
+ {
+ return (*protocols[i].Remove) (data_length, data);
+ }
+ }
+ return 0;
+}
+
+int
+AddAuthorization (unsigned name_length, char *name, unsigned data_length, char *data)
+{
+ int i;
+
+ for (i = 0; i < NUM_AUTHORIZATION; i++) {
+ if (protocols[i].name_length == name_length &&
+ memcmp (protocols[i].name, name, (int) name_length) == 0 &&
+ protocols[i].Add)
+ {
+ return (*protocols[i].Add) (data_length, data, FakeClientID(0));
+ }
+ }
+ return 0;
+}
+
+#ifdef XCSECURITY
+
+XID
+GenerateAuthorization(
+ unsigned name_length,
+ char *name,
+ unsigned data_length,
+ char *data,
+ unsigned *data_length_return,
+ char **data_return)
+{
+ int i;
+
+ for (i = 0; i < NUM_AUTHORIZATION; i++) {
+ if (protocols[i].name_length == name_length &&
+ memcmp (protocols[i].name, name, (int) name_length) == 0 &&
+ protocols[i].Generate)
+ {
+ return (*protocols[i].Generate) (data_length, data,
+ FakeClientID(0), data_length_return, data_return);
+ }
+ }
+ return -1;
+}
+
+/* A random number generator that is more unpredictable
+ than that shipped with some systems.
+ This code is taken from the C standard. */
+
+static unsigned long int next = 1;
+
+static int
+xdm_rand(void)
+{
+ next = next * 1103515245 + 12345;
+ return (unsigned int)(next/65536) % 32768;
+}
+
+static void
+xdm_srand(unsigned int seed)
+{
+ next = seed;
+}
+
+void
+GenerateRandomData (int len, char *buf)
+{
+ static int seed;
+ int value;
+ int i;
+
+ seed += GetTimeInMillis();
+ xdm_srand (seed);
+ for (i = 0; i < len; i++)
+ {
+ value = xdm_rand ();
+ buf[i] ^= (value & 0xff00) >> 8;
+ }
+
+ /* XXX add getrusage, popen("ps -ale") */
+}
+
+#endif /* XCSECURITY */
diff --git a/nx-X11/programs/Xserver/os/client.c b/nx-X11/programs/Xserver/os/client.c
new file mode 100644
index 000000000..ef5e3935d
--- /dev/null
+++ b/nx-X11/programs/Xserver/os/client.c
@@ -0,0 +1,397 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All
+ * rights reserved.
+ * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/**
+ * @file
+ *
+ * This file contains functionality for identifying clients by various
+ * means. The primary purpose of identification is to simply aid in
+ * finding out which clients are using X server and how they are using
+ * it. For example, it's often necessary to monitor what requests
+ * clients are executing (to spot bad behaviour) and how they are
+ * allocating resources in X server (to spot excessive resource
+ * usage).
+ *
+ * This framework automatically allocates information, that can be
+ * used for client identification, when a client connects to the
+ * server. The information is freed when the client disconnects. The
+ * allocated information is just a collection of various IDs, such as
+ * PID and process name for local clients, that are likely to be
+ * useful in analyzing X server usage.
+ *
+ * Users of the framework can query ID information about clients at
+ * any time. To avoid repeated polling of IDs the users can also
+ * subscribe for notifications about the availability of ID
+ * information. IDs have been allocated before ClientStateCallback is
+ * called with ClientStateInitial state. Similarly the IDs will be
+ * released after ClientStateCallback is called with ClientStateGone
+ * state.
+ *
+ * Author: Rami Ylimäki <rami.ylimaki@vincit.fi>
+ */
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "client.h"
+#include "os.h"
+#include "dixstruct.h"
+
+#ifdef __sun
+#include <errno.h>
+#include <procfs.h>
+#endif
+
+#ifdef __OpenBSD__
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/types.h>
+
+#include <kvm.h>
+#include <limits.h>
+#endif
+
+/**
+ * Try to determine a PID for a client from its connection
+ * information. This should be called only once when new client has
+ * connected, use GetClientPid to determine the PID at other times.
+ *
+ * @param[in] client Connection linked to some process.
+ *
+ * @return PID of the client. Error (-1) if PID can't be determined
+ * for the client.
+ *
+ * @see GetClientPid
+ */
+pid_t
+DetermineClientPid(struct _Client * client)
+{
+ LocalClientCredRec *lcc = NULL;
+ pid_t pid = -1;
+
+ if (client == NullClient)
+ return pid;
+
+ if (client == serverClient)
+ return getpid();
+
+ if (GetLocalClientCreds(client, &lcc) != -1) {
+ if (lcc->fieldsSet & LCC_PID_SET)
+ pid = lcc->pid;
+ FreeLocalClientCreds(lcc);
+ }
+
+ return pid;
+}
+
+/**
+ * Try to determine a command line string for a client based on its
+ * PID. Note that mapping PID to a command hasn't been implemented for
+ * some operating systems. This should be called only once when a new
+ * client has connected, use GetClientCmdName/Args to determine the
+ * string at other times.
+ *
+ * @param[in] pid Process ID of a client.
+
+ * @param[out] cmdname Client process name without arguments. You must
+ * release this by calling free. On error NULL is
+ * returned. Pass NULL if you aren't interested in
+ * this value.
+ * @param[out] cmdargs Arguments to client process. Useful for
+ * identifying a client that is executed from a
+ * launcher program. You must release this by
+ * calling free. On error NULL is returned. Pass
+ * NULL if you aren't interested in this value.
+ *
+ * @see GetClientCmdName/Args
+ */
+void
+DetermineClientCmd(pid_t pid, const char **cmdname, const char **cmdargs)
+{
+ char path[PATH_MAX + 1];
+ int totsize = 0;
+ int fd = 0;
+
+ if (cmdname)
+ *cmdname = NULL;
+ if (cmdargs)
+ *cmdargs = NULL;
+
+ if (pid == -1)
+ return;
+
+#ifdef __sun /* Solaris */
+ /* Solaris does not support /proc/pid/cmdline, but makes information
+ * similar to what ps shows available in a binary structure in the
+ * /proc/pid/psinfo file. */
+ if (snprintf(path, sizeof(path), "/proc/%d/psinfo", pid) < 0)
+ return;
+ fd = open(path, O_RDONLY);
+ if (fd < 0) {
+ ErrorF("Failed to open %s: %s\n", path, strerror(errno));
+ return;
+ }
+ else {
+ psinfo_t psinfo = { 0 };
+ char *sp;
+
+ totsize = read(fd, &psinfo, sizeof(psinfo_t));
+ close(fd);
+ if (totsize <= 0)
+ return;
+
+ /* pr_psargs is the first PRARGSZ (80) characters of the command
+ * line string - assume up to the first space is the command name,
+ * since it's not delimited. While there is also pr_fname, that's
+ * more limited, giving only the first 16 chars of the basename of
+ * the file that was exec'ed, thus cutting off many long gnome
+ * command names, or returning "isapython2.6" for all python scripts.
+ */
+ psinfo.pr_psargs[PRARGSZ - 1] = '\0';
+ sp = strchr(psinfo.pr_psargs, ' ');
+ if (sp)
+ *sp++ = '\0';
+
+ if (cmdname)
+ *cmdname = strdup(psinfo.pr_psargs);
+
+ if (cmdargs && sp)
+ *cmdargs = strdup(sp);
+ }
+#elif defined(__OpenBSD__)
+ /* on OpenBSD use kvm_getargv() */
+ {
+ kvm_t *kd;
+ char errbuf[_POSIX2_LINE_MAX];
+ char **argv;
+ struct kinfo_proc *kp;
+ size_t len = 0;
+ int i, n;
+
+ kd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, errbuf);
+ if (kd == NULL)
+ return;
+ kp = kvm_getprocs(kd, KERN_PROC_PID, pid, sizeof(struct kinfo_proc),
+ &n);
+ if (n != 1)
+ return;
+ argv = kvm_getargv(kd, kp, 0);
+ *cmdname = strdup(argv[0]);
+ i = 1;
+ while (argv[i] != NULL) {
+ len += strlen(argv[i]) + 1;
+ i++;
+ }
+ *cmdargs = calloc(1, len);
+ i = 1;
+ while (argv[i] != NULL) {
+ strlcat(*cmdargs, argv[i], len);
+ strlcat(*cmdargs, " ", len);
+ i++;
+ }
+ kvm_close(kd);
+ }
+#else /* Linux using /proc/pid/cmdline */
+
+ /* Check if /proc/pid/cmdline exists. It's not supported on all
+ * operating systems. */
+ if (snprintf(path, sizeof(path), "/proc/%d/cmdline", pid) < 0)
+ return;
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ return;
+
+ /* Read the contents of /proc/pid/cmdline. It should contain the
+ * process name and arguments. */
+ totsize = read(fd, path, sizeof(path));
+ close(fd);
+ if (totsize <= 0)
+ return;
+ path[totsize - 1] = '\0';
+
+ /* Contruct the process name without arguments. */
+ if (cmdname) {
+ *cmdname = strdup(path);
+ }
+
+ /* Construct the arguments for client process. */
+ if (cmdargs) {
+ int cmdsize = strlen(path) + 1;
+ int argsize = totsize - cmdsize;
+ char *args = NULL;
+
+ if (argsize > 0)
+ args = malloc(argsize);
+ if (args) {
+ int i = 0;
+
+ for (i = 0; i < (argsize - 1); ++i) {
+ const char c = path[cmdsize + i];
+
+ args[i] = (c == '\0') ? ' ' : c;
+ }
+ args[argsize - 1] = '\0';
+ *cmdargs = args;
+ }
+ }
+#endif
+}
+
+/**
+ * Called when a new client connects. Allocates client ID information.
+ *
+ * @param[in] client Recently connected client.
+ */
+void
+ReserveClientIds(struct _Client *client)
+{
+#ifdef CLIENTIDS
+ if (client == NullClient)
+ return;
+
+ assert(!client->clientIds);
+ client->clientIds = calloc(1, sizeof(ClientIdRec));
+ if (!client->clientIds)
+ return;
+
+ client->clientIds->pid = DetermineClientPid(client);
+ if (client->clientIds->pid != -1)
+ DetermineClientCmd(client->clientIds->pid, &client->clientIds->cmdname,
+ &client->clientIds->cmdargs);
+
+ DebugF("client(%lx): Reserved pid(%d).\n",
+ (unsigned long) client->clientAsMask, client->clientIds->pid);
+ DebugF("client(%lx): Reserved cmdname(%s) and cmdargs(%s).\n",
+ (unsigned long) client->clientAsMask,
+ client->clientIds->cmdname ? client->clientIds->cmdname : "NULL",
+ client->clientIds->cmdargs ? client->clientIds->cmdargs : "NULL");
+#endif /* CLIENTIDS */
+}
+
+/**
+ * Called when an existing client disconnects. Frees client ID
+ * information.
+ *
+ * @param[in] client Recently disconnected client.
+ */
+void
+ReleaseClientIds(struct _Client *client)
+{
+#ifdef CLIENTIDS
+ if (client == NullClient)
+ return;
+
+ if (!client->clientIds)
+ return;
+
+ DebugF("client(%lx): Released pid(%d).\n",
+ (unsigned long) client->clientAsMask, client->clientIds->pid);
+ DebugF("client(%lx): Released cmdline(%s) and cmdargs(%s).\n",
+ (unsigned long) client->clientAsMask,
+ client->clientIds->cmdname ? client->clientIds->cmdname : "NULL",
+ client->clientIds->cmdargs ? client->clientIds->cmdargs : "NULL");
+
+ free((void *) client->clientIds->cmdname); /* const char * */
+ free((void *) client->clientIds->cmdargs); /* const char * */
+ free(client->clientIds);
+ client->clientIds = NULL;
+#endif /* CLIENTIDS */
+}
+
+/**
+ * Get cached PID of a client.
+ *
+ * param[in] client Client whose PID has been already cached.
+ *
+ * @return Cached client PID. Error (-1) if called:
+ * - before ClientStateInitial client state notification
+ * - after ClientStateGone client state notification
+ * - for remote clients
+ *
+ * @see DetermineClientPid
+ */
+pid_t
+GetClientPid(struct _Client *client)
+{
+ if (client == NullClient)
+ return -1;
+
+ if (!client->clientIds)
+ return -1;
+
+ return client->clientIds->pid;
+}
+
+/**
+ * Get cached command name string of a client.
+ *
+ * param[in] client Client whose command line string has been already
+ * cached.
+ *
+ * @return Cached client command name. Error (NULL) if called:
+ * - before ClientStateInitial client state notification
+ * - after ClientStateGone client state notification
+ * - for remote clients
+ * - on OS that doesn't support mapping of PID to command line
+ *
+ * @see DetermineClientCmd
+ */
+const char *
+GetClientCmdName(struct _Client *client)
+{
+ if (client == NullClient)
+ return NULL;
+
+ if (!client->clientIds)
+ return NULL;
+
+ return client->clientIds->cmdname;
+}
+
+/**
+ * Get cached command arguments string of a client.
+ *
+ * param[in] client Client whose command line string has been already
+ * cached.
+ *
+ * @return Cached client command arguments. Error (NULL) if called:
+ * - before ClientStateInitial client state notification
+ * - after ClientStateGone client state notification
+ * - for remote clients
+ * - on OS that doesn't support mapping of PID to command line
+ *
+ * @see DetermineClientCmd
+ */
+const char *
+GetClientCmdArgs(struct _Client *client)
+{
+ if (client == NullClient)
+ return NULL;
+
+ if (!client->clientIds)
+ return NULL;
+
+ return client->clientIds->cmdargs;
+}
diff --git a/nx-X11/programs/Xserver/os/connection.c b/nx-X11/programs/Xserver/os/connection.c
new file mode 100644
index 000000000..c5ebeea1e
--- /dev/null
+++ b/nx-X11/programs/Xserver/os/connection.c
@@ -0,0 +1,1377 @@
+/***********************************************************
+
+Copyright 1987, 1989, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+/*****************************************************************
+ * Stuff to create connections --- OS dependent
+ *
+ * EstablishNewConnections, CreateWellKnownSockets, ResetWellKnownSockets,
+ * CloseDownConnection, CheckConnections,
+ * OnlyListToOneClient,
+ * ListenToAllClients,
+ *
+ * (WaitForSomething is in its own file)
+ *
+ * In this implementation, a client socket table is not kept.
+ * Instead, what would be the index into the table is just the
+ * file descriptor of the socket. This won't work for if the
+ * socket ids aren't small nums (0 - 2^8)
+ *
+ *****************************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifdef WIN32
+#include <nx-X11/Xwinsock.h>
+#endif
+#include <nx-X11/X.h>
+#include <nx-X11/Xproto.h>
+#define XSERV_t
+#define TRANS_SERVER
+#define TRANS_REOPEN
+#include <nx-X11/Xtrans/Xtrans.h>
+#include <nx-X11/Xtrans/Xtransint.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#ifndef WIN32
+#include <sys/socket.h>
+
+#if defined(TCPCONN)
+# include <netinet/in.h>
+# include <arpa/inet.h>
+
+/* FIXME: correct indentation levels after ancient platform support clean-up */
+
+# 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 /* WIN32 */
+#include "misc.h"
+#include "osdep.h"
+#include <nx-X11/Xpoll.h>
+#include "opaque.h"
+#include "dixstruct.h"
+#include "list.h"
+#ifdef XCSECURITY
+#define _SECURITY_SERVER
+#include <nx-X11/extensions/security.h>
+#endif
+
+#ifdef X_NOT_POSIX
+#define Pid_t int
+#else
+#define Pid_t pid_t
+#endif
+
+int lastfdesc; /* maximum file descriptor */
+
+fd_set NotifyReadFds; /* mask for other file descriptors */
+fd_set NotifyWriteFds; /* mask for other write file descriptors */
+fd_set AllSockets; /* select on this */
+fd_set AllClients; /* available clients */
+fd_set LastSelectMask; /* mask returned from last select call */
+fd_set LastSelectWriteMask; /* mask returned from last select call */
+fd_set ClientsWithInput; /* clients with FULL requests in buffer */
+fd_set ClientsWriteBlocked; /* clients who cannot receive output */
+fd_set OutputPending; /* clients with reply/event data ready to go */
+int MaxClients = 0;
+int NumNotifyWriteFd; /* Number of NotifyFd members with write set */
+Bool NewOutputPending; /* not yet attempted to write some new output */
+Bool AnyWritesPending; /* true if some client blocked on write or NotifyFd with write */
+Bool NoListenAll; /* Don't establish any listening sockets */
+Bool RunFromSmartParent; /* send SIGUSR1 to parent process */
+static char dynamic_display[7]; /* display name */
+Bool PartialNetwork; /* continue even if unable to bind all addrs */
+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;
+
+static void
+QueueNewConnections(int curconn, int ready, void *data);
+
+#if !defined(WIN32)
+int *ConnectionTranslation = NULL;
+#else
+/*
+ * On NT fds are not between 0 and MAXSOCKS, they are unrelated, and there is
+ * not even a known maximum value, so use something quite arbitrary for now.
+ * Do storage is a hash table of size 256. Collisions are handled in a linked
+ * list.
+ */
+
+#undef MAXSOCKS
+#define MAXSOCKS 500
+#undef MAXSELECT
+#define MAXSELECT 500
+#define MAXFD 500
+
+struct _ct_node {
+ struct _ct_node *next;
+ int key;
+ int value;
+};
+
+struct _ct_node *ct_head[256];
+
+void InitConnectionTranslation(void)
+{
+ bzero(ct_head, 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) /* remove entry */
+ {
+ 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 = (struct _ct_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
+
+XtransConnInfo *ListenTransConns = NULL;
+int *ListenTransFds = NULL;
+int ListenTransCount;
+
+static void ErrorConnMax(XtransConnInfo /* trans_conn */);
+
+static
+void CloseDownFileDescriptor(
+ OsCommPtr /*oc*/
+);
+
+
+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);
+}
+
+/* Set MaxClients and lastfdesc, and allocate ConnectionTranslation */
+
+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 /* __CYGWIN__ */
+
+ /* This is the fallback */
+ 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)
+ ConnectionTranslation = (int *)xnfalloc(sizeof(int)*(lastfdesc + 1));
+#else
+ InitConnectionTranslation();
+#endif
+}
+
+/*
+ * If SIGUSR1 was set to SIG_IGN when the server started, assume that either
+ *
+ * a- The parent process is ignoring SIGUSR1
+ *
+ * or
+ *
+ * b- The parent process is expecting a SIGUSR1
+ * when the server is ready to accept connections
+ *
+ * In the first case, the signal will be harmless, in the second case,
+ * the signal will be quite useful.
+ */
+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 ();
+#ifdef __UNIXOS2__
+ /*
+ * fg030505: under OS/2, xinit is not the parent process but
+ * the "grant parent" process of the server because execvpe()
+ * presents us an additional process number;
+ * GetPPID(pid) is part of libemxfix
+ */
+ ParentProcess = GetPPID (ParentProcess);
+#endif /* __UNIXOS2__ */
+#endif
+}
+
+void
+NotifyParentProcess(void)
+{
+#if !defined(WIN32)
+ if (displayfd >= 0) {
+#ifdef NXAGENT_SERVER
+ if (displayfd == STDERR_FILENO)
+ {
+ const char *msg = "Auto-detected display number is: DISPLAY=:";
+ if (write(displayfd, msg, strlen(msg)) != strlen(msg))
+ FatalError("Cannot write display number to fd %d\n", displayfd);
+ }
+#endif
+ if (write(displayfd, display, strlen(display)) != strlen(display))
+ FatalError("Cannot write display number to fd %d\n", displayfd);
+ if (write(displayfd, "\n", 1) != 1)
+ FatalError("Cannot write display number to fd %d\n", displayfd);
+ close(displayfd);
+ displayfd = -1;
+ }
+ if (RunFromSmartParent) {
+ if (ParentProcess > 1) {
+ kill (ParentProcess, SIGUSR1);
+ }
+ }
+#endif
+}
+
+static Bool
+TryCreateSocket(int num, int *partial)
+{
+ char port[20];
+
+ snprintf(port, sizeof(port), "%d", num);
+
+ return (_XSERVTransMakeAllCOTSServerListeners(port, partial,
+ &ListenTransCount,
+ &ListenTransConns) >= 0);
+}
+
+/*****************
+ * CreateWellKnownSockets
+ * At initialization, create the sockets to listen on for new clients.
+ *****************/
+
+void
+CreateWellKnownSockets(void)
+{
+ int i;
+ int partial;
+
+ 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
+
+ /* display is initialized to "0" by main(). It is then set to the display
+ * number if specified on the command line. */
+ if (NoListenAll) {
+ ListenTransCount = 0;
+ }
+#ifndef NXAGENT_SERVER
+ else if ((displayfd < 0) || explicit_display) {
+#else
+ else if (displayfd < 0) {
+#endif /* ! NXAGENT_SERVER */
+ if (TryCreateSocket(atoi(display), &partial) &&
+ ListenTransCount >= 1)
+ if (!PartialNetwork && partial)
+ FatalError ("Failed to establish all listening sockets");
+ }
+ else { /* -displayfd and no explicit display number */
+ Bool found = 0;
+ int i_offset = 0;
+#ifdef NXAGENT_SERVER
+ if (explicit_display)
+ i_offset = atoi(display);
+#endif /* NXAGENT_SERVER */
+ for (i = i_offset; i < 65536 - X_TCP_PORT; i++) {
+ if (TryCreateSocket(i, &partial) && !partial) {
+ found = 1;
+ break;
+ }
+ else
+ CloseWellKnownConnections();
+ }
+ if (!found)
+ FatalError("Failed to find a socket to listen on");
+ snprintf(dynamic_display, sizeof(dynamic_display), "%d", i);
+ display = dynamic_display;
+ LogSetDisplay();
+ }
+
+ ListenTransFds = malloc(ListenTransCount * sizeof (int));
+
+ for (i = 0; i < ListenTransCount; i++) {
+ int fd = _XSERVTransGetConnectionNumber(ListenTransConns[i]);
+
+ ListenTransFds[i] = fd;
+ SetNotifyFd(fd, QueueNewConnections, X_NOTIFY_READ, NULL);
+
+ if (!_XSERVTransIsLocal(ListenTransConns[i]))
+ DefineSelf (fd);
+ }
+
+ if (ListenTransCount == 0 && !NoListenAll)
+ 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);
+ ResetHosts(display);
+
+ InitParentProcess();
+
+#ifdef XDMCP
+ XdmcpInit ();
+#endif
+}
+
+#ifdef NX_TRANS_SOCKET
+
+/*
+ * The following block is now defined also
+ * under Cygwin to support this environment.
+ */
+
+#ifndef __DARWIN__
+
+/*
+ * This is defined in Xtranssock.c and must
+ * be called explicitly as it doesn't share
+ * a pointer in the transport function table.
+ */
+
+extern void _XSERVTransSocketRejectConnection(XtransConnInfo);
+
+void
+RejectWellKnownSockets ()
+{
+ int i;
+
+ for (i = 0; i < ListenTransCount; i++)
+ {
+ _XSERVTransSocketRejectConnection(ListenTransConns[i]);
+ }
+}
+
+#endif /* #ifndef __DARWIN__ */
+
+#else /* #ifdef NX_TRANS_SOCKET */
+
+void
+RejectWellKnownSockets ()
+{
+}
+
+#endif /* #ifdef NX_TRANS_SOCKET */
+
+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)
+ {
+ /*
+ * ListenTransConns[i] freed by xtrans.
+ * Remove it from out list.
+ */
+
+ RemoveNotifyFd(ListenTransFds[i]);
+ ListenTransFds[i] = ListenTransFds[ListenTransCount - 1];
+ ListenTransConns[i] = ListenTransConns[ListenTransCount - 1];
+ ListenTransCount -= 1;
+ i -= 1;
+ }
+ else if (status == TRANS_RESET_NEW_FD)
+ {
+ /*
+ * A new file descriptor was allocated (the old one was closed)
+ */
+
+ int newfd = _XSERVTransGetConnectionNumber (ListenTransConns[i]);
+
+ ListenTransFds[i] = newfd;
+ }
+ }
+ }
+
+ for (i = 0; i < ListenTransCount; i++)
+ SetNotifyFd(ListenTransFds[i], QueueNewConnections, X_NOTIFY_READ, NULL);
+
+ ResetAuthorization ();
+ ResetHosts(display);
+ /*
+ * restart XDMCP
+ */
+#ifdef XDMCP
+ XdmcpReset ();
+#endif
+}
+
+void
+CloseWellKnownConnections(void)
+{
+ int i;
+
+ for (i = 0; i < ListenTransCount; i++) {
+ if (ListenTransConns[i] != NULL) {
+ _XSERVTransClose(ListenTransConns[i]);
+ ListenTransConns[i] = NULL;
+ if (ListenTransFds != NULL)
+ RemoveNotifyFd(ListenTransFds[i]);
+ }
+ }
+ ListenTransCount = 0;
+}
+
+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;
+
+ 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)
+ 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; /* length written to client_uid_string */
+
+ 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) {
+ 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) {
+ 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';
+ }
+
+ 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;
+}
+
+
+/*****************************************************************
+ * ClientAuthorized
+ *
+ * Sent by the client at connection setup:
+ * typedef struct _xConnClientPrefix {
+ * CARD8 byteOrder;
+ * BYTE pad;
+ * CARD16 majorVersion, minorVersion;
+ * CARD16 nbytesAuthProto;
+ * CARD16 nbytesAuthString;
+ * } xConnClientPrefix;
+ *
+ * It is hoped that eventually one protocol will be agreed upon. In the
+ * mean time, a server that implements a different protocol than the
+ * client expects, or a server that only implements the host-based
+ * mechanism, will simply ignore this information.
+ *
+ *****************************************************************/
+
+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;
+
+ auth_id = CheckAuthorization (proto_n, auth_proto,
+ string_n, auth_string, client, &reason);
+
+ if (auth_id == (XID) ~0L)
+ {
+ if (
+#ifdef XCSECURITY
+ (proto_n == 0 ||
+ strncmp (auth_proto, XSecurityAuthorizationName, proto_n) != 0) &&
+#endif
+ _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;
+ if (auditTrailLevel > 1)
+ AuthAudit(client, TRUE,
+ (struct sockaddr *) from, fromlen,
+ proto_n, auth_proto, auth_id);
+ }
+
+ free ((char *) from);
+ }
+
+ if (auth_id == (XID) ~0L) {
+ if (reason)
+ return reason;
+ else
+ return "Client is not authorized to connect to Server";
+ }
+ }
+ else if (auditTrailLevel > 1)
+ {
+ if (_XSERVTransGetPeerAddr (trans_conn,
+ &family, &fromlen, &from) != -1)
+ {
+ AuthAudit(client, TRUE, (struct sockaddr *) from, fromlen,
+ proto_n, auth_proto, auth_id);
+
+ free ((char *) from);
+ }
+ }
+ priv->auth_id = auth_id;
+ priv->conn_time = 0;
+
+#ifdef XDMCP
+ /* indicate to Xdmcp protocol that we've opened new client */
+ XdmcpOpenDisplay(priv->fd);
+#endif /* XDMCP */
+ /* At this point, if the client is authorized to change the access control
+ * list, we should getpeername() information, and add the client to
+ * the selfhosts list. It's not really the host machine, but the
+ * true purpose of the selfhosts list is to see who may change the
+ * access control list.
+ */
+ 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 = (OsCommPtr)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((void *)oc)))
+ {
+ free (oc);
+ return NullClient;
+ }
+ client->local = 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
+
+ return client;
+}
+
+/*****************
+ * EstablishNewConnections
+ * If anyone is waiting on listened sockets, accept them.
+ * Returns a mask with indices of new clients. Updates AllClients
+ * and AllSockets.
+ *****************/
+
+static Bool
+EstablishNewConnections(ClientPtr clientUnused, void * closure)
+{
+ int curconn = (int) (intptr_t) closure;
+ int newconn; /* fd of new client */
+ CARD32 connect_time;
+ int i;
+ ClientPtr client;
+ OsCommPtr oc;
+ XtransConnInfo trans_conn, new_trans_conn;
+ int status;
+
+ connect_time = GetTimeInMillis();
+ /* kill off stragglers */
+ 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);
+ }
+ }
+ if ((trans_conn = lookup_trans_conn(curconn)) == NULL)
+ return TRUE;
+
+ if ((new_trans_conn = _XSERVTransAccept(trans_conn, &status)) == NULL)
+ return TRUE;
+
+ 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 (trans_conn->flags & TRANS_NOXAUTH)
+ new_trans_conn->flags = new_trans_conn->flags | TRANS_NOXAUTH;
+
+ if (!AllocNewConnection(new_trans_conn, newconn, connect_time)) {
+ ErrorConnMax(new_trans_conn);
+ }
+
+ return TRUE;
+}
+
+static void
+QueueNewConnections(int fd, int ready, void *data)
+{
+ QueueWorkProc(EstablishNewConnections, NULL, (void *) (intptr_t) fd);
+}
+
+#define NOROOM "Maximum number of clients reached"
+
+/************
+ * ErrorConnMax
+ * Fail a connection due to lack of client or file descriptor space
+ ************/
+
+static void
+ConnMaxNotify(int fd, int events, void *data)
+{
+ XtransConnInfo trans_conn = data;
+ char order = 0;
+
+ /* try to read the byte-order of the connection */
+ (void)_XSERVTransRead(trans_conn, &order, 1);
+ if (order == 'l' || order == 'B' || order == 'r' || order == 'R')
+ {
+
+ xConnSetupPrefix csp;
+ char pad[3] = { 0, 0, 0 };
+ int whichbyte = 1;
+ struct iovec iov[3];
+
+ 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) && (order == 'B' || order == 'R')) ||
+ (!(*(char *) &whichbyte) && (order == 'l' || order == 'r')))
+ {
+ swaps(&csp.majorVersion);
+ swaps(&csp.minorVersion);
+ swaps(&csp.length);
+ }
+ 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);
+ }
+ RemoveNotifyFd(trans_conn->fd);
+ _XSERVTransClose(trans_conn);
+}
+
+static void
+ErrorConnMax(XtransConnInfo trans_conn)
+{
+ if (!SetNotifyFd(trans_conn->fd, ConnMaxNotify, X_NOTIFY_READ, trans_conn))
+ _XSERVTransClose(trans_conn);
+}
+
+/************
+ * CloseDownFileDescriptor:
+ * Remove this file descriptor and it's I/O buffers, etc.
+ ************/
+
+static void
+CloseDownFileDescriptor(OsCommPtr oc)
+{
+ int connection = oc->fd;
+
+ if (oc->trans_conn) {
+ _XSERVTransDisconnect(oc->trans_conn);
+ _XSERVTransClose(oc->trans_conn);
+ }
+ FreeOsBuffers(oc);
+ free(oc);
+#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) && NumNotifyWriteFd == 0)
+ AnyWritesPending = FALSE;
+ FD_CLR(connection, &OutputPending);
+}
+
+/*****************
+ * CheckConnections
+ * Some connection has died, go find which one and shut it down
+ * The file descriptor has been closed, but is still in AllClients.
+ * If would truly be wonderful if select() would put the bogus
+ * file descriptors in the exception mask, but nooooo. So we have
+ * to check each and every socket individually.
+ *****************/
+
+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 = ffs (mask) - 1;
+ curclient = curoff + (i * (sizeof(fd_mask)*8));
+ FD_ZERO(&tmask);
+ FD_SET(curclient, &tmask);
+ r = Select (curclient + 1, &tmask, NULL, NULL, &notime);
+ if (r < 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);
+ r = Select (curclient + 1, &tmask, NULL, NULL, &notime);
+ if (r < 0)
+ CloseDownClient(clients[GetConnectionTranslation(curclient)]);
+ }
+#endif
+}
+
+
+/*****************
+ * CloseDownConnection
+ * Delete client from AllClients and free resources
+ *****************/
+
+void
+CloseDownConnection(ClientPtr client)
+{
+ OsCommPtr oc = (OsCommPtr)client->osPrivate;
+
+ if (FlushCallback)
+ CallCallbacks(&FlushCallback, client);
+
+ if (oc->output && oc->output->count)
+ FlushClient(client, oc, (char *)NULL, 0);
+#ifdef XDMCP
+ XdmcpCloseDisplay(oc->fd);
+#endif
+ CloseDownFileDescriptor(oc);
+ client->osPrivate = (void *)NULL;
+ if (auditTrailLevel > 1)
+ AuditF("client %d disconnected\n", client->index);
+}
+
+struct notify_fd {
+ struct xorg_list list;
+ int fd;
+ int mask;
+ NotifyFdProcPtr notify;
+ void *data;
+};
+
+static struct xorg_list notify_fds;
+
+void
+InitNotifyFds(void)
+{
+ struct notify_fd *s, *next;
+ static int been_here;
+
+ if (been_here)
+ xorg_list_for_each_entry_safe(s, next, &notify_fds, list)
+ RemoveNotifyFd(s->fd);
+
+ xorg_list_init(&notify_fds);
+ NumNotifyWriteFd = 0;
+ been_here = 1;
+}
+
+/*****************
+ * SetNotifyFd
+ * Registers a callback to be invoked when the specified
+ * file descriptor becomes readable.
+ *****************/
+
+Bool
+SetNotifyFd(int fd, NotifyFdProcPtr notify, int mask, void *data)
+{
+ struct notify_fd *n;
+ int changes;
+
+ xorg_list_for_each_entry(n, &notify_fds, list)
+ if (n->fd == fd)
+ break;
+
+ if (&n->list == &notify_fds) {
+ if (mask == 0)
+ return TRUE;
+
+ n = calloc(1, sizeof (struct notify_fd));
+ if (!n)
+ return FALSE;
+ n->fd = fd;
+ xorg_list_add(&n->list, &notify_fds);
+ }
+
+ changes = n->mask ^ mask;
+
+ if (changes & X_NOTIFY_READ) {
+ if (mask & X_NOTIFY_READ) {
+ FD_SET(fd, &NotifyReadFds);
+ FD_SET(fd, &AllSockets);
+ if (GrabInProgress)
+ FD_SET(fd, &SavedAllSockets);
+ } else {
+ FD_CLR(fd, &AllSockets);
+ if (GrabInProgress)
+ FD_CLR(fd, &SavedAllSockets);
+ FD_CLR(fd, &NotifyReadFds);
+ }
+ }
+
+ if (changes & X_NOTIFY_WRITE) {
+ if (mask & X_NOTIFY_WRITE) {
+ FD_SET(fd, &NotifyWriteFds);
+ if (!NumNotifyWriteFd++)
+ AnyWritesPending = TRUE;
+ } else {
+ FD_CLR(fd, &NotifyWriteFds);
+ if (!--NumNotifyWriteFd)
+ if (!XFD_ANYSET(&ClientsWriteBlocked))
+ AnyWritesPending = FALSE;
+ }
+ }
+
+ if (mask == 0) {
+ xorg_list_del(&n->list);
+ free(n);
+ } else {
+ n->mask = mask;
+ n->data = data;
+ n->notify = notify;
+ }
+
+ return TRUE;
+}
+
+/*****************
+ * HandlNotifyFds
+ * A WorkProc to be called when any of the registered
+ * file descriptors are readable.
+ *****************/
+
+void
+HandleNotifyFds(void)
+{
+ struct notify_fd *n, *next;
+
+ xorg_list_for_each_entry_safe(n, next, &notify_fds, list) {
+ int ready = 0;
+ if ((n->mask & X_NOTIFY_READ) && FD_ISSET(n->fd, &LastSelectMask))
+ ready |= X_NOTIFY_READ;
+ if ((n->mask & X_NOTIFY_WRITE) & FD_ISSET(n->fd, &LastSelectWriteMask))
+ ready |= X_NOTIFY_WRITE;
+ if (ready != 0)
+ n->notify(n->fd, ready, n->data);
+ }
+}
+
+/*****************
+ * OnlyListenToOneClient:
+ * Only accept requests from one client. Continue to handle new
+ * connections, but don't take any protocol requests from the new
+ * ones. Note that if GrabInProgress is set, EstablishNewConnections
+ * needs to put new clients into SavedAllSockets and SavedAllClients.
+ * Note also that there is no timeout for this in the protocol.
+ * This routine is "undone" by ListenToAllClients()
+ *****************/
+
+void
+OnlyListenToOneClient(ClientPtr client)
+{
+ OsCommPtr oc = (OsCommPtr)client->osPrivate;
+ int connection = oc->fd;
+
+ 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;
+ }
+}
+
+/****************
+ * ListenToAllClients:
+ * Undoes OnlyListentToOneClient()
+ ****************/
+
+void
+ListenToAllClients(void)
+{
+ if (GrabInProgress)
+ {
+ XFD_ORSET(&AllSockets, &AllSockets, &SavedAllSockets);
+ XFD_ORSET(&AllClients, &AllClients, &SavedAllClients);
+ XFD_ORSET(&ClientsWithInput, &ClientsWithInput, &SavedClientsWithInput);
+ GrabInProgress = 0;
+ }
+}
+
+/****************
+ * IgnoreClient
+ * Removes one client from input masks.
+ * Must have cooresponding call to AttendClient.
+ ****************/
+
+void
+IgnoreClient (ClientPtr client)
+{
+ OsCommPtr oc = (OsCommPtr)client->osPrivate;
+ int connection = oc->fd;
+
+ 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);
+ }
+}
+
+/****************
+ * AttendClient
+ * Adds one client back into the input masks.
+ ****************/
+
+void
+AttendClient (ClientPtr client)
+{
+ OsCommPtr oc = (OsCommPtr)client->osPrivate;
+ int connection = oc->fd;
+ 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);
+ }
+}
+
+/* make client impervious to grabs; assume only executing client calls this */
+
+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);
+ }
+}
+
+/* make client pervious to grabs; assume only executing client calls this */
+
+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);
+ }
+}
+
diff --git a/nx-X11/programs/Xserver/os/io.c b/nx-X11/programs/Xserver/os/io.c
new file mode 100644
index 000000000..07399438e
--- /dev/null
+++ b/nx-X11/programs/Xserver/os/io.c
@@ -0,0 +1,1293 @@
+/***********************************************************
+
+Copyright 1987, 1989, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+
+******************************************************************/
+/*****************************************************************
+ * i/o functions
+ *
+ * WriteToClient, ReadRequestFromClient
+ * InsertFakeRequest, ResetCurrentRequest
+ *
+ *****************************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#if 0
+#define DEBUG_COMMUNICATION
+#endif
+#ifdef WIN32
+#include <nx-X11/Xwinsock.h>
+#endif
+#include <stdio.h>
+#define XSERV_t
+#define TRANS_SERVER
+#define TRANS_REOPEN
+#include <nx-X11/Xtrans/Xtrans.h>
+#include <nx-X11/Xmd.h>
+#include <errno.h>
+#if !defined(WIN32)
+#include <sys/uio.h>
+#endif
+#include <nx-X11/X.h>
+#include <nx-X11/Xproto.h>
+#include "os.h"
+#include "osdep.h"
+#include <nx-X11/Xpoll.h>
+#include "opaque.h"
+#include "dixstruct.h"
+#include "misc.h"
+
+CallbackListPtr ReplyCallback;
+CallbackListPtr FlushCallback;
+
+/* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX
+ * systems are broken and return EWOULDBLOCK when they should return EAGAIN
+ */
+#ifndef WIN32
+#if defined(EAGAIN) && defined(EWOULDBLOCK)
+#define ETEST(err) (err == EAGAIN || err == EWOULDBLOCK)
+#else
+#ifdef EAGAIN
+#define ETEST(err) (err == EAGAIN)
+#else
+#define ETEST(err) (err == EWOULDBLOCK)
+#endif
+#endif
+#else /* WIN32 The socket errorcodes differ from the normal errors*/
+#define ETEST(err) (err == EAGAIN || err == WSAEWOULDBLOCK)
+#endif
+
+Bool CriticalOutputPending;
+int timesThisConnection = 0;
+ConnectionInputPtr FreeInputs = (ConnectionInputPtr)NULL;
+ConnectionOutputPtr FreeOutputs = (ConnectionOutputPtr)NULL;
+OsCommPtr AvailableInput = (OsCommPtr)NULL;
+
+#define get_req_len(req,cli) ((cli)->swapped ? \
+ lswaps((req)->length) : (req)->length)
+
+#ifdef BIGREQS
+#include <nx-X11/extensions/bigreqstr.h>
+
+#define get_big_req_len(req,cli) ((cli)->swapped ? \
+ lswapl(((xBigReq *)(req))->length) : \
+ ((xBigReq *)(req))->length)
+#endif
+
+#define MAX_TIMES_PER 10
+
+/*
+ * A lot of the code in this file manipulates a ConnectionInputPtr:
+ *
+ * -----------------------------------------------
+ * |------- bufcnt ------->| | |
+ * | |- gotnow ->| | |
+ * | |-------- needed ------>| |
+ * |-----------+--------- size --------+---------->|
+ * -----------------------------------------------
+ * ^ ^
+ * | |
+ * buffer bufptr
+ *
+ * buffer is a pointer to the start of the buffer.
+ * bufptr points to the start of the current request.
+ * bufcnt counts how many bytes are in the buffer.
+ * size is the size of the buffer in bytes.
+ *
+ * In several of the functions, gotnow and needed are local variables
+ * that do the following:
+ *
+ * gotnow is the number of bytes of the request that we're
+ * trying to read that are currently in the buffer.
+ * Typically, gotnow = (buffer + bufcnt) - bufptr
+ *
+ * needed = the length of the request that we're trying to
+ * read. Watch out: needed sometimes counts bytes and sometimes
+ * counts CARD32's.
+ */
+
+
+/*****************************************************************
+ * ReadRequestFromClient
+ * Returns one request in client->requestBuffer. The request
+ * length will be in client->req_len. Return status is:
+ *
+ * > 0 if successful, specifies length in bytes of the request
+ * = 0 if entire request is not yet available
+ * < 0 if client should be terminated
+ *
+ * The request returned must be contiguous so that it can be
+ * cast in the dispatcher to the correct request type. Because requests
+ * are variable length, ReadRequestFromClient() must look at the first 4
+ * or 8 bytes of a request to determine the length (the request length is
+ * in the 3rd and 4th bytes of the request unless it is a Big Request
+ * (see the Big Request Extension), in which case the 3rd and 4th bytes
+ * are zero and the following 4 bytes are the request length.
+ *
+ * Note: in order to make the server scheduler (WaitForSomething())
+ * "fair", the ClientsWithInput mask is used. This mask tells which
+ * clients have FULL requests left in their buffers. Clients with
+ * partial requests require a read. Basically, client buffers
+ * are drained before select() is called again. But, we can't keep
+ * reading from a client that is sending buckets of data (or has
+ * a partial request) because others clients need to be scheduled.
+ *****************************************************************/
+
+#define YieldControl() \
+ { isItTimeToYield = TRUE; \
+ timesThisConnection = 0; }
+#define YieldControlNoInput() \
+ { YieldControl(); \
+ FD_CLR(fd, &ClientsWithInput); }
+#define YieldControlDeath() \
+ { timesThisConnection = 0; }
+
+int
+ReadRequestFromClient(ClientPtr client)
+{
+ OsCommPtr oc = (OsCommPtr)client->osPrivate;
+ ConnectionInputPtr oci = oc->input;
+ int fd = oc->fd;
+ unsigned int gotnow, needed;
+ int result;
+ register xReq *request;
+ Bool need_header;
+#ifdef BIGREQS
+ Bool move_header;
+#endif
+
+ /* If an input buffer was empty, either free it if it is too big
+ * or link it into our list of free input buffers. This means that
+ * different clients can share the same input buffer (at different
+ * times). This was done to save memory.
+ */
+
+ if (AvailableInput)
+ {
+ if (AvailableInput != oc)
+ {
+ register ConnectionInputPtr aci = AvailableInput->input;
+ if (aci->size > BUFWATERMARK)
+ {
+ free(aci->buffer);
+ free(aci);
+ }
+ else
+ {
+ aci->next = FreeInputs;
+ FreeInputs = aci;
+ }
+ AvailableInput->input = (ConnectionInputPtr)NULL;
+ }
+ AvailableInput = (OsCommPtr)NULL;
+ }
+
+ /* make sure we have an input buffer */
+
+ if (!oci)
+ {
+ if ((oci = FreeInputs))
+ {
+ FreeInputs = oci->next;
+ }
+ else if (!(oci = AllocateInputBuffer()))
+ {
+ YieldControlDeath();
+ return -1;
+ }
+ oc->input = oci;
+ }
+
+ /* advance to start of next request */
+
+ oci->bufptr += oci->lenLastReq;
+
+ need_header = FALSE;
+#ifdef BIGREQS
+ move_header = FALSE;
+#endif
+ gotnow = oci->bufcnt + oci->buffer - oci->bufptr;
+
+ if (oci->ignoreBytes > 0) {
+ if (oci->ignoreBytes > oci->size)
+ needed = oci->size;
+ else
+ needed = oci->ignoreBytes;
+ }
+ else if (gotnow < sizeof(xReq))
+ {
+ /* We don't have an entire xReq yet. Can't tell how big
+ * the request will be until we get the whole xReq.
+ */
+ needed = sizeof(xReq);
+ need_header = TRUE;
+ }
+ else
+ {
+ /* We have a whole xReq. We can tell how big the whole
+ * request will be unless it is a Big Request.
+ */
+ request = (xReq *)oci->bufptr;
+ needed = get_req_len(request, client);
+#ifdef BIGREQS
+ if (!needed && client->big_requests)
+ {
+ /* It's a Big Request. */
+ move_header = TRUE;
+ if (gotnow < sizeof(xBigReq))
+ {
+ /* Still need more data to tell just how big. */
+ needed = sizeof(xBigReq) >> 2; /* needed is in CARD32s now */
+ need_header = TRUE;
+ }
+ else
+ needed = get_big_req_len(request, client);
+ }
+#endif
+ client->req_len = needed;
+ needed <<= 2; /* needed is in bytes now */
+ }
+ if (gotnow < needed)
+ {
+ /* Need to read more data, either so that we can get a
+ * complete xReq (if need_header is TRUE), a complete
+ * xBigReq (if move_header is TRUE), or the rest of the
+ * request (if need_header and move_header are both FALSE).
+ */
+
+ oci->lenLastReq = 0;
+ if (needed > MAXBUFSIZE)
+ {
+ /* request is too big for us to handle */
+ /*
+ * Mark the rest of it as needing to be ignored, and then return
+ * the full size. Dispatch() will turn it into a BadLength error.
+ */
+ oci->ignoreBytes = needed - gotnow;
+ oci->lenLastReq = gotnow;
+ return needed;
+ }
+ if ((gotnow == 0) ||
+ ((oci->bufptr - oci->buffer + needed) > oci->size))
+ {
+ /* no data, or the request is too big to fit in the buffer */
+
+ if ((gotnow > 0) && (oci->bufptr != oci->buffer))
+ /* save the data we've already read */
+ memmove(oci->buffer, oci->bufptr, gotnow);
+ if (needed > oci->size)
+ {
+ /* make buffer bigger to accomodate request */
+ char *ibuf;
+
+ ibuf = (char *)realloc(oci->buffer, needed);
+ if (!ibuf)
+ {
+ YieldControlDeath();
+ return -1;
+ }
+ oci->size = needed;
+ oci->buffer = ibuf;
+ }
+ oci->bufptr = oci->buffer;
+ oci->bufcnt = gotnow;
+ }
+ /* XXX this is a workaround. This function is sometimes called
+ * after the trans_conn has been freed. In this case trans_conn
+ * will be null. Really ought to restructure things so that we
+ * never get here in those circumstances.
+ */
+ if (!oc->trans_conn)
+ {
+ /* treat as if an error occured on the read, which is what
+ * used to happen
+ */
+ YieldControlDeath();
+ return -1;
+ }
+ result = _XSERVTransRead(oc->trans_conn, oci->buffer + oci->bufcnt,
+ oci->size - oci->bufcnt);
+ if (result <= 0)
+ {
+ if ((result < 0) && ETEST(errno))
+ {
+#if defined(SVR4) && defined(i386) && !defined(sun)
+ if (0)
+#endif
+ {
+ YieldControlNoInput();
+ return 0;
+ }
+ }
+ YieldControlDeath();
+ return -1;
+ }
+ oci->bufcnt += result;
+ gotnow += result;
+ /* free up some space after huge requests */
+ if ((oci->size > BUFWATERMARK) &&
+ (oci->bufcnt < BUFSIZE) && (needed < BUFSIZE))
+ {
+ char *ibuf;
+
+ ibuf = (char *)realloc(oci->buffer, BUFSIZE);
+ if (ibuf)
+ {
+ oci->size = BUFSIZE;
+ oci->buffer = ibuf;
+ oci->bufptr = ibuf + oci->bufcnt - gotnow;
+ }
+ }
+ if (need_header && gotnow >= needed)
+ {
+ /* We wanted an xReq, now we've gotten it. */
+ request = (xReq *)oci->bufptr;
+ needed = get_req_len(request, client);
+#ifdef BIGREQS
+ if (!needed && client->big_requests)
+ {
+ move_header = TRUE;
+ if (gotnow < sizeof(xBigReq))
+ needed = sizeof(xBigReq) >> 2;
+ else
+ needed = get_big_req_len(request, client);
+ }
+#endif
+ client->req_len = needed;
+ needed <<= 2;
+ }
+ if (gotnow < needed)
+ {
+ /* Still don't have enough; punt. */
+ YieldControlNoInput();
+ return 0;
+ }
+ }
+ if (needed == 0)
+ {
+#ifdef BIGREQS
+ if (client->big_requests)
+ needed = sizeof(xBigReq);
+ else
+#endif
+ needed = sizeof(xReq);
+ }
+
+ /* If there are bytes to ignore, ignore them now. */
+
+ if (oci->ignoreBytes > 0) {
+ assert(needed == oci->ignoreBytes || needed == oci->size);
+ oci->ignoreBytes -= gotnow;
+ needed = gotnow = 0;
+ /*
+ * The _XSERVTransRead call above may return more or fewer bytes than we
+ * want to ignore. Ignore the smaller of the two sizes.
+ */
+ if (gotnow < needed) {
+ oci->ignoreBytes -= gotnow;
+ oci->bufptr += gotnow;
+ gotnow = 0;
+ } else {
+ oci->ignoreBytes -= needed;
+ oci->bufptr += needed;
+ gotnow -= needed;
+ }
+ needed = 0;
+ }
+
+ oci->lenLastReq = needed;
+
+ /*
+ * Check to see if client has at least one whole request in the
+ * buffer beyond the request we're returning to the caller.
+ * If there is only a partial request, treat like buffer
+ * is empty so that select() will be called again and other clients
+ * can get into the queue.
+ */
+
+ gotnow -= needed;
+ if (gotnow >= sizeof(xReq))
+ {
+ request = (xReq *)(oci->bufptr + needed);
+ if (gotnow >= (result = (get_req_len(request, client) << 2))
+#ifdef BIGREQS
+ && (result ||
+ (client->big_requests &&
+ (gotnow >= sizeof(xBigReq) &&
+ gotnow >= (get_big_req_len(request, client) << 2))))
+#endif
+ )
+ FD_SET(fd, &ClientsWithInput);
+ else
+ {
+ FD_CLR(fd, &ClientsWithInput);
+ }
+ }
+ else
+ {
+ if (!gotnow)
+ AvailableInput = oc;
+ FD_CLR(fd, &ClientsWithInput);
+ }
+#ifdef BIGREQS
+ if (move_header)
+ {
+ request = (xReq *)oci->bufptr;
+ oci->bufptr += (sizeof(xBigReq) - sizeof(xReq));
+ *(xReq *)oci->bufptr = *request;
+ oci->lenLastReq -= (sizeof(xBigReq) - sizeof(xReq));
+ client->req_len -= (sizeof(xBigReq) - sizeof(xReq)) >> 2;
+ }
+#endif
+ client->requestBuffer = (void *)oci->bufptr;
+#ifdef DEBUG_COMMUNICATION
+ {
+ xReq *req = client->requestBuffer;
+ ErrorF("REQUEST: ClientIDX: %i, type: 0x%x data: 0x%x len: %i\n",
+ client->index,req->reqType,req->data,req->length);
+ }
+#endif
+ return needed;
+}
+
+/*****************************************************************
+ * InsertFakeRequest
+ * Splice a consed up (possibly partial) request in as the next request.
+ *
+ **********************/
+
+Bool
+InsertFakeRequest(ClientPtr client, char *data, int count)
+{
+ OsCommPtr oc = (OsCommPtr)client->osPrivate;
+ ConnectionInputPtr oci = oc->input;
+ int fd = oc->fd;
+ int gotnow, moveup;
+
+ if (AvailableInput)
+ {
+ if (AvailableInput != oc)
+ {
+ ConnectionInputPtr aci = AvailableInput->input;
+ if (aci->size > BUFWATERMARK)
+ {
+ free(aci->buffer);
+ free(aci);
+ }
+ else
+ {
+ aci->next = FreeInputs;
+ FreeInputs = aci;
+ }
+ AvailableInput->input = (ConnectionInputPtr)NULL;
+ }
+ AvailableInput = (OsCommPtr)NULL;
+ }
+ if (!oci)
+ {
+ if ((oci = FreeInputs))
+ FreeInputs = oci->next;
+ else if (!(oci = AllocateInputBuffer()))
+ return FALSE;
+ oc->input = oci;
+ }
+ oci->bufptr += oci->lenLastReq;
+ oci->lenLastReq = 0;
+ gotnow = oci->bufcnt + oci->buffer - oci->bufptr;
+ if ((gotnow + count) > oci->size)
+ {
+ char *ibuf;
+
+ ibuf = (char *)realloc(oci->buffer, gotnow + count);
+ if (!ibuf)
+ return(FALSE);
+ oci->size = gotnow + count;
+ oci->buffer = ibuf;
+ oci->bufptr = ibuf + oci->bufcnt - gotnow;
+ }
+ moveup = count - (oci->bufptr - oci->buffer);
+ if (moveup > 0)
+ {
+ if (gotnow > 0)
+ memmove(oci->bufptr + moveup, oci->bufptr, gotnow);
+ oci->bufptr += moveup;
+ oci->bufcnt += moveup;
+ }
+ memmove(oci->bufptr - count, data, count);
+ oci->bufptr -= count;
+ gotnow += count;
+ if ((gotnow >= sizeof(xReq)) &&
+ (gotnow >= (int)(get_req_len((xReq *)oci->bufptr, client) << 2)))
+ FD_SET(fd, &ClientsWithInput);
+ else
+ YieldControlNoInput();
+ return(TRUE);
+}
+
+/*****************************************************************
+ * ResetRequestFromClient
+ * Reset to reexecute the current request, and yield.
+ *
+ **********************/
+
+void
+ResetCurrentRequest(ClientPtr client)
+{
+ OsCommPtr oc = (OsCommPtr)client->osPrivate;
+ register ConnectionInputPtr oci = oc->input;
+ int fd = oc->fd;
+ register xReq *request;
+ int gotnow, needed;
+ if (AvailableInput == oc)
+ AvailableInput = (OsCommPtr)NULL;
+ oci->lenLastReq = 0;
+ gotnow = oci->bufcnt + oci->buffer - oci->bufptr;
+ if (gotnow < sizeof(xReq))
+ {
+ YieldControlNoInput();
+ }
+ else
+ {
+ request = (xReq *)oci->bufptr;
+ needed = get_req_len(request, client);
+#ifdef BIGREQS
+ if (!needed && client->big_requests)
+ {
+ oci->bufptr -= sizeof(xBigReq) - sizeof(xReq);
+ *(xReq *)oci->bufptr = *request;
+ ((xBigReq *)oci->bufptr)->length = client->req_len;
+ if (client->swapped)
+ {
+ swapl(&((xBigReq *)oci->bufptr)->length);
+ }
+ }
+#endif
+ if (gotnow >= (needed << 2))
+ {
+ if (FD_ISSET(fd, &AllClients))
+ {
+ FD_SET(fd, &ClientsWithInput);
+ }
+ else
+ {
+ FD_SET(fd, &IgnoredClientsWithInput);
+ }
+ YieldControl();
+ }
+ else
+ YieldControlNoInput();
+ }
+}
+
+
+
+/*****************************************************************
+ * PeekNextRequest and SkipRequests were implemented to support DBE
+ * idioms, but can certainly be used outside of DBE. There are two
+ * related macros in os.h, ReqLen and CastxReq. See the porting
+ * layer document for more details.
+ *
+ **********************/
+
+
+/*****************************************************************
+ * PeekNextRequest
+ * lets you look ahead at the unexecuted requests in a
+ * client's request buffer.
+ *
+ * Note: this implementation of PeekNextRequest ignores the
+ * readmore parameter.
+ *
+ **********************/
+
+xReqPtr
+PeekNextRequest(
+ xReqPtr req, /* request we're starting from */
+ ClientPtr client, /* client whose requests we're skipping */
+ Bool readmore) /* attempt to read more if next request isn't there? */
+{
+ register ConnectionInputPtr oci = ((OsCommPtr)client->osPrivate)->input;
+ xReqPtr pnextreq;
+ int needed, gotnow, reqlen;
+
+ if (!oci) return NULL;
+
+ if (!req)
+ {
+ /* caller wants the request after the one currently being executed */
+ pnextreq = (xReqPtr)
+ (((CARD32 *)client->requestBuffer) + client->req_len);
+ }
+ else
+ {
+ /* caller wants the request after the one specified by req */
+ reqlen = get_req_len(req, client);
+#ifdef BIGREQS
+ if (!reqlen) reqlen = get_big_req_len(req, client);
+#endif
+ pnextreq = (xReqPtr)(((char *)req) + (reqlen << 2));
+ }
+
+ /* see how much of the next request we have available */
+
+ gotnow = oci->bufcnt - (((char *)pnextreq) - oci->buffer);
+
+ if (gotnow < sizeof(xReq))
+ return NULL;
+
+ needed = get_req_len(pnextreq, client) << 2;
+#ifdef BIGREQS
+ if (!needed)
+ {
+ /* it's a big request */
+ if (gotnow < sizeof(xBigReq))
+ return NULL;
+ needed = get_big_req_len(pnextreq, client) << 2;
+ }
+#endif
+
+ /* if we have less than we need, return NULL */
+
+ return (gotnow < needed) ? NULL : pnextreq;
+}
+
+/*****************************************************************
+ * SkipRequests
+ * lets you skip over some of the requests in a client's
+ * request buffer. Presumably the caller has used PeekNextRequest
+ * to examine the requests being skipped and has performed whatever
+ * actions they dictate.
+ *
+ **********************/
+
+CallbackListPtr SkippedRequestsCallback = NULL;
+
+void
+SkipRequests(
+ xReqPtr req, /* last request being skipped */
+ ClientPtr client, /* client whose requests we're skipping */
+ int numskipped) /* how many requests we're skipping */
+{
+ OsCommPtr oc = (OsCommPtr)client->osPrivate;
+ register ConnectionInputPtr oci = oc->input;
+ int reqlen;
+
+ /* see if anyone wants to snoop the skipped requests */
+
+ if (SkippedRequestsCallback)
+ {
+ SkippedRequestInfoRec skipinfo;
+ skipinfo.req = req;
+ skipinfo.client = client;
+ skipinfo.numskipped = numskipped;
+ CallCallbacks(&SkippedRequestsCallback, &skipinfo);
+ }
+
+ /* adjust the sequence number */
+ client->sequence += numskipped;
+
+ /* twiddle the oci to skip over the requests */
+
+ reqlen = get_req_len(req, client);
+#ifdef BIGREQS
+ if (!reqlen) reqlen = get_big_req_len(req, client);
+#endif
+ reqlen <<= 2;
+ oci->bufptr = (char *)req;
+ oci->lenLastReq = reqlen;
+
+ /* see if any requests left in the buffer */
+
+ if ( ((char *)req + reqlen) == (oci->buffer + oci->bufcnt) )
+ {
+ /* no requests; mark input buffer as available and client
+ * as having no input
+ */
+ int fd = oc->fd;
+ AvailableInput = oc;
+ YieldControlNoInput();
+ }
+}
+
+
+ /* lookup table for adding padding bytes to data that is read from
+ or written to the X socket. */
+static int padlength[4] = {0, 3, 2, 1};
+
+ /********************
+ * FlushAllOutput()
+ * Flush all clients with output. However, if some client still
+ * has input in the queue (more requests), then don't flush. This
+ * will prevent the output queue from being flushed every time around
+ * the round robin queue. Now, some say that it SHOULD be flushed
+ * every time around, but...
+ *
+ **********************/
+
+void
+FlushAllOutput(void)
+{
+ register int index, base;
+ register fd_mask mask; /* raphael */
+ OsCommPtr oc;
+ register ClientPtr client;
+ Bool newoutput = NewOutputPending;
+#if defined(WIN32)
+ fd_set newOutputPending;
+#endif
+
+ if (!newoutput)
+ return;
+
+ /*
+ * It may be that some client still has critical output pending,
+ * but he is not yet ready to receive it anyway, so we will
+ * simply wait for the select to tell us when he's ready to receive.
+ */
+ CriticalOutputPending = FALSE;
+ NewOutputPending = FALSE;
+
+#ifndef WIN32
+ for (base = 0; base < howmany(XFD_SETSIZE, NFDBITS); base++)
+ {
+ mask = OutputPending.fds_bits[ base ];
+ OutputPending.fds_bits[ base ] = 0;
+ while (mask)
+ {
+ index = ffs(mask) - 1;
+ mask &= ~lowbit(mask);
+ if ((index = ConnectionTranslation[(base * (sizeof(fd_mask)*8)) + index]) == 0)
+ continue;
+ client = clients[index];
+ if (client->clientGone)
+ continue;
+ oc = (OsCommPtr)client->osPrivate;
+ if (
+ FD_ISSET(oc->fd, &ClientsWithInput))
+ {
+ FD_SET(oc->fd, &OutputPending); /* set the bit again */
+ NewOutputPending = TRUE;
+ }
+ else
+ (void)FlushClient(client, oc, (char *)NULL, 0);
+ }
+ }
+#else /* WIN32 */
+ FD_ZERO(&newOutputPending);
+ for (base = 0; base < XFD_SETCOUNT(&OutputPending); base++)
+ {
+ index = XFD_FD(&OutputPending, base);
+ if ((index = GetConnectionTranslation(index)) == 0)
+ continue;
+ client = clients[index];
+ if (client->clientGone)
+ continue;
+ oc = (OsCommPtr)client->osPrivate;
+ if (
+ FD_ISSET(oc->fd, &ClientsWithInput))
+ {
+ FD_SET(oc->fd, &newOutputPending); /* set the bit again */
+ NewOutputPending = TRUE;
+ }
+ else
+ (void)FlushClient(client, oc, (char *)NULL, 0);
+ }
+ XFD_COPYSET(&newOutputPending, &OutputPending);
+#endif /* WIN32 */
+}
+
+void
+FlushIfCriticalOutputPending(void)
+{
+ if (CriticalOutputPending)
+ FlushAllOutput();
+}
+
+void
+SetCriticalOutputPending(void)
+{
+ CriticalOutputPending = TRUE;
+}
+
+/*****************
+ * WriteToClient
+ * Copies buf into ClientPtr.buf if it fits (with padding), else
+ * flushes ClientPtr.buf and buf to client. As of this writing,
+ * every use of WriteToClient is cast to void, and the result
+ * is ignored. Potentially, this could be used by requests
+ * that are sending several chunks of data and want to break
+ * out of a loop on error. Thus, we will leave the type of
+ * this routine as int.
+ *****************/
+
+int
+WriteToClient (ClientPtr who, int count, const void *__buf)
+{
+ OsCommPtr oc;
+ ConnectionOutputPtr oco;
+ int padBytes;
+ const char *buf = __buf;
+#ifdef DEBUG_COMMUNICATION
+ Bool multicount = FALSE;
+#endif
+ if (!count || !who || who == serverClient || who->clientGone)
+ return(0);
+ oc = who->osPrivate;
+ oco = oc->output;
+#ifdef DEBUG_COMMUNICATION
+ {
+ char info[128];
+ xError *err;
+ xGenericReply *rep;
+ xEvent *ev;
+
+ if (!who->replyBytesRemaining) {
+ switch(buf[0]) {
+ case X_Reply:
+ rep = (xGenericReply*)buf;
+ if (rep->sequenceNumber == who->sequence) {
+ snprintf(info,127,"Xreply: type: 0x%x data: 0x%x "
+ "len: %i seq#: 0x%x", rep->type, rep->data1,
+ rep->length, rep->sequenceNumber);
+ multicount = TRUE;
+ }
+ break;
+ case X_Error:
+ err = (xError*)buf;
+ snprintf(info,127,"Xerror: Code: 0x%x resID: 0x%x maj: 0x%x "
+ "min: %x", err->errorCode,err->resourceID,
+ err->minorCode,err->majorCode);
+ break;
+ default:
+ if ((buf[0] & 0x7f) == KeymapNotify)
+ snprintf(info,127,"KeymapNotifyEvent: %i",buf[0]);
+ else {
+ ev = (xEvent*)buf;
+ snprintf(info,127,"XEvent: type: 0x%x detail: 0x%x "
+ "seq#: 0x%x", ev->u.u.type, ev->u.u.detail,
+ ev->u.u.sequenceNumber);
+ }
+ }
+ ErrorF("REPLY: ClientIDX: %i %s\n",who->index, info);
+ } else
+ multicount = TRUE;
+ }
+#endif
+
+ if (!oco)
+ {
+ if ((oco = FreeOutputs))
+ {
+ FreeOutputs = oco->next;
+ }
+ else if (!(oco = AllocateOutputBuffer()))
+ {
+ if (oc->trans_conn) {
+ _XSERVTransDisconnect(oc->trans_conn);
+ _XSERVTransClose(oc->trans_conn);
+ oc->trans_conn = NULL;
+ }
+ MarkClientException(who);
+ return -1;
+ }
+ oc->output = oco;
+ }
+
+ padBytes = padlength[count & 3];
+
+ if(ReplyCallback)
+ {
+ ReplyInfoRec replyinfo;
+
+ replyinfo.client = who;
+ replyinfo.replyData = buf;
+ replyinfo.dataLenBytes = count + padBytes;
+ if (who->replyBytesRemaining)
+ { /* still sending data of an earlier reply */
+ who->replyBytesRemaining -= count + padBytes;
+ replyinfo.startOfReply = FALSE;
+ replyinfo.bytesRemaining = who->replyBytesRemaining;
+ CallCallbacks((&ReplyCallback), (void *)&replyinfo);
+ }
+ else if (who->clientState == ClientStateRunning
+ && buf[0] == X_Reply)
+ { /* start of new reply */
+ CARD32 replylen;
+ unsigned long bytesleft;
+
+ replylen = ((xGenericReply *)buf)->length;
+ if (who->swapped)
+ swapl(&replylen);
+ bytesleft = (replylen * 4) + SIZEOF(xReply) - count - padBytes;
+ replyinfo.startOfReply = TRUE;
+ replyinfo.bytesRemaining = who->replyBytesRemaining = bytesleft;
+ CallCallbacks((&ReplyCallback), (void *)&replyinfo);
+ }
+ }
+#ifdef DEBUG_COMMUNICATION
+ else if (multicount) {
+ if (who->replyBytesRemaining) {
+ who->replyBytesRemaining -= (count + padBytes);
+ } else {
+ CARD32 replylen;
+ replylen = ((xGenericReply *)buf)->length;
+ who->replyBytesRemaining =
+ (replylen * 4) + SIZEOF(xReply) - count - padBytes;
+ }
+ }
+#endif
+ if (oco->count == 0 || oco->count + count + padBytes > oco->size)
+ {
+ FD_CLR(oc->fd, &OutputPending);
+ if(!XFD_ANYSET(&OutputPending)) {
+ CriticalOutputPending = FALSE;
+ NewOutputPending = FALSE;
+ }
+ return FlushClient(who, oc, buf, count);
+ }
+
+ NewOutputPending = TRUE;
+ FD_SET(oc->fd, &OutputPending);
+ memmove((char *)oco->buf + oco->count, buf, count);
+ oco->count += count;
+ if (padBytes) {
+ memset(oco->buf + oco->count, '\0', padBytes);
+ oco->count += padBytes;
+ }
+ return(count);
+}
+
+ /********************
+ * FlushClient()
+ * If the client isn't keeping up with us, then we try to continue
+ * buffering the data and set the apropriate bit in ClientsWritable
+ * (which is used by WaitFor in the select). If the connection yields
+ * a permanent error, or we can't allocate any more space, we then
+ * close the connection.
+ *
+ **********************/
+
+int
+FlushClient(ClientPtr who, OsCommPtr oc, const void *__extraBuf, int extraCount)
+{
+ ConnectionOutputPtr oco = oc->output;
+ int connection = oc->fd;
+ XtransConnInfo trans_conn = oc->trans_conn;
+ struct iovec iov[3];
+ static char padBuffer[3];
+ const char *extraBuf = __extraBuf;
+ long written;
+ long padsize;
+ long notWritten;
+ long todo;
+
+ if (!oco)
+ return 0;
+ written = 0;
+ padsize = padlength[extraCount & 3];
+ notWritten = oco->count + extraCount + padsize;
+
+ if (!notWritten)
+ return 0;
+
+ if (FlushCallback)
+ CallCallbacks(&FlushCallback, who);
+
+ todo = notWritten;
+ while (notWritten) {
+ long before = written; /* amount of whole thing written */
+ long remain = todo; /* amount to try this time, <= notWritten */
+ int i = 0;
+ long len;
+
+ /* You could be very general here and have "in" and "out" iovecs
+ * and write a loop without using a macro, but what the heck. This
+ * translates to:
+ *
+ * how much of this piece is new?
+ * if more new then we are trying this time, clamp
+ * if nothing new
+ * then bump down amount already written, for next piece
+ * else put new stuff in iovec, will need all of next piece
+ *
+ * Note that todo had better be at least 1 or else we'll end up
+ * writing 0 iovecs.
+ */
+#define InsertIOV(pointer, length) \
+ len = (length) - before; \
+ if (len > remain) \
+ len = remain; \
+ if (len <= 0) { \
+ before = (-len); \
+ } else { \
+ iov[i].iov_len = len; \
+ iov[i].iov_base = (pointer) + before; \
+ i++; \
+ remain -= len; \
+ before = 0; \
+ }
+
+ InsertIOV ((char *)oco->buf, oco->count)
+ InsertIOV ((char *)extraBuf, extraCount)
+ InsertIOV (padBuffer, padsize)
+
+ errno = 0;
+ if (trans_conn && (len = _XSERVTransWritev(trans_conn, iov, i)) >= 0)
+ {
+ written += len;
+ notWritten -= len;
+ todo = notWritten;
+ }
+ else if (ETEST(errno)
+#ifdef SUNSYSV /* check for another brain-damaged OS bug */
+ || (errno == 0)
+#endif
+#ifdef EMSGSIZE /* check for another brain-damaged OS bug */
+ || ((errno == EMSGSIZE) && (todo == 1))
+#endif
+ )
+ {
+ /* If we've arrived here, then the client is stuffed to the gills
+ and not ready to accept more. Make a note of it and buffer
+ the rest. */
+ FD_SET(connection, &ClientsWriteBlocked);
+ AnyWritesPending = TRUE;
+
+ if (written < oco->count)
+ {
+ if (written > 0)
+ {
+ oco->count -= written;
+ memmove((char *)oco->buf,
+ (char *)oco->buf + written,
+ oco->count);
+ written = 0;
+ }
+ }
+ else
+ {
+ written -= oco->count;
+ oco->count = 0;
+ }
+
+ if (notWritten > oco->size)
+ {
+ unsigned char *obuf = NULL;
+
+ if (notWritten + BUFSIZE <= INT_MAX) {
+ obuf = realloc(oco->buf, notWritten + BUFSIZE);
+ }
+ if (!obuf)
+ {
+ _XSERVTransDisconnect(oc->trans_conn);
+ _XSERVTransClose(oc->trans_conn);
+ oc->trans_conn = NULL;
+ MarkClientException(who);
+ oco->count = 0;
+ return(-1);
+ }
+ oco->size = notWritten + BUFSIZE;
+ oco->buf = obuf;
+ }
+
+ /* If the amount written extended into the padBuffer, then the
+ difference "extraCount - written" may be less than 0 */
+ if ((len = extraCount - written) > 0)
+ memmove ((char *)oco->buf + oco->count,
+ extraBuf + written,
+ len);
+
+ oco->count = notWritten; /* this will include the pad */
+ /* return only the amount explicitly requested */
+ return extraCount;
+ }
+#ifdef EMSGSIZE /* check for another brain-damaged OS bug */
+ else if (errno == EMSGSIZE)
+ {
+ todo >>= 1;
+ }
+#endif
+ else
+ {
+ if (oc->trans_conn)
+ {
+ _XSERVTransDisconnect(oc->trans_conn);
+ _XSERVTransClose(oc->trans_conn);
+ oc->trans_conn = NULL;
+ }
+ MarkClientException(who);
+ oco->count = 0;
+ return(-1);
+ }
+ }
+
+ /* everything was flushed out */
+ oco->count = 0;
+ /* check to see if this client was write blocked */
+ if (AnyWritesPending)
+ {
+ FD_CLR(oc->fd, &ClientsWriteBlocked);
+ if (!XFD_ANYSET(&ClientsWriteBlocked) && NumNotifyWriteFd == 0)
+ AnyWritesPending = FALSE;
+
+ }
+ if (oco->size > BUFWATERMARK)
+ {
+ free(oco->buf);
+ free(oco);
+ }
+ else
+ {
+ oco->next = FreeOutputs;
+ FreeOutputs = oco;
+ }
+ oc->output = (ConnectionOutputPtr)NULL;
+ return extraCount; /* return only the amount explicitly requested */
+}
+
+ConnectionInputPtr
+AllocateInputBuffer(void)
+{
+ ConnectionInputPtr oci;
+
+ oci = (ConnectionInputPtr)malloc(sizeof(ConnectionInput));
+ if (!oci)
+ return (ConnectionInputPtr)NULL;
+ oci->buffer = (char *)malloc(BUFSIZE);
+ if (!oci->buffer)
+ {
+ free(oci);
+ return (ConnectionInputPtr)NULL;
+ }
+ oci->size = BUFSIZE;
+ oci->bufptr = oci->buffer;
+ oci->bufcnt = 0;
+ oci->lenLastReq = 0;
+ oci->ignoreBytes = 0;
+ return oci;
+}
+
+ConnectionOutputPtr
+AllocateOutputBuffer(void)
+{
+ ConnectionOutputPtr oco;
+
+ oco = (ConnectionOutputPtr)malloc(sizeof(ConnectionOutput));
+ if (!oco)
+ return (ConnectionOutputPtr)NULL;
+ oco->buf = (unsigned char *) malloc(BUFSIZE);
+ if (!oco->buf)
+ {
+ free(oco);
+ return (ConnectionOutputPtr)NULL;
+ }
+ oco->size = BUFSIZE;
+ oco->count = 0;
+ return oco;
+}
+
+void
+FreeOsBuffers(OsCommPtr oc)
+{
+ ConnectionInputPtr oci;
+ ConnectionOutputPtr oco;
+
+ if (AvailableInput == oc)
+ AvailableInput = (OsCommPtr)NULL;
+ if ((oci = oc->input))
+ {
+ if (FreeInputs)
+ {
+ free(oci->buffer);
+ free(oci);
+ }
+ else
+ {
+ FreeInputs = oci;
+ oci->next = (ConnectionInputPtr)NULL;
+ oci->bufptr = oci->buffer;
+ oci->bufcnt = 0;
+ oci->lenLastReq = 0;
+ oci->ignoreBytes = 0;
+ }
+ }
+ if ((oco = oc->output))
+ {
+ if (FreeOutputs)
+ {
+ free(oco->buf);
+ free(oco);
+ }
+ else
+ {
+ FreeOutputs = oco;
+ oco->next = (ConnectionOutputPtr)NULL;
+ oco->count = 0;
+ }
+ }
+}
+
+void
+ResetOsBuffers(void)
+{
+ ConnectionInputPtr oci;
+ ConnectionOutputPtr oco;
+
+ while ((oci = FreeInputs))
+ {
+ FreeInputs = oci->next;
+ free(oci->buffer);
+ free(oci);
+ }
+ while ((oco = FreeOutputs))
+ {
+ FreeOutputs = oco->next;
+ free(oco->buf);
+ free(oco);
+ }
+}
diff --git a/nx-X11/programs/Xserver/os/log.c b/nx-X11/programs/Xserver/os/log.c
new file mode 100644
index 000000000..0ead6e9f0
--- /dev/null
+++ b/nx-X11/programs/Xserver/os/log.c
@@ -0,0 +1,779 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* nx-X11, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+
+Copyright 1987, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
+Copyright 1994 Quarterdeck Office Systems.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Digital and
+Quarterdeck not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+DIGITAL AND QUARTERDECK DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT
+OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
+OR PERFORMANCE OF THIS SOFTWARE.
+
+*/
+
+/*
+ * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the copyright holder(s)
+ * and author(s) shall not be used in advertising or otherwise to promote
+ * the sale, use or other dealings in this Software without prior written
+ * authorization from the copyright holder(s) and author(s).
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <nx-X11/Xos.h>
+#include <stdio.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <stdarg.h>
+#include <stdlib.h> /* for malloc() */
+#include <errno.h>
+
+#include "input.h"
+#include "site.h"
+#include "opaque.h"
+
+#ifdef WIN32
+#include <process.h>
+#define getpid(x) _getpid(x)
+#endif
+
+#ifdef NX_TRANS_SOCKET
+
+#include <nx/NX.h>
+
+#endif
+
+#ifdef DDXOSVERRORF
+void (*OsVendorVErrorFProc)(const char *, va_list args) = NULL;
+#ifdef NX_TRANS_EXIT
+int OsVendorVErrorFFatal = 0;
+#endif
+#endif
+
+static FILE *logFile = NULL;
+static Bool logFlush = FALSE;
+static Bool logSync = FALSE;
+static int logVerbosity = DEFAULT_LOG_VERBOSITY;
+static int logFileVerbosity = DEFAULT_LOG_FILE_VERBOSITY;
+
+/* Buffer to information logged before the log file is opened. */
+static char *saveBuffer = NULL;
+static int bufferSize = 0, bufferUnused = 0, bufferPos = 0;
+static Bool needBuffer = TRUE;
+
+/* Prefix strings for log messages. */
+#ifndef X_UNKNOWN_STRING
+#define X_UNKNOWN_STRING "(\?\?)"
+#endif
+#ifndef X_PROBE_STRING
+#define X_PROBE_STRING "(--)"
+#endif
+#ifndef X_CONFIG_STRING
+#define X_CONFIG_STRING "(**)"
+#endif
+#ifndef X_DEFAULT_STRING
+#define X_DEFAULT_STRING "(==)"
+#endif
+#ifndef X_CMDLINE_STRING
+#define X_CMDLINE_STRING "(++)"
+#endif
+#ifndef X_NOTICE_STRING
+#define X_NOTICE_STRING "(!!)"
+#endif
+#ifndef X_ERROR_STRING
+#define X_ERROR_STRING "(EE)"
+#endif
+#ifndef X_WARNING_STRING
+#define X_WARNING_STRING "(WW)"
+#endif
+#ifndef X_INFO_STRING
+#define X_INFO_STRING "(II)"
+#endif
+#ifndef X_NOT_IMPLEMENTED_STRING
+#define X_NOT_IMPLEMENTED_STRING "(NI)"
+#endif
+
+/*
+ * LogFilePrep is called to setup files for logging, including getting
+ * an old file out of the way, but it doesn't actually open the file,
+ * since it may be used for renaming a file we're already logging to.
+ */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+
+static char *
+LogFilePrep(const char *fname, const char *backup, const char *idstring)
+{
+ char *logFileName = NULL;
+
+ if (asprintf(&logFileName, fname, idstring) == -1)
+ FatalError("Cannot allocate space for the log file name\n");
+
+ if (backup && *backup) {
+ struct stat buf;
+
+ if (!stat(logFileName, &buf) && S_ISREG(buf.st_mode)) {
+ char *suffix;
+ char *oldLog;
+
+ if ((asprintf(&suffix, backup, idstring) == -1) ||
+ (asprintf(&oldLog, "%s%s", logFileName, suffix) == -1)) {
+ FatalError("Cannot allocate space for the log file name\n");
+ }
+ free(suffix);
+
+ if (rename(logFileName, oldLog) == -1) {
+ FatalError("Cannot move old log file \"%s\" to \"%s\"\n",
+ logFileName, oldLog);
+ }
+ free(oldLog);
+ }
+ }
+ else {
+ if (remove(logFileName) != 0) {
+ FatalError("Cannot remove old log file \"%s\": %s\n",
+ logFileName, strerror(errno));
+ }
+ }
+
+ return logFileName;
+}
+#pragma GCC diagnostic pop
+
+/*
+ * LogInit is called to start logging to a file. It is also called (with
+ * NULL arguments) when logging to a file is not wanted. It must always be
+ * called, otherwise log messages will continue to accumulate in a buffer.
+ *
+ * %s, if present in the fname or backup strings, is expanded to the display
+ * string (or to a string containing the pid if the display is not yet set).
+ */
+
+static char *saved_log_fname;
+static char *saved_log_backup;
+static char *saved_log_tempname;
+
+const char *
+LogInit(const char *fname, const char *backup)
+{
+ char *logFileName = NULL;
+
+ if (fname && *fname) {
+ if (displayfd != -1) {
+ /* Display isn't set yet, so we can't use it in filenames yet. */
+ char pidstring[32];
+ snprintf(pidstring, sizeof(pidstring), "pid-%ld",
+ (unsigned long) getpid());
+ logFileName = LogFilePrep(fname, backup, pidstring);
+ saved_log_tempname = logFileName;
+
+ /* Save the patterns for use when the display is named. */
+ saved_log_fname = strdup(fname);
+ if (backup == NULL)
+ saved_log_backup = NULL;
+ else
+ saved_log_backup = strdup(backup);
+ } else
+ logFileName = LogFilePrep(fname, backup, display);
+ if ((logFile = fopen(logFileName, "w")) == NULL)
+ FatalError("Cannot open log file \"%s\"\n", logFileName);
+ setvbuf(logFile, NULL, _IONBF, 0);
+
+ /* Flush saved log information. */
+ if (saveBuffer && bufferSize > 0) {
+ fwrite(saveBuffer, bufferPos, 1, logFile);
+ fflush(logFile);
+#ifndef WIN32
+ fsync(fileno(logFile));
+#endif
+ }
+ }
+
+ /*
+ * Unconditionally free the buffer, and flag that the buffer is no longer
+ * needed.
+ */
+ if (saveBuffer && bufferSize > 0) {
+ free(saveBuffer); /* Must be free(), not free() */
+ saveBuffer = NULL;
+ bufferSize = 0;
+ }
+ needBuffer = FALSE;
+
+ return logFileName;
+}
+
+void
+LogSetDisplay(void)
+{
+ if (saved_log_fname) {
+ char *logFileName;
+
+ logFileName = LogFilePrep(saved_log_fname, saved_log_backup, display);
+
+ if (rename(saved_log_tempname, logFileName) == 0) {
+ LogMessageVerb(X_PROBED, 0,
+ "Log file renamed from \"%s\" to \"%s\"\n",
+ saved_log_tempname, logFileName);
+
+ if (strlen(saved_log_tempname) >= strlen(logFileName))
+ strncpy(saved_log_tempname, logFileName,
+ strlen(saved_log_tempname));
+ }
+ else {
+ ErrorF("Failed to rename log file \"%s\" to \"%s\": %s\n",
+ saved_log_tempname, logFileName, strerror(errno));
+ }
+
+ /* free newly allocated string - can't free old one since existing
+ pointers to it may exist in DDX callers. */
+ free(logFileName);
+ free(saved_log_fname);
+ free(saved_log_backup);
+ }
+}
+
+void
+LogClose()
+{
+ if (logFile) {
+ fclose(logFile);
+ logFile = NULL;
+ }
+}
+
+Bool
+LogSetParameter(LogParameter param, int value)
+{
+ switch (param) {
+ case XLOG_FLUSH:
+ logFlush = value ? TRUE : FALSE;
+ return TRUE;
+ case XLOG_SYNC:
+ logSync = value ? TRUE : FALSE;
+ return TRUE;
+ case XLOG_VERBOSITY:
+ logVerbosity = value;
+ return TRUE;
+ case XLOG_FILE_VERBOSITY:
+ logFileVerbosity = value;
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+/* This function does the actual log message writes. */
+
+void
+LogVWrite(int verb, const char *f, va_list args)
+{
+ static char tmpBuffer[1024];
+ int len = 0;
+
+ /*
+ * Since a va_list can only be processed once, write the string to a
+ * buffer, and then write the buffer out to the appropriate output
+ * stream(s).
+ */
+ if (verb < 0 || logFileVerbosity >= verb || logVerbosity >= verb) {
+ vsnprintf(tmpBuffer, sizeof(tmpBuffer), f, args);
+#ifdef NX_TRANS_EXIT
+ /*
+ * Beautify the message. Make the
+ * first letter uppercase.
+ */
+
+ *tmpBuffer = toupper(*tmpBuffer);
+
+ /*
+ * Remove the trailing newline.
+ */
+
+ if (strlen(tmpBuffer) > 0 &&
+ *(tmpBuffer + strlen(tmpBuffer) - 1) == '\n') {
+ *(tmpBuffer + strlen(tmpBuffer) - 1) = '\0';
+ }
+
+ /*
+ * Remove the trailing full-stop.
+ */
+
+ if (strlen(tmpBuffer) > 0 &&
+ *(tmpBuffer + strlen(tmpBuffer) - 1) == '.') {
+ *(tmpBuffer + strlen(tmpBuffer) - 1) = '\0';
+ }
+#endif /* #ifdef NX_TRANS_EXIT */
+ len = strlen(tmpBuffer);
+ }
+ if ((verb < 0 || logVerbosity >= verb) && len > 0)
+ fwrite(tmpBuffer, len, 1, stderr);
+ if ((verb < 0 || logFileVerbosity >= verb) && len > 0) {
+ if (logFile) {
+ fwrite(tmpBuffer, len, 1, logFile);
+ if (logFlush) {
+ fflush(logFile);
+#ifndef WIN32
+ if (logSync)
+ fsync(fileno(logFile));
+#endif
+ }
+ } else if (needBuffer) {
+ /*
+ * Note, this code is used before OsInit() has been called, so
+ * malloc() and friends can't be used.
+ */
+ if (len > bufferUnused) {
+ bufferSize += 1024;
+ bufferUnused += 1024;
+ if (saveBuffer)
+ saveBuffer = realloc(saveBuffer, bufferSize);
+ else
+ saveBuffer = malloc(bufferSize);
+ if (!saveBuffer)
+ FatalError("realloc() failed while saving log messages\n");
+ }
+ bufferUnused -= len;
+ memcpy(saveBuffer + bufferPos, tmpBuffer, len);
+ bufferPos += len;
+ }
+ }
+}
+
+void
+LogWrite(int verb, const char *f, ...)
+{
+ va_list args;
+
+ va_start(args, f);
+ LogVWrite(verb, f, args);
+ va_end(args);
+}
+
+void
+LogVMessageVerb(MessageType type, int verb, const char *format, va_list args)
+{
+ const char *s = X_UNKNOWN_STRING;
+ char *tmpBuf = NULL;
+
+ /* Ignore verbosity for X_ERROR */
+ if (logVerbosity >= verb || logFileVerbosity >= verb || type == X_ERROR) {
+ switch (type) {
+ case X_PROBED:
+ s = X_PROBE_STRING;
+ break;
+ case X_CONFIG:
+ s = X_CONFIG_STRING;
+ break;
+ case X_DEFAULT:
+ s = X_DEFAULT_STRING;
+ break;
+ case X_CMDLINE:
+ s = X_CMDLINE_STRING;
+ break;
+ case X_NOTICE:
+ s = X_NOTICE_STRING;
+ break;
+ case X_ERROR:
+ s = X_ERROR_STRING;
+ if (verb > 0)
+ verb = 0;
+ break;
+ case X_WARNING:
+ s = X_WARNING_STRING;
+ break;
+ case X_INFO:
+ s = X_INFO_STRING;
+ break;
+ case X_NOT_IMPLEMENTED:
+ s = X_NOT_IMPLEMENTED_STRING;
+ break;
+ case X_UNKNOWN:
+ s = X_UNKNOWN_STRING;
+ break;
+ case X_NONE:
+ s = NULL;
+ break;
+ }
+
+ /*
+ * Prefix the format string with the message type. We do it this way
+ * so that LogVWrite() is only called once per message.
+ */
+ if (s) {
+ tmpBuf = malloc(strlen(format) + strlen(s) + 1 + 1);
+ /* Silently return if malloc fails here. */
+ if (!tmpBuf)
+ return;
+ sprintf(tmpBuf, "%s ", s);
+ strcat(tmpBuf, format);
+ LogVWrite(verb, tmpBuf, args);
+ free(tmpBuf);
+ } else
+ LogVWrite(verb, format, args);
+ }
+}
+
+/* Log message with verbosity level specified. */
+void
+LogMessageVerb(MessageType type, int verb, const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ LogVMessageVerb(type, verb, format, ap);
+ va_end(ap);
+}
+
+/* Log a message with the standard verbosity level of 1. */
+void
+LogMessage(MessageType type, const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ LogVMessageVerb(type, 1, format, ap);
+ va_end(ap);
+}
+
+#ifdef __GNUC__
+void AbortServer(void) __attribute__((noreturn));
+#endif
+
+void
+AbortServer(void)
+{
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
+ fprintf(stderr, "AbortServer: Going to abort the current server.\n");
+#endif
+ OsCleanup(TRUE);
+ AbortDDX();
+ fflush(stderr);
+ if (CoreDump)
+ abort();
+#ifdef NX_TRANS_EXIT
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "AbortServer: Going to clean up NX resources and exit.\n");
+#endif
+ NXTransExit(1);
+#else /* #ifdef NX_TRANS_EXIT */
+ exit (1);
+#endif
+}
+
+#ifndef AUDIT_PREFIX
+#define AUDIT_PREFIX "AUDIT: %s: %ld %s: "
+#endif
+#ifndef AUDIT_TIMEOUT
+#define AUDIT_TIMEOUT ((CARD32)(120 * 1000)) /* 2 mn */
+#endif
+
+static int nrepeat = 0;
+static int oldlen = -1;
+static OsTimerPtr auditTimer = NULL;
+
+void
+FreeAuditTimer(void)
+{
+ if (auditTimer != NULL) {
+ /* Force output of pending messages */
+ TimerForce(auditTimer);
+ TimerFree(auditTimer);
+ auditTimer = NULL;
+ }
+}
+
+static char *
+AuditPrefix(void)
+{
+ time_t tm;
+ char *autime, *s;
+ char *tmpBuf;
+ int len;
+
+ time(&tm);
+ autime = ctime(&tm);
+ if ((s = strchr(autime, '\n')))
+ *s = '\0';
+ if ((s = strrchr(argvGlobal[0], '/')))
+ s++;
+ else
+ s = argvGlobal[0];
+ len = strlen(AUDIT_PREFIX) + strlen(autime) + 10 + strlen(s) + 1;
+ tmpBuf = malloc(len);
+ if (!tmpBuf)
+ return NULL;
+ snprintf(tmpBuf, len, AUDIT_PREFIX, autime, (unsigned long)getpid(), s);
+ return tmpBuf;
+}
+
+void
+AuditF(const char * f, ...)
+{
+ va_list args;
+
+ va_start(args, f);
+
+ VAuditF(f, args);
+ va_end(args);
+}
+
+static CARD32
+AuditFlush(OsTimerPtr timer, CARD32 now, void * arg)
+{
+ char *prefix;
+
+ if (nrepeat > 0) {
+ prefix = AuditPrefix();
+ ErrorF("%slast message repeated %d times\n",
+ prefix != NULL ? prefix : "", nrepeat);
+ nrepeat = 0;
+ if (prefix != NULL)
+ free(prefix);
+ return AUDIT_TIMEOUT;
+ } else {
+ /* if the timer expires without anything to print, flush the message */
+ oldlen = -1;
+ return 0;
+ }
+}
+
+void
+VAuditF(const char *f, va_list args)
+{
+ char *prefix;
+ char buf[1024];
+ int len;
+ static char oldbuf[1024];
+
+ prefix = AuditPrefix();
+ len = vsnprintf(buf, sizeof(buf), f, args);
+
+ if (len == oldlen && strcmp(buf, oldbuf) == 0) {
+ /* Message already seen */
+ nrepeat++;
+ } else {
+ /* new message */
+ if (auditTimer != NULL)
+ TimerForce(auditTimer);
+ ErrorF("%s%s", prefix != NULL ? prefix : "", buf);
+ strlcpy(oldbuf, buf, sizeof(oldbuf));
+ oldlen = len;
+ nrepeat = 0;
+ auditTimer = TimerSet(auditTimer, 0, AUDIT_TIMEOUT, AuditFlush, NULL);
+ }
+ if (prefix != NULL)
+ free(prefix);
+}
+
+void
+FatalError(const char *f, ...)
+{
+ va_list args;
+ static Bool beenhere = FALSE;
+
+#ifdef NX_TRANS_EXIT
+ if (beenhere) {
+ fprintf(stderr, "Error: Aborting session with fatal error function reentered.\n");
+ }
+ else {
+ /*
+ * Tell to the log function that this
+ * is a fatal error.
+ */
+
+ OsVendorVErrorFFatal = 1;
+
+ fprintf(stderr, "Error: Aborting session with '");
+
+ va_start(args, f);
+ VErrorF(f, args);
+ va_end(args);
+
+ fprintf(stderr, "'.\n");
+ }
+#else /* #ifdef NX_TRANS_EXIT */
+ if (beenhere)
+ ErrorF("\nFatalError re-entered, aborting\n");
+ else
+ ErrorF("\nFatal server error:\n");
+
+ va_start(args, f);
+ VErrorF(f, args);
+ va_end(args);
+ ErrorF("\n");
+#endif /* #ifdef NX_TRANS_EXIT */
+#ifdef DDXOSFATALERROR
+ if (!beenhere)
+ OsVendorFatalError();
+#endif
+#ifdef ABORTONFATALERROR
+ abort();
+#endif
+ if (!beenhere) {
+ beenhere = TRUE;
+ AbortServer();
+ } else
+ abort();
+ /*NOTREACHED*/
+}
+
+void
+VErrorF(const char *f, va_list args)
+{
+#ifdef DDXOSVERRORF
+ if (OsVendorVErrorFProc)
+ OsVendorVErrorFProc(f, args);
+ else
+ LogVWrite(-1, f, args);
+#else
+ LogVWrite(-1, f, args);
+#endif
+}
+
+void
+ErrorF(const char * f, ...)
+{
+ va_list args;
+
+ va_start(args, f);
+ VErrorF(f, args);
+ va_end(args);
+}
+
+/* A perror() workalike. */
+
+#ifndef NEED_STRERROR
+#ifdef SYSV
+#if !defined(ISC) || defined(ISC202) || defined(ISC22)
+#define NEED_STRERROR
+#endif
+#endif
+#endif
+
+#if defined(NEED_STRERROR) && !defined(strerror)
+extern char *sys_errlist[];
+extern int sys_nerr;
+#define strerror(n) \
+ ((n) >= 0 && (n) < sys_nerr) ? sys_errlist[(n)] : "unknown error"
+#endif
+
+void
+Error(char *str)
+{
+ char *err = NULL;
+ int saveErrno = errno;
+
+ if (str) {
+ err = malloc(strlen(strerror(saveErrno)) + strlen(str) + 2 + 1);
+ if (!err)
+ return;
+ sprintf(err, "%s: ", str);
+ strcat(err, strerror(saveErrno));
+ LogWrite(-1, "%s", err);
+ } else
+ LogWrite(-1, "%s", strerror(saveErrno));
+}
+
+void
+LogPrintMarkers()
+{
+ /* Show what the message marker symbols mean. */
+ ErrorF("Markers: ");
+ LogMessageVerb(X_PROBED, -1, "probed, ");
+ LogMessageVerb(X_CONFIG, -1, "from config file, ");
+ LogMessageVerb(X_DEFAULT, -1, "default setting,\n\t");
+ LogMessageVerb(X_CMDLINE, -1, "from command line, ");
+ LogMessageVerb(X_NOTICE, -1, "notice, ");
+ LogMessageVerb(X_INFO, -1, "informational,\n\t");
+ LogMessageVerb(X_WARNING, -1, "warning, ");
+ LogMessageVerb(X_ERROR, -1, "error, ");
+ LogMessageVerb(X_NOT_IMPLEMENTED, -1, "not implemented, ");
+ LogMessageVerb(X_UNKNOWN, -1, "unknown.\n");
+}
+
diff --git a/nx-X11/programs/Xserver/os/mitauth.c b/nx-X11/programs/Xserver/os/mitauth.c
new file mode 100644
index 000000000..578f8ba42
--- /dev/null
+++ b/nx-X11/programs/Xserver/os/mitauth.c
@@ -0,0 +1,197 @@
+/*
+
+Copyright 1988, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+
+/*
+ * MIT-MAGIC-COOKIE-1 authorization scheme
+ * Author: Keith Packard, MIT X Consortium
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <nx-X11/X.h>
+#include "os.h"
+#include "osdep.h"
+#include "dixstruct.h"
+
+static struct auth {
+ struct auth *next;
+ unsigned short len;
+ char *data;
+ XID id;
+} *mit_auth;
+
+int
+MitAddCookie (
+ unsigned short data_length,
+ char *data,
+ XID id)
+{
+ struct auth *new;
+
+ new = (struct auth *) malloc (sizeof (struct auth));
+ if (!new)
+ return 0;
+ new->data = (char *) malloc ((unsigned) data_length);
+ if (!new->data) {
+ free(new);
+ return 0;
+ }
+ new->next = mit_auth;
+ mit_auth = new;
+ memmove(new->data, data, (int) data_length);
+ new->len = data_length;
+ new->id = id;
+ return 1;
+}
+
+XID
+MitCheckCookie (
+ unsigned short data_length,
+ char *data,
+ ClientPtr client,
+ char **reason)
+{
+ struct auth *auth;
+
+ for (auth = mit_auth; auth; auth=auth->next) {
+ if (data_length == auth->len &&
+ timingsafe_memcmp (data, auth->data, (int) data_length) == 0)
+ return auth->id;
+ }
+ *reason = "Invalid MIT-MAGIC-COOKIE-1 key";
+ return (XID) -1;
+}
+
+int
+MitResetCookie (void)
+{
+ struct auth *auth, *next;
+
+ for (auth = mit_auth; auth; auth=next) {
+ next = auth->next;
+ free (auth->data);
+ free (auth);
+ }
+ mit_auth = 0;
+ return 0;
+}
+
+XID
+MitToID (
+ unsigned short data_length,
+ char *data)
+{
+ struct auth *auth;
+
+ for (auth = mit_auth; auth; auth=auth->next) {
+ if (data_length == auth->len &&
+ memcmp (data, auth->data, data_length) == 0)
+ return auth->id;
+ }
+ return (XID) -1;
+}
+
+int
+MitFromID (
+ XID id,
+ unsigned short *data_lenp,
+ char **datap)
+{
+ struct auth *auth;
+
+ for (auth = mit_auth; auth; auth=auth->next) {
+ if (id == auth->id) {
+ *data_lenp = auth->len;
+ *datap = auth->data;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int
+MitRemoveCookie (
+ unsigned short data_length,
+ char *data)
+{
+ struct auth *auth, *prev;
+
+ prev = 0;
+ for (auth = mit_auth; auth; prev = auth, auth=auth->next) {
+ if (data_length == auth->len &&
+ memcmp (data, auth->data, data_length) == 0)
+ {
+ if (prev)
+ prev->next = auth->next;
+ else
+ mit_auth = auth->next;
+ free (auth->data);
+ free (auth);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+#ifdef XCSECURITY
+
+static char cookie[16]; /* 128 bits */
+
+XID
+MitGenerateCookie (
+ unsigned data_length,
+ char *data,
+ XID id,
+ unsigned *data_length_return,
+ char **data_return)
+{
+ int i = 0;
+ int status;
+
+ while (data_length--)
+ {
+ cookie[i++] += *data++;
+ if (i >= sizeof (cookie)) i = 0;
+ }
+ GenerateRandomData(sizeof (cookie), cookie);
+ status = MitAddCookie(sizeof (cookie), cookie, id);
+ if (!status)
+ {
+ id = -1;
+ }
+ else
+ {
+ *data_return = cookie;
+ *data_length_return = sizeof (cookie);
+ }
+ return id;
+}
+
+#endif /* XCSECURITY */
diff --git a/nx-X11/programs/Xserver/os/oscolor.c b/nx-X11/programs/Xserver/os/oscolor.c
new file mode 100644
index 000000000..70940653f
--- /dev/null
+++ b/nx-X11/programs/Xserver/os/oscolor.c
@@ -0,0 +1,1661 @@
+/***********************************************************
+
+Copyright 1987, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "os.h"
+
+typedef struct _builtinColor {
+ unsigned char red;
+ unsigned char green;
+ unsigned char blue;
+ unsigned short name;
+} BuiltinColor;
+
+static const char BuiltinColorNames[] = {
+ "alice blue\0"
+ "AliceBlue\0"
+ "antique white\0"
+ "AntiqueWhite\0"
+ "AntiqueWhite1\0"
+ "AntiqueWhite2\0"
+ "AntiqueWhite3\0"
+ "AntiqueWhite4\0"
+ "aqua\0"
+ "aquamarine\0"
+ "aquamarine1\0"
+ "aquamarine2\0"
+ "aquamarine3\0"
+ "aquamarine4\0"
+ "azure\0"
+ "azure1\0"
+ "azure2\0"
+ "azure3\0"
+ "azure4\0"
+ "beige\0"
+ "bisque\0"
+ "bisque1\0"
+ "bisque2\0"
+ "bisque3\0"
+ "bisque4\0"
+ "black\0"
+ "blanched almond\0"
+ "BlanchedAlmond\0"
+ "blue\0"
+ "blue violet\0"
+ "blue1\0"
+ "blue2\0"
+ "blue3\0"
+ "blue4\0"
+ "BlueViolet\0"
+ "brown\0"
+ "brown1\0"
+ "brown2\0"
+ "brown3\0"
+ "brown4\0"
+ "burlywood\0"
+ "burlywood1\0"
+ "burlywood2\0"
+ "burlywood3\0"
+ "burlywood4\0"
+ "cadet blue\0"
+ "CadetBlue\0"
+ "CadetBlue1\0"
+ "CadetBlue2\0"
+ "CadetBlue3\0"
+ "CadetBlue4\0"
+ "chartreuse\0"
+ "chartreuse1\0"
+ "chartreuse2\0"
+ "chartreuse3\0"
+ "chartreuse4\0"
+ "chocolate\0"
+ "chocolate1\0"
+ "chocolate2\0"
+ "chocolate3\0"
+ "chocolate4\0"
+ "coral\0"
+ "coral1\0"
+ "coral2\0"
+ "coral3\0"
+ "coral4\0"
+ "cornflower blue\0"
+ "CornflowerBlue\0"
+ "cornsilk\0"
+ "cornsilk1\0"
+ "cornsilk2\0"
+ "cornsilk3\0"
+ "cornsilk4\0"
+ "crimson\0"
+ "cyan\0"
+ "cyan1\0"
+ "cyan2\0"
+ "cyan3\0"
+ "cyan4\0"
+ "dark blue\0"
+ "dark cyan\0"
+ "dark goldenrod\0"
+ "dark gray\0"
+ "dark green\0"
+ "dark grey\0"
+ "dark khaki\0"
+ "dark magenta\0"
+ "dark olive green\0"
+ "dark orange\0"
+ "dark orchid\0"
+ "dark red\0"
+ "dark salmon\0"
+ "dark sea green\0"
+ "dark slate blue\0"
+ "dark slate gray\0"
+ "dark slate grey\0"
+ "dark turquoise\0"
+ "dark violet\0"
+ "DarkBlue\0"
+ "DarkCyan\0"
+ "DarkGoldenrod\0"
+ "DarkGoldenrod1\0"
+ "DarkGoldenrod2\0"
+ "DarkGoldenrod3\0"
+ "DarkGoldenrod4\0"
+ "DarkGray\0"
+ "DarkGreen\0"
+ "DarkGrey\0"
+ "DarkKhaki\0"
+ "DarkMagenta\0"
+ "DarkOliveGreen\0"
+ "DarkOliveGreen1\0"
+ "DarkOliveGreen2\0"
+ "DarkOliveGreen3\0"
+ "DarkOliveGreen4\0"
+ "DarkOrange\0"
+ "DarkOrange1\0"
+ "DarkOrange2\0"
+ "DarkOrange3\0"
+ "DarkOrange4\0"
+ "DarkOrchid\0"
+ "DarkOrchid1\0"
+ "DarkOrchid2\0"
+ "DarkOrchid3\0"
+ "DarkOrchid4\0"
+ "DarkRed\0"
+ "DarkSalmon\0"
+ "DarkSeaGreen\0"
+ "DarkSeaGreen1\0"
+ "DarkSeaGreen2\0"
+ "DarkSeaGreen3\0"
+ "DarkSeaGreen4\0"
+ "DarkSlateBlue\0"
+ "DarkSlateGray\0"
+ "DarkSlateGray1\0"
+ "DarkSlateGray2\0"
+ "DarkSlateGray3\0"
+ "DarkSlateGray4\0"
+ "DarkSlateGrey\0"
+ "DarkTurquoise\0"
+ "DarkViolet\0"
+ "deep pink\0"
+ "deep sky blue\0"
+ "DeepPink\0"
+ "DeepPink1\0"
+ "DeepPink2\0"
+ "DeepPink3\0"
+ "DeepPink4\0"
+ "DeepSkyBlue\0"
+ "DeepSkyBlue1\0"
+ "DeepSkyBlue2\0"
+ "DeepSkyBlue3\0"
+ "DeepSkyBlue4\0"
+ "dim gray\0"
+ "dim grey\0"
+ "DimGray\0"
+ "DimGrey\0"
+ "dodger blue\0"
+ "DodgerBlue\0"
+ "DodgerBlue1\0"
+ "DodgerBlue2\0"
+ "DodgerBlue3\0"
+ "DodgerBlue4\0"
+ "firebrick\0"
+ "firebrick1\0"
+ "firebrick2\0"
+ "firebrick3\0"
+ "firebrick4\0"
+ "floral white\0"
+ "FloralWhite\0"
+ "forest green\0"
+ "ForestGreen\0"
+ "fuchsia\0"
+ "gainsboro\0"
+ "ghost white\0"
+ "GhostWhite\0"
+ "gold\0"
+ "gold1\0"
+ "gold2\0"
+ "gold3\0"
+ "gold4\0"
+ "goldenrod\0"
+ "goldenrod1\0"
+ "goldenrod2\0"
+ "goldenrod3\0"
+ "goldenrod4\0"
+ "gray\0"
+ "gray0\0"
+ "gray1\0"
+ "gray10\0"
+ "gray100\0"
+ "gray11\0"
+ "gray12\0"
+ "gray13\0"
+ "gray14\0"
+ "gray15\0"
+ "gray16\0"
+ "gray17\0"
+ "gray18\0"
+ "gray19\0"
+ "gray2\0"
+ "gray20\0"
+ "gray21\0"
+ "gray22\0"
+ "gray23\0"
+ "gray24\0"
+ "gray25\0"
+ "gray26\0"
+ "gray27\0"
+ "gray28\0"
+ "gray29\0"
+ "gray3\0"
+ "gray30\0"
+ "gray31\0"
+ "gray32\0"
+ "gray33\0"
+ "gray34\0"
+ "gray35\0"
+ "gray36\0"
+ "gray37\0"
+ "gray38\0"
+ "gray39\0"
+ "gray4\0"
+ "gray40\0"
+ "gray41\0"
+ "gray42\0"
+ "gray43\0"
+ "gray44\0"
+ "gray45\0"
+ "gray46\0"
+ "gray47\0"
+ "gray48\0"
+ "gray49\0"
+ "gray5\0"
+ "gray50\0"
+ "gray51\0"
+ "gray52\0"
+ "gray53\0"
+ "gray54\0"
+ "gray55\0"
+ "gray56\0"
+ "gray57\0"
+ "gray58\0"
+ "gray59\0"
+ "gray6\0"
+ "gray60\0"
+ "gray61\0"
+ "gray62\0"
+ "gray63\0"
+ "gray64\0"
+ "gray65\0"
+ "gray66\0"
+ "gray67\0"
+ "gray68\0"
+ "gray69\0"
+ "gray7\0"
+ "gray70\0"
+ "gray71\0"
+ "gray72\0"
+ "gray73\0"
+ "gray74\0"
+ "gray75\0"
+ "gray76\0"
+ "gray77\0"
+ "gray78\0"
+ "gray79\0"
+ "gray8\0"
+ "gray80\0"
+ "gray81\0"
+ "gray82\0"
+ "gray83\0"
+ "gray84\0"
+ "gray85\0"
+ "gray86\0"
+ "gray87\0"
+ "gray88\0"
+ "gray89\0"
+ "gray9\0"
+ "gray90\0"
+ "gray91\0"
+ "gray92\0"
+ "gray93\0"
+ "gray94\0"
+ "gray95\0"
+ "gray96\0"
+ "gray97\0"
+ "gray98\0"
+ "gray99\0"
+ "green\0"
+ "green yellow\0"
+ "green1\0"
+ "green2\0"
+ "green3\0"
+ "green4\0"
+ "GreenYellow\0"
+ "grey\0"
+ "grey0\0"
+ "grey1\0"
+ "grey10\0"
+ "grey100\0"
+ "grey11\0"
+ "grey12\0"
+ "grey13\0"
+ "grey14\0"
+ "grey15\0"
+ "grey16\0"
+ "grey17\0"
+ "grey18\0"
+ "grey19\0"
+ "grey2\0"
+ "grey20\0"
+ "grey21\0"
+ "grey22\0"
+ "grey23\0"
+ "grey24\0"
+ "grey25\0"
+ "grey26\0"
+ "grey27\0"
+ "grey28\0"
+ "grey29\0"
+ "grey3\0"
+ "grey30\0"
+ "grey31\0"
+ "grey32\0"
+ "grey33\0"
+ "grey34\0"
+ "grey35\0"
+ "grey36\0"
+ "grey37\0"
+ "grey38\0"
+ "grey39\0"
+ "grey4\0"
+ "grey40\0"
+ "grey41\0"
+ "grey42\0"
+ "grey43\0"
+ "grey44\0"
+ "grey45\0"
+ "grey46\0"
+ "grey47\0"
+ "grey48\0"
+ "grey49\0"
+ "grey5\0"
+ "grey50\0"
+ "grey51\0"
+ "grey52\0"
+ "grey53\0"
+ "grey54\0"
+ "grey55\0"
+ "grey56\0"
+ "grey57\0"
+ "grey58\0"
+ "grey59\0"
+ "grey6\0"
+ "grey60\0"
+ "grey61\0"
+ "grey62\0"
+ "grey63\0"
+ "grey64\0"
+ "grey65\0"
+ "grey66\0"
+ "grey67\0"
+ "grey68\0"
+ "grey69\0"
+ "grey7\0"
+ "grey70\0"
+ "grey71\0"
+ "grey72\0"
+ "grey73\0"
+ "grey74\0"
+ "grey75\0"
+ "grey76\0"
+ "grey77\0"
+ "grey78\0"
+ "grey79\0"
+ "grey8\0"
+ "grey80\0"
+ "grey81\0"
+ "grey82\0"
+ "grey83\0"
+ "grey84\0"
+ "grey85\0"
+ "grey86\0"
+ "grey87\0"
+ "grey88\0"
+ "grey89\0"
+ "grey9\0"
+ "grey90\0"
+ "grey91\0"
+ "grey92\0"
+ "grey93\0"
+ "grey94\0"
+ "grey95\0"
+ "grey96\0"
+ "grey97\0"
+ "grey98\0"
+ "grey99\0"
+ "honeydew\0"
+ "honeydew1\0"
+ "honeydew2\0"
+ "honeydew3\0"
+ "honeydew4\0"
+ "hot pink\0"
+ "HotPink\0"
+ "HotPink1\0"
+ "HotPink2\0"
+ "HotPink3\0"
+ "HotPink4\0"
+ "indian red\0"
+ "IndianRed\0"
+ "IndianRed1\0"
+ "IndianRed2\0"
+ "IndianRed3\0"
+ "IndianRed4\0"
+ "indigo\0"
+ "ivory\0"
+ "ivory1\0"
+ "ivory2\0"
+ "ivory3\0"
+ "ivory4\0"
+ "khaki\0"
+ "khaki1\0"
+ "khaki2\0"
+ "khaki3\0"
+ "khaki4\0"
+ "lavender\0"
+ "lavender blush\0"
+ "LavenderBlush\0"
+ "LavenderBlush1\0"
+ "LavenderBlush2\0"
+ "LavenderBlush3\0"
+ "LavenderBlush4\0"
+ "lawn green\0"
+ "LawnGreen\0"
+ "lemon chiffon\0"
+ "LemonChiffon\0"
+ "LemonChiffon1\0"
+ "LemonChiffon2\0"
+ "LemonChiffon3\0"
+ "LemonChiffon4\0"
+ "light blue\0"
+ "light coral\0"
+ "light cyan\0"
+ "light goldenrod\0"
+ "light goldenrod yellow\0"
+ "light gray\0"
+ "light green\0"
+ "light grey\0"
+ "light pink\0"
+ "light salmon\0"
+ "light sea green\0"
+ "light sky blue\0"
+ "light slate blue\0"
+ "light slate gray\0"
+ "light slate grey\0"
+ "light steel blue\0"
+ "light yellow\0"
+ "LightBlue\0"
+ "LightBlue1\0"
+ "LightBlue2\0"
+ "LightBlue3\0"
+ "LightBlue4\0"
+ "LightCoral\0"
+ "LightCyan\0"
+ "LightCyan1\0"
+ "LightCyan2\0"
+ "LightCyan3\0"
+ "LightCyan4\0"
+ "LightGoldenrod\0"
+ "LightGoldenrod1\0"
+ "LightGoldenrod2\0"
+ "LightGoldenrod3\0"
+ "LightGoldenrod4\0"
+ "LightGoldenrodYellow\0"
+ "LightGray\0"
+ "LightGreen\0"
+ "LightGrey\0"
+ "LightPink\0"
+ "LightPink1\0"
+ "LightPink2\0"
+ "LightPink3\0"
+ "LightPink4\0"
+ "LightSalmon\0"
+ "LightSalmon1\0"
+ "LightSalmon2\0"
+ "LightSalmon3\0"
+ "LightSalmon4\0"
+ "LightSeaGreen\0"
+ "LightSkyBlue\0"
+ "LightSkyBlue1\0"
+ "LightSkyBlue2\0"
+ "LightSkyBlue3\0"
+ "LightSkyBlue4\0"
+ "LightSlateBlue\0"
+ "LightSlateGray\0"
+ "LightSlateGrey\0"
+ "LightSteelBlue\0"
+ "LightSteelBlue1\0"
+ "LightSteelBlue2\0"
+ "LightSteelBlue3\0"
+ "LightSteelBlue4\0"
+ "LightYellow\0"
+ "LightYellow1\0"
+ "LightYellow2\0"
+ "LightYellow3\0"
+ "LightYellow4\0"
+ "lime\0"
+ "lime green\0"
+ "LimeGreen\0"
+ "linen\0"
+ "magenta\0"
+ "magenta1\0"
+ "magenta2\0"
+ "magenta3\0"
+ "magenta4\0"
+ "maroon\0"
+ "maroon1\0"
+ "maroon2\0"
+ "maroon3\0"
+ "maroon4\0"
+ "medium aquamarine\0"
+ "medium blue\0"
+ "medium orchid\0"
+ "medium purple\0"
+ "medium sea green\0"
+ "medium slate blue\0"
+ "medium spring green\0"
+ "medium turquoise\0"
+ "medium violet red\0"
+ "MediumAquamarine\0"
+ "MediumBlue\0"
+ "MediumOrchid\0"
+ "MediumOrchid1\0"
+ "MediumOrchid2\0"
+ "MediumOrchid3\0"
+ "MediumOrchid4\0"
+ "MediumPurple\0"
+ "MediumPurple1\0"
+ "MediumPurple2\0"
+ "MediumPurple3\0"
+ "MediumPurple4\0"
+ "MediumSeaGreen\0"
+ "MediumSlateBlue\0"
+ "MediumSpringGreen\0"
+ "MediumTurquoise\0"
+ "MediumVioletRed\0"
+ "midnight blue\0"
+ "MidnightBlue\0"
+ "mint cream\0"
+ "MintCream\0"
+ "misty rose\0"
+ "MistyRose\0"
+ "MistyRose1\0"
+ "MistyRose2\0"
+ "MistyRose3\0"
+ "MistyRose4\0"
+ "moccasin\0"
+ "navajo white\0"
+ "NavajoWhite\0"
+ "NavajoWhite1\0"
+ "NavajoWhite2\0"
+ "NavajoWhite3\0"
+ "NavajoWhite4\0"
+ "navy\0"
+ "navy blue\0"
+ "NavyBlue\0"
+ "old lace\0"
+ "OldLace\0"
+ "olive\0"
+ "olive drab\0"
+ "OliveDrab\0"
+ "OliveDrab1\0"
+ "OliveDrab2\0"
+ "OliveDrab3\0"
+ "OliveDrab4\0"
+ "orange\0"
+ "orange red\0"
+ "orange1\0"
+ "orange2\0"
+ "orange3\0"
+ "orange4\0"
+ "OrangeRed\0"
+ "OrangeRed1\0"
+ "OrangeRed2\0"
+ "OrangeRed3\0"
+ "OrangeRed4\0"
+ "orchid\0"
+ "orchid1\0"
+ "orchid2\0"
+ "orchid3\0"
+ "orchid4\0"
+ "pale goldenrod\0"
+ "pale green\0"
+ "pale turquoise\0"
+ "pale violet red\0"
+ "PaleGoldenrod\0"
+ "PaleGreen\0"
+ "PaleGreen1\0"
+ "PaleGreen2\0"
+ "PaleGreen3\0"
+ "PaleGreen4\0"
+ "PaleTurquoise\0"
+ "PaleTurquoise1\0"
+ "PaleTurquoise2\0"
+ "PaleTurquoise3\0"
+ "PaleTurquoise4\0"
+ "PaleVioletRed\0"
+ "PaleVioletRed1\0"
+ "PaleVioletRed2\0"
+ "PaleVioletRed3\0"
+ "PaleVioletRed4\0"
+ "papaya whip\0"
+ "PapayaWhip\0"
+ "peach puff\0"
+ "PeachPuff\0"
+ "PeachPuff1\0"
+ "PeachPuff2\0"
+ "PeachPuff3\0"
+ "PeachPuff4\0"
+ "peru\0"
+ "pink\0"
+ "pink1\0"
+ "pink2\0"
+ "pink3\0"
+ "pink4\0"
+ "plum\0"
+ "plum1\0"
+ "plum2\0"
+ "plum3\0"
+ "plum4\0"
+ "powder blue\0"
+ "PowderBlue\0"
+ "purple\0"
+ "purple1\0"
+ "purple2\0"
+ "purple3\0"
+ "purple4\0"
+ "rebecca purple\0"
+ "RebeccaPurple\0"
+ "red\0"
+ "red1\0"
+ "red2\0"
+ "red3\0"
+ "red4\0"
+ "rosy brown\0"
+ "RosyBrown\0"
+ "RosyBrown1\0"
+ "RosyBrown2\0"
+ "RosyBrown3\0"
+ "RosyBrown4\0"
+ "royal blue\0"
+ "RoyalBlue\0"
+ "RoyalBlue1\0"
+ "RoyalBlue2\0"
+ "RoyalBlue3\0"
+ "RoyalBlue4\0"
+ "saddle brown\0"
+ "SaddleBrown\0"
+ "salmon\0"
+ "salmon1\0"
+ "salmon2\0"
+ "salmon3\0"
+ "salmon4\0"
+ "sandy brown\0"
+ "SandyBrown\0"
+ "sea green\0"
+ "SeaGreen\0"
+ "SeaGreen1\0"
+ "SeaGreen2\0"
+ "SeaGreen3\0"
+ "SeaGreen4\0"
+ "seashell\0"
+ "seashell1\0"
+ "seashell2\0"
+ "seashell3\0"
+ "seashell4\0"
+ "sienna\0"
+ "sienna1\0"
+ "sienna2\0"
+ "sienna3\0"
+ "sienna4\0"
+ "silver\0"
+ "sky blue\0"
+ "SkyBlue\0"
+ "SkyBlue1\0"
+ "SkyBlue2\0"
+ "SkyBlue3\0"
+ "SkyBlue4\0"
+ "slate blue\0"
+ "slate gray\0"
+ "slate grey\0"
+ "SlateBlue\0"
+ "SlateBlue1\0"
+ "SlateBlue2\0"
+ "SlateBlue3\0"
+ "SlateBlue4\0"
+ "SlateGray\0"
+ "SlateGray1\0"
+ "SlateGray2\0"
+ "SlateGray3\0"
+ "SlateGray4\0"
+ "SlateGrey\0"
+ "snow\0"
+ "snow1\0"
+ "snow2\0"
+ "snow3\0"
+ "snow4\0"
+ "spring green\0"
+ "SpringGreen\0"
+ "SpringGreen1\0"
+ "SpringGreen2\0"
+ "SpringGreen3\0"
+ "SpringGreen4\0"
+ "steel blue\0"
+ "SteelBlue\0"
+ "SteelBlue1\0"
+ "SteelBlue2\0"
+ "SteelBlue3\0"
+ "SteelBlue4\0"
+ "tan\0"
+ "tan1\0"
+ "tan2\0"
+ "tan3\0"
+ "tan4\0"
+ "teal\0"
+ "thistle\0"
+ "thistle1\0"
+ "thistle2\0"
+ "thistle3\0"
+ "thistle4\0"
+ "tomato\0"
+ "tomato1\0"
+ "tomato2\0"
+ "tomato3\0"
+ "tomato4\0"
+ "turquoise\0"
+ "turquoise1\0"
+ "turquoise2\0"
+ "turquoise3\0"
+ "turquoise4\0"
+ "violet\0"
+ "violet red\0"
+ "VioletRed\0"
+ "VioletRed1\0"
+ "VioletRed2\0"
+ "VioletRed3\0"
+ "VioletRed4\0"
+ "web gray\0"
+ "web green\0"
+ "web grey\0"
+ "web maroon\0"
+ "web purple\0"
+ "WebGray\0"
+ "WebGreen\0"
+ "WebGrey\0"
+ "WebMaroon\0"
+ "WebPurple\0"
+ "wheat\0"
+ "wheat1\0"
+ "wheat2\0"
+ "wheat3\0"
+ "wheat4\0"
+ "white\0"
+ "white smoke\0"
+ "WhiteSmoke\0"
+ "x11 gray\0"
+ "x11 green\0"
+ "x11 grey\0"
+ "x11 maroon\0"
+ "x11 purple\0"
+ "X11Gray\0"
+ "X11Green\0"
+ "X11Grey\0"
+ "X11Maroon\0"
+ "X11Purple\0"
+ "yellow\0"
+ "yellow green\0"
+ "yellow1\0"
+ "yellow2\0"
+ "yellow3\0"
+ "yellow4\0"
+ "YellowGreen\0"
+};
+
+static const BuiltinColor BuiltinColors[] = {
+ {240, 248, 255, 0}, /* alice blue */
+ {240, 248, 255, 11}, /* AliceBlue */
+ {250, 235, 215, 21}, /* antique white */
+ {250, 235, 215, 35}, /* AntiqueWhite */
+ {255, 239, 219, 48}, /* AntiqueWhite1 */
+ {238, 223, 204, 62}, /* AntiqueWhite2 */
+ {205, 192, 176, 76}, /* AntiqueWhite3 */
+ {139, 131, 120, 90}, /* AntiqueWhite4 */
+ {0, 255, 255, 104}, /* aqua */
+ {127, 255, 212, 109}, /* aquamarine */
+ {127, 255, 212, 120}, /* aquamarine1 */
+ {118, 238, 198, 132}, /* aquamarine2 */
+ {102, 205, 170, 144}, /* aquamarine3 */
+ {69, 139, 116, 156}, /* aquamarine4 */
+ {240, 255, 255, 168}, /* azure */
+ {240, 255, 255, 174}, /* azure1 */
+ {224, 238, 238, 181}, /* azure2 */
+ {193, 205, 205, 188}, /* azure3 */
+ {131, 139, 139, 195}, /* azure4 */
+ {245, 245, 220, 202}, /* beige */
+ {255, 228, 196, 208}, /* bisque */
+ {255, 228, 196, 215}, /* bisque1 */
+ {238, 213, 183, 223}, /* bisque2 */
+ {205, 183, 158, 231}, /* bisque3 */
+ {139, 125, 107, 239}, /* bisque4 */
+ {0, 0, 0, 247}, /* black */
+ {255, 235, 205, 253}, /* blanched almond */
+ {255, 235, 205, 269}, /* BlanchedAlmond */
+ {0, 0, 255, 284}, /* blue */
+ {138, 43, 226, 289}, /* blue violet */
+ {0, 0, 255, 301}, /* blue1 */
+ {0, 0, 238, 307}, /* blue2 */
+ {0, 0, 205, 313}, /* blue3 */
+ {0, 0, 139, 319}, /* blue4 */
+ {138, 43, 226, 325}, /* BlueViolet */
+ {165, 42, 42, 336}, /* brown */
+ {255, 64, 64, 342}, /* brown1 */
+ {238, 59, 59, 349}, /* brown2 */
+ {205, 51, 51, 356}, /* brown3 */
+ {139, 35, 35, 363}, /* brown4 */
+ {222, 184, 135, 370}, /* burlywood */
+ {255, 211, 155, 380}, /* burlywood1 */
+ {238, 197, 145, 391}, /* burlywood2 */
+ {205, 170, 125, 402}, /* burlywood3 */
+ {139, 115, 85, 413}, /* burlywood4 */
+ {95, 158, 160, 424}, /* cadet blue */
+ {95, 158, 160, 435}, /* CadetBlue */
+ {152, 245, 255, 445}, /* CadetBlue1 */
+ {142, 229, 238, 456}, /* CadetBlue2 */
+ {122, 197, 205, 467}, /* CadetBlue3 */
+ {83, 134, 139, 478}, /* CadetBlue4 */
+ {127, 255, 0, 489}, /* chartreuse */
+ {127, 255, 0, 500}, /* chartreuse1 */
+ {118, 238, 0, 512}, /* chartreuse2 */
+ {102, 205, 0, 524}, /* chartreuse3 */
+ {69, 139, 0, 536}, /* chartreuse4 */
+ {210, 105, 30, 548}, /* chocolate */
+ {255, 127, 36, 558}, /* chocolate1 */
+ {238, 118, 33, 569}, /* chocolate2 */
+ {205, 102, 29, 580}, /* chocolate3 */
+ {139, 69, 19, 591}, /* chocolate4 */
+ {255, 127, 80, 602}, /* coral */
+ {255, 114, 86, 608}, /* coral1 */
+ {238, 106, 80, 615}, /* coral2 */
+ {205, 91, 69, 622}, /* coral3 */
+ {139, 62, 47, 629}, /* coral4 */
+ {100, 149, 237, 636}, /* cornflower blue */
+ {100, 149, 237, 652}, /* CornflowerBlue */
+ {255, 248, 220, 667}, /* cornsilk */
+ {255, 248, 220, 676}, /* cornsilk1 */
+ {238, 232, 205, 686}, /* cornsilk2 */
+ {205, 200, 177, 696}, /* cornsilk3 */
+ {139, 136, 120, 706}, /* cornsilk4 */
+ {220, 20, 60, 716}, /* crimson */
+ {0, 255, 255, 724}, /* cyan */
+ {0, 255, 255, 729}, /* cyan1 */
+ {0, 238, 238, 735}, /* cyan2 */
+ {0, 205, 205, 741}, /* cyan3 */
+ {0, 139, 139, 747}, /* cyan4 */
+ {0, 0, 139, 753}, /* dark blue */
+ {0, 139, 139, 763}, /* dark cyan */
+ {184, 134, 11, 773}, /* dark goldenrod */
+ {169, 169, 169, 788}, /* dark gray */
+ {0, 100, 0, 798}, /* dark green */
+ {169, 169, 169, 809}, /* dark grey */
+ {189, 183, 107, 819}, /* dark khaki */
+ {139, 0, 139, 830}, /* dark magenta */
+ {85, 107, 47, 843}, /* dark olive green */
+ {255, 140, 0, 860}, /* dark orange */
+ {153, 50, 204, 872}, /* dark orchid */
+ {139, 0, 0, 884}, /* dark red */
+ {233, 150, 122, 893}, /* dark salmon */
+ {143, 188, 143, 905}, /* dark sea green */
+ {72, 61, 139, 920}, /* dark slate blue */
+ {47, 79, 79, 936}, /* dark slate gray */
+ {47, 79, 79, 952}, /* dark slate grey */
+ {0, 206, 209, 968}, /* dark turquoise */
+ {148, 0, 211, 983}, /* dark violet */
+ {0, 0, 139, 995}, /* DarkBlue */
+ {0, 139, 139, 1004}, /* DarkCyan */
+ {184, 134, 11, 1013}, /* DarkGoldenrod */
+ {255, 185, 15, 1027}, /* DarkGoldenrod1 */
+ {238, 173, 14, 1042}, /* DarkGoldenrod2 */
+ {205, 149, 12, 1057}, /* DarkGoldenrod3 */
+ {139, 101, 8, 1072}, /* DarkGoldenrod4 */
+ {169, 169, 169, 1087}, /* DarkGray */
+ {0, 100, 0, 1096}, /* DarkGreen */
+ {169, 169, 169, 1106}, /* DarkGrey */
+ {189, 183, 107, 1115}, /* DarkKhaki */
+ {139, 0, 139, 1125}, /* DarkMagenta */
+ {85, 107, 47, 1137}, /* DarkOliveGreen */
+ {202, 255, 112, 1152}, /* DarkOliveGreen1 */
+ {188, 238, 104, 1168}, /* DarkOliveGreen2 */
+ {162, 205, 90, 1184}, /* DarkOliveGreen3 */
+ {110, 139, 61, 1200}, /* DarkOliveGreen4 */
+ {255, 140, 0, 1216}, /* DarkOrange */
+ {255, 127, 0, 1227}, /* DarkOrange1 */
+ {238, 118, 0, 1239}, /* DarkOrange2 */
+ {205, 102, 0, 1251}, /* DarkOrange3 */
+ {139, 69, 0, 1263}, /* DarkOrange4 */
+ {153, 50, 204, 1275}, /* DarkOrchid */
+ {191, 62, 255, 1286}, /* DarkOrchid1 */
+ {178, 58, 238, 1298}, /* DarkOrchid2 */
+ {154, 50, 205, 1310}, /* DarkOrchid3 */
+ {104, 34, 139, 1322}, /* DarkOrchid4 */
+ {139, 0, 0, 1334}, /* DarkRed */
+ {233, 150, 122, 1342}, /* DarkSalmon */
+ {143, 188, 143, 1353}, /* DarkSeaGreen */
+ {193, 255, 193, 1366}, /* DarkSeaGreen1 */
+ {180, 238, 180, 1380}, /* DarkSeaGreen2 */
+ {155, 205, 155, 1394}, /* DarkSeaGreen3 */
+ {105, 139, 105, 1408}, /* DarkSeaGreen4 */
+ {72, 61, 139, 1422}, /* DarkSlateBlue */
+ {47, 79, 79, 1436}, /* DarkSlateGray */
+ {151, 255, 255, 1450}, /* DarkSlateGray1 */
+ {141, 238, 238, 1465}, /* DarkSlateGray2 */
+ {121, 205, 205, 1480}, /* DarkSlateGray3 */
+ {82, 139, 139, 1495}, /* DarkSlateGray4 */
+ {47, 79, 79, 1510}, /* DarkSlateGrey */
+ {0, 206, 209, 1524}, /* DarkTurquoise */
+ {148, 0, 211, 1538}, /* DarkViolet */
+ {255, 20, 147, 1549}, /* deep pink */
+ {0, 191, 255, 1559}, /* deep sky blue */
+ {255, 20, 147, 1573}, /* DeepPink */
+ {255, 20, 147, 1582}, /* DeepPink1 */
+ {238, 18, 137, 1592}, /* DeepPink2 */
+ {205, 16, 118, 1602}, /* DeepPink3 */
+ {139, 10, 80, 1612}, /* DeepPink4 */
+ {0, 191, 255, 1622}, /* DeepSkyBlue */
+ {0, 191, 255, 1634}, /* DeepSkyBlue1 */
+ {0, 178, 238, 1647}, /* DeepSkyBlue2 */
+ {0, 154, 205, 1660}, /* DeepSkyBlue3 */
+ {0, 104, 139, 1673}, /* DeepSkyBlue4 */
+ {105, 105, 105, 1686}, /* dim gray */
+ {105, 105, 105, 1695}, /* dim grey */
+ {105, 105, 105, 1704}, /* DimGray */
+ {105, 105, 105, 1712}, /* DimGrey */
+ {30, 144, 255, 1720}, /* dodger blue */
+ {30, 144, 255, 1732}, /* DodgerBlue */
+ {30, 144, 255, 1743}, /* DodgerBlue1 */
+ {28, 134, 238, 1755}, /* DodgerBlue2 */
+ {24, 116, 205, 1767}, /* DodgerBlue3 */
+ {16, 78, 139, 1779}, /* DodgerBlue4 */
+ {178, 34, 34, 1791}, /* firebrick */
+ {255, 48, 48, 1801}, /* firebrick1 */
+ {238, 44, 44, 1812}, /* firebrick2 */
+ {205, 38, 38, 1823}, /* firebrick3 */
+ {139, 26, 26, 1834}, /* firebrick4 */
+ {255, 250, 240, 1845}, /* floral white */
+ {255, 250, 240, 1858}, /* FloralWhite */
+ {34, 139, 34, 1870}, /* forest green */
+ {34, 139, 34, 1883}, /* ForestGreen */
+ {255, 0, 255, 1895}, /* fuchsia */
+ {220, 220, 220, 1903}, /* gainsboro */
+ {248, 248, 255, 1913}, /* ghost white */
+ {248, 248, 255, 1925}, /* GhostWhite */
+ {255, 215, 0, 1936}, /* gold */
+ {255, 215, 0, 1941}, /* gold1 */
+ {238, 201, 0, 1947}, /* gold2 */
+ {205, 173, 0, 1953}, /* gold3 */
+ {139, 117, 0, 1959}, /* gold4 */
+ {218, 165, 32, 1965}, /* goldenrod */
+ {255, 193, 37, 1975}, /* goldenrod1 */
+ {238, 180, 34, 1986}, /* goldenrod2 */
+ {205, 155, 29, 1997}, /* goldenrod3 */
+ {139, 105, 20, 2008}, /* goldenrod4 */
+ {190, 190, 190, 2019}, /* gray */
+ {0, 0, 0, 2024}, /* gray0 */
+ {3, 3, 3, 2030}, /* gray1 */
+ {26, 26, 26, 2036}, /* gray10 */
+ {255, 255, 255, 2043}, /* gray100 */
+ {28, 28, 28, 2051}, /* gray11 */
+ {31, 31, 31, 2058}, /* gray12 */
+ {33, 33, 33, 2065}, /* gray13 */
+ {36, 36, 36, 2072}, /* gray14 */
+ {38, 38, 38, 2079}, /* gray15 */
+ {41, 41, 41, 2086}, /* gray16 */
+ {43, 43, 43, 2093}, /* gray17 */
+ {46, 46, 46, 2100}, /* gray18 */
+ {48, 48, 48, 2107}, /* gray19 */
+ {5, 5, 5, 2114}, /* gray2 */
+ {51, 51, 51, 2120}, /* gray20 */
+ {54, 54, 54, 2127}, /* gray21 */
+ {56, 56, 56, 2134}, /* gray22 */
+ {59, 59, 59, 2141}, /* gray23 */
+ {61, 61, 61, 2148}, /* gray24 */
+ {64, 64, 64, 2155}, /* gray25 */
+ {66, 66, 66, 2162}, /* gray26 */
+ {69, 69, 69, 2169}, /* gray27 */
+ {71, 71, 71, 2176}, /* gray28 */
+ {74, 74, 74, 2183}, /* gray29 */
+ {8, 8, 8, 2190}, /* gray3 */
+ {77, 77, 77, 2196}, /* gray30 */
+ {79, 79, 79, 2203}, /* gray31 */
+ {82, 82, 82, 2210}, /* gray32 */
+ {84, 84, 84, 2217}, /* gray33 */
+ {87, 87, 87, 2224}, /* gray34 */
+ {89, 89, 89, 2231}, /* gray35 */
+ {92, 92, 92, 2238}, /* gray36 */
+ {94, 94, 94, 2245}, /* gray37 */
+ {97, 97, 97, 2252}, /* gray38 */
+ {99, 99, 99, 2259}, /* gray39 */
+ {10, 10, 10, 2266}, /* gray4 */
+ {102, 102, 102, 2272}, /* gray40 */
+ {105, 105, 105, 2279}, /* gray41 */
+ {107, 107, 107, 2286}, /* gray42 */
+ {110, 110, 110, 2293}, /* gray43 */
+ {112, 112, 112, 2300}, /* gray44 */
+ {115, 115, 115, 2307}, /* gray45 */
+ {117, 117, 117, 2314}, /* gray46 */
+ {120, 120, 120, 2321}, /* gray47 */
+ {122, 122, 122, 2328}, /* gray48 */
+ {125, 125, 125, 2335}, /* gray49 */
+ {13, 13, 13, 2342}, /* gray5 */
+ {127, 127, 127, 2348}, /* gray50 */
+ {130, 130, 130, 2355}, /* gray51 */
+ {133, 133, 133, 2362}, /* gray52 */
+ {135, 135, 135, 2369}, /* gray53 */
+ {138, 138, 138, 2376}, /* gray54 */
+ {140, 140, 140, 2383}, /* gray55 */
+ {143, 143, 143, 2390}, /* gray56 */
+ {145, 145, 145, 2397}, /* gray57 */
+ {148, 148, 148, 2404}, /* gray58 */
+ {150, 150, 150, 2411}, /* gray59 */
+ {15, 15, 15, 2418}, /* gray6 */
+ {153, 153, 153, 2424}, /* gray60 */
+ {156, 156, 156, 2431}, /* gray61 */
+ {158, 158, 158, 2438}, /* gray62 */
+ {161, 161, 161, 2445}, /* gray63 */
+ {163, 163, 163, 2452}, /* gray64 */
+ {166, 166, 166, 2459}, /* gray65 */
+ {168, 168, 168, 2466}, /* gray66 */
+ {171, 171, 171, 2473}, /* gray67 */
+ {173, 173, 173, 2480}, /* gray68 */
+ {176, 176, 176, 2487}, /* gray69 */
+ {18, 18, 18, 2494}, /* gray7 */
+ {179, 179, 179, 2500}, /* gray70 */
+ {181, 181, 181, 2507}, /* gray71 */
+ {184, 184, 184, 2514}, /* gray72 */
+ {186, 186, 186, 2521}, /* gray73 */
+ {189, 189, 189, 2528}, /* gray74 */
+ {191, 191, 191, 2535}, /* gray75 */
+ {194, 194, 194, 2542}, /* gray76 */
+ {196, 196, 196, 2549}, /* gray77 */
+ {199, 199, 199, 2556}, /* gray78 */
+ {201, 201, 201, 2563}, /* gray79 */
+ {20, 20, 20, 2570}, /* gray8 */
+ {204, 204, 204, 2576}, /* gray80 */
+ {207, 207, 207, 2583}, /* gray81 */
+ {209, 209, 209, 2590}, /* gray82 */
+ {212, 212, 212, 2597}, /* gray83 */
+ {214, 214, 214, 2604}, /* gray84 */
+ {217, 217, 217, 2611}, /* gray85 */
+ {219, 219, 219, 2618}, /* gray86 */
+ {222, 222, 222, 2625}, /* gray87 */
+ {224, 224, 224, 2632}, /* gray88 */
+ {227, 227, 227, 2639}, /* gray89 */
+ {23, 23, 23, 2646}, /* gray9 */
+ {229, 229, 229, 2652}, /* gray90 */
+ {232, 232, 232, 2659}, /* gray91 */
+ {235, 235, 235, 2666}, /* gray92 */
+ {237, 237, 237, 2673}, /* gray93 */
+ {240, 240, 240, 2680}, /* gray94 */
+ {242, 242, 242, 2687}, /* gray95 */
+ {245, 245, 245, 2694}, /* gray96 */
+ {247, 247, 247, 2701}, /* gray97 */
+ {250, 250, 250, 2708}, /* gray98 */
+ {252, 252, 252, 2715}, /* gray99 */
+ {0, 255, 0, 2722}, /* green */
+ {173, 255, 47, 2728}, /* green yellow */
+ {0, 255, 0, 2741}, /* green1 */
+ {0, 238, 0, 2748}, /* green2 */
+ {0, 205, 0, 2755}, /* green3 */
+ {0, 139, 0, 2762}, /* green4 */
+ {173, 255, 47, 2769}, /* GreenYellow */
+ {190, 190, 190, 2781}, /* grey */
+ {0, 0, 0, 2786}, /* grey0 */
+ {3, 3, 3, 2792}, /* grey1 */
+ {26, 26, 26, 2798}, /* grey10 */
+ {255, 255, 255, 2805}, /* grey100 */
+ {28, 28, 28, 2813}, /* grey11 */
+ {31, 31, 31, 2820}, /* grey12 */
+ {33, 33, 33, 2827}, /* grey13 */
+ {36, 36, 36, 2834}, /* grey14 */
+ {38, 38, 38, 2841}, /* grey15 */
+ {41, 41, 41, 2848}, /* grey16 */
+ {43, 43, 43, 2855}, /* grey17 */
+ {46, 46, 46, 2862}, /* grey18 */
+ {48, 48, 48, 2869}, /* grey19 */
+ {5, 5, 5, 2876}, /* grey2 */
+ {51, 51, 51, 2882}, /* grey20 */
+ {54, 54, 54, 2889}, /* grey21 */
+ {56, 56, 56, 2896}, /* grey22 */
+ {59, 59, 59, 2903}, /* grey23 */
+ {61, 61, 61, 2910}, /* grey24 */
+ {64, 64, 64, 2917}, /* grey25 */
+ {66, 66, 66, 2924}, /* grey26 */
+ {69, 69, 69, 2931}, /* grey27 */
+ {71, 71, 71, 2938}, /* grey28 */
+ {74, 74, 74, 2945}, /* grey29 */
+ {8, 8, 8, 2952}, /* grey3 */
+ {77, 77, 77, 2958}, /* grey30 */
+ {79, 79, 79, 2965}, /* grey31 */
+ {82, 82, 82, 2972}, /* grey32 */
+ {84, 84, 84, 2979}, /* grey33 */
+ {87, 87, 87, 2986}, /* grey34 */
+ {89, 89, 89, 2993}, /* grey35 */
+ {92, 92, 92, 3000}, /* grey36 */
+ {94, 94, 94, 3007}, /* grey37 */
+ {97, 97, 97, 3014}, /* grey38 */
+ {99, 99, 99, 3021}, /* grey39 */
+ {10, 10, 10, 3028}, /* grey4 */
+ {102, 102, 102, 3034}, /* grey40 */
+ {105, 105, 105, 3041}, /* grey41 */
+ {107, 107, 107, 3048}, /* grey42 */
+ {110, 110, 110, 3055}, /* grey43 */
+ {112, 112, 112, 3062}, /* grey44 */
+ {115, 115, 115, 3069}, /* grey45 */
+ {117, 117, 117, 3076}, /* grey46 */
+ {120, 120, 120, 3083}, /* grey47 */
+ {122, 122, 122, 3090}, /* grey48 */
+ {125, 125, 125, 3097}, /* grey49 */
+ {13, 13, 13, 3104}, /* grey5 */
+ {127, 127, 127, 3110}, /* grey50 */
+ {130, 130, 130, 3117}, /* grey51 */
+ {133, 133, 133, 3124}, /* grey52 */
+ {135, 135, 135, 3131}, /* grey53 */
+ {138, 138, 138, 3138}, /* grey54 */
+ {140, 140, 140, 3145}, /* grey55 */
+ {143, 143, 143, 3152}, /* grey56 */
+ {145, 145, 145, 3159}, /* grey57 */
+ {148, 148, 148, 3166}, /* grey58 */
+ {150, 150, 150, 3173}, /* grey59 */
+ {15, 15, 15, 3180}, /* grey6 */
+ {153, 153, 153, 3186}, /* grey60 */
+ {156, 156, 156, 3193}, /* grey61 */
+ {158, 158, 158, 3200}, /* grey62 */
+ {161, 161, 161, 3207}, /* grey63 */
+ {163, 163, 163, 3214}, /* grey64 */
+ {166, 166, 166, 3221}, /* grey65 */
+ {168, 168, 168, 3228}, /* grey66 */
+ {171, 171, 171, 3235}, /* grey67 */
+ {173, 173, 173, 3242}, /* grey68 */
+ {176, 176, 176, 3249}, /* grey69 */
+ {18, 18, 18, 3256}, /* grey7 */
+ {179, 179, 179, 3262}, /* grey70 */
+ {181, 181, 181, 3269}, /* grey71 */
+ {184, 184, 184, 3276}, /* grey72 */
+ {186, 186, 186, 3283}, /* grey73 */
+ {189, 189, 189, 3290}, /* grey74 */
+ {191, 191, 191, 3297}, /* grey75 */
+ {194, 194, 194, 3304}, /* grey76 */
+ {196, 196, 196, 3311}, /* grey77 */
+ {199, 199, 199, 3318}, /* grey78 */
+ {201, 201, 201, 3325}, /* grey79 */
+ {20, 20, 20, 3332}, /* grey8 */
+ {204, 204, 204, 3338}, /* grey80 */
+ {207, 207, 207, 3345}, /* grey81 */
+ {209, 209, 209, 3352}, /* grey82 */
+ {212, 212, 212, 3359}, /* grey83 */
+ {214, 214, 214, 3366}, /* grey84 */
+ {217, 217, 217, 3373}, /* grey85 */
+ {219, 219, 219, 3380}, /* grey86 */
+ {222, 222, 222, 3387}, /* grey87 */
+ {224, 224, 224, 3394}, /* grey88 */
+ {227, 227, 227, 3401}, /* grey89 */
+ {23, 23, 23, 3408}, /* grey9 */
+ {229, 229, 229, 3414}, /* grey90 */
+ {232, 232, 232, 3421}, /* grey91 */
+ {235, 235, 235, 3428}, /* grey92 */
+ {237, 237, 237, 3435}, /* grey93 */
+ {240, 240, 240, 3442}, /* grey94 */
+ {242, 242, 242, 3449}, /* grey95 */
+ {245, 245, 245, 3456}, /* grey96 */
+ {247, 247, 247, 3463}, /* grey97 */
+ {250, 250, 250, 3470}, /* grey98 */
+ {252, 252, 252, 3477}, /* grey99 */
+ {240, 255, 240, 3484}, /* honeydew */
+ {240, 255, 240, 3493}, /* honeydew1 */
+ {224, 238, 224, 3503}, /* honeydew2 */
+ {193, 205, 193, 3513}, /* honeydew3 */
+ {131, 139, 131, 3523}, /* honeydew4 */
+ {255, 105, 180, 3533}, /* hot pink */
+ {255, 105, 180, 3542}, /* HotPink */
+ {255, 110, 180, 3550}, /* HotPink1 */
+ {238, 106, 167, 3559}, /* HotPink2 */
+ {205, 96, 144, 3568}, /* HotPink3 */
+ {139, 58, 98, 3577}, /* HotPink4 */
+ {205, 92, 92, 3586}, /* indian red */
+ {205, 92, 92, 3597}, /* IndianRed */
+ {255, 106, 106, 3607}, /* IndianRed1 */
+ {238, 99, 99, 3618}, /* IndianRed2 */
+ {205, 85, 85, 3629}, /* IndianRed3 */
+ {139, 58, 58, 3640}, /* IndianRed4 */
+ {75, 0, 130, 3651}, /* indigo */
+ {255, 255, 240, 3658}, /* ivory */
+ {255, 255, 240, 3664}, /* ivory1 */
+ {238, 238, 224, 3671}, /* ivory2 */
+ {205, 205, 193, 3678}, /* ivory3 */
+ {139, 139, 131, 3685}, /* ivory4 */
+ {240, 230, 140, 3692}, /* khaki */
+ {255, 246, 143, 3698}, /* khaki1 */
+ {238, 230, 133, 3705}, /* khaki2 */
+ {205, 198, 115, 3712}, /* khaki3 */
+ {139, 134, 78, 3719}, /* khaki4 */
+ {230, 230, 250, 3726}, /* lavender */
+ {255, 240, 245, 3735}, /* lavender blush */
+ {255, 240, 245, 3750}, /* LavenderBlush */
+ {255, 240, 245, 3764}, /* LavenderBlush1 */
+ {238, 224, 229, 3779}, /* LavenderBlush2 */
+ {205, 193, 197, 3794}, /* LavenderBlush3 */
+ {139, 131, 134, 3809}, /* LavenderBlush4 */
+ {124, 252, 0, 3824}, /* lawn green */
+ {124, 252, 0, 3835}, /* LawnGreen */
+ {255, 250, 205, 3845}, /* lemon chiffon */
+ {255, 250, 205, 3859}, /* LemonChiffon */
+ {255, 250, 205, 3872}, /* LemonChiffon1 */
+ {238, 233, 191, 3886}, /* LemonChiffon2 */
+ {205, 201, 165, 3900}, /* LemonChiffon3 */
+ {139, 137, 112, 3914}, /* LemonChiffon4 */
+ {173, 216, 230, 3928}, /* light blue */
+ {240, 128, 128, 3939}, /* light coral */
+ {224, 255, 255, 3951}, /* light cyan */
+ {238, 221, 130, 3962}, /* light goldenrod */
+ {250, 250, 210, 3978}, /* light goldenrod yellow */
+ {211, 211, 211, 4001}, /* light gray */
+ {144, 238, 144, 4012}, /* light green */
+ {211, 211, 211, 4024}, /* light grey */
+ {255, 182, 193, 4035}, /* light pink */
+ {255, 160, 122, 4046}, /* light salmon */
+ {32, 178, 170, 4059}, /* light sea green */
+ {135, 206, 250, 4075}, /* light sky blue */
+ {132, 112, 255, 4090}, /* light slate blue */
+ {119, 136, 153, 4107}, /* light slate gray */
+ {119, 136, 153, 4124}, /* light slate grey */
+ {176, 196, 222, 4141}, /* light steel blue */
+ {255, 255, 224, 4158}, /* light yellow */
+ {173, 216, 230, 4171}, /* LightBlue */
+ {191, 239, 255, 4181}, /* LightBlue1 */
+ {178, 223, 238, 4192}, /* LightBlue2 */
+ {154, 192, 205, 4203}, /* LightBlue3 */
+ {104, 131, 139, 4214}, /* LightBlue4 */
+ {240, 128, 128, 4225}, /* LightCoral */
+ {224, 255, 255, 4236}, /* LightCyan */
+ {224, 255, 255, 4246}, /* LightCyan1 */
+ {209, 238, 238, 4257}, /* LightCyan2 */
+ {180, 205, 205, 4268}, /* LightCyan3 */
+ {122, 139, 139, 4279}, /* LightCyan4 */
+ {238, 221, 130, 4290}, /* LightGoldenrod */
+ {255, 236, 139, 4305}, /* LightGoldenrod1 */
+ {238, 220, 130, 4321}, /* LightGoldenrod2 */
+ {205, 190, 112, 4337}, /* LightGoldenrod3 */
+ {139, 129, 76, 4353}, /* LightGoldenrod4 */
+ {250, 250, 210, 4369}, /* LightGoldenrodYellow */
+ {211, 211, 211, 4390}, /* LightGray */
+ {144, 238, 144, 4400}, /* LightGreen */
+ {211, 211, 211, 4411}, /* LightGrey */
+ {255, 182, 193, 4421}, /* LightPink */
+ {255, 174, 185, 4431}, /* LightPink1 */
+ {238, 162, 173, 4442}, /* LightPink2 */
+ {205, 140, 149, 4453}, /* LightPink3 */
+ {139, 95, 101, 4464}, /* LightPink4 */
+ {255, 160, 122, 4475}, /* LightSalmon */
+ {255, 160, 122, 4487}, /* LightSalmon1 */
+ {238, 149, 114, 4500}, /* LightSalmon2 */
+ {205, 129, 98, 4513}, /* LightSalmon3 */
+ {139, 87, 66, 4526}, /* LightSalmon4 */
+ {32, 178, 170, 4539}, /* LightSeaGreen */
+ {135, 206, 250, 4553}, /* LightSkyBlue */
+ {176, 226, 255, 4566}, /* LightSkyBlue1 */
+ {164, 211, 238, 4580}, /* LightSkyBlue2 */
+ {141, 182, 205, 4594}, /* LightSkyBlue3 */
+ {96, 123, 139, 4608}, /* LightSkyBlue4 */
+ {132, 112, 255, 4622}, /* LightSlateBlue */
+ {119, 136, 153, 4637}, /* LightSlateGray */
+ {119, 136, 153, 4652}, /* LightSlateGrey */
+ {176, 196, 222, 4667}, /* LightSteelBlue */
+ {202, 225, 255, 4682}, /* LightSteelBlue1 */
+ {188, 210, 238, 4698}, /* LightSteelBlue2 */
+ {162, 181, 205, 4714}, /* LightSteelBlue3 */
+ {110, 123, 139, 4730}, /* LightSteelBlue4 */
+ {255, 255, 224, 4746}, /* LightYellow */
+ {255, 255, 224, 4758}, /* LightYellow1 */
+ {238, 238, 209, 4771}, /* LightYellow2 */
+ {205, 205, 180, 4784}, /* LightYellow3 */
+ {139, 139, 122, 4797}, /* LightYellow4 */
+ {0, 255, 0, 4810}, /* lime */
+ {50, 205, 50, 4815}, /* lime green */
+ {50, 205, 50, 4826}, /* LimeGreen */
+ {250, 240, 230, 4836}, /* linen */
+ {255, 0, 255, 4842}, /* magenta */
+ {255, 0, 255, 4850}, /* magenta1 */
+ {238, 0, 238, 4859}, /* magenta2 */
+ {205, 0, 205, 4868}, /* magenta3 */
+ {139, 0, 139, 4877}, /* magenta4 */
+ {176, 48, 96, 4886}, /* maroon */
+ {255, 52, 179, 4893}, /* maroon1 */
+ {238, 48, 167, 4901}, /* maroon2 */
+ {205, 41, 144, 4909}, /* maroon3 */
+ {139, 28, 98, 4917}, /* maroon4 */
+ {102, 205, 170, 4925}, /* medium aquamarine */
+ {0, 0, 205, 4943}, /* medium blue */
+ {186, 85, 211, 4955}, /* medium orchid */
+ {147, 112, 219, 4969}, /* medium purple */
+ {60, 179, 113, 4983}, /* medium sea green */
+ {123, 104, 238, 5000}, /* medium slate blue */
+ {0, 250, 154, 5018}, /* medium spring green */
+ {72, 209, 204, 5038}, /* medium turquoise */
+ {199, 21, 133, 5055}, /* medium violet red */
+ {102, 205, 170, 5073}, /* MediumAquamarine */
+ {0, 0, 205, 5090}, /* MediumBlue */
+ {186, 85, 211, 5101}, /* MediumOrchid */
+ {224, 102, 255, 5114}, /* MediumOrchid1 */
+ {209, 95, 238, 5128}, /* MediumOrchid2 */
+ {180, 82, 205, 5142}, /* MediumOrchid3 */
+ {122, 55, 139, 5156}, /* MediumOrchid4 */
+ {147, 112, 219, 5170}, /* MediumPurple */
+ {171, 130, 255, 5183}, /* MediumPurple1 */
+ {159, 121, 238, 5197}, /* MediumPurple2 */
+ {137, 104, 205, 5211}, /* MediumPurple3 */
+ {93, 71, 139, 5225}, /* MediumPurple4 */
+ {60, 179, 113, 5239}, /* MediumSeaGreen */
+ {123, 104, 238, 5254}, /* MediumSlateBlue */
+ {0, 250, 154, 5270}, /* MediumSpringGreen */
+ {72, 209, 204, 5288}, /* MediumTurquoise */
+ {199, 21, 133, 5304}, /* MediumVioletRed */
+ {25, 25, 112, 5320}, /* midnight blue */
+ {25, 25, 112, 5334}, /* MidnightBlue */
+ {245, 255, 250, 5347}, /* mint cream */
+ {245, 255, 250, 5358}, /* MintCream */
+ {255, 228, 225, 5368}, /* misty rose */
+ {255, 228, 225, 5379}, /* MistyRose */
+ {255, 228, 225, 5389}, /* MistyRose1 */
+ {238, 213, 210, 5400}, /* MistyRose2 */
+ {205, 183, 181, 5411}, /* MistyRose3 */
+ {139, 125, 123, 5422}, /* MistyRose4 */
+ {255, 228, 181, 5433}, /* moccasin */
+ {255, 222, 173, 5442}, /* navajo white */
+ {255, 222, 173, 5455}, /* NavajoWhite */
+ {255, 222, 173, 5467}, /* NavajoWhite1 */
+ {238, 207, 161, 5480}, /* NavajoWhite2 */
+ {205, 179, 139, 5493}, /* NavajoWhite3 */
+ {139, 121, 94, 5506}, /* NavajoWhite4 */
+ {0, 0, 128, 5519}, /* navy */
+ {0, 0, 128, 5524}, /* navy blue */
+ {0, 0, 128, 5534}, /* NavyBlue */
+ {253, 245, 230, 5543}, /* old lace */
+ {253, 245, 230, 5552}, /* OldLace */
+ {128, 128, 0, 5560}, /* olive */
+ {107, 142, 35, 5566}, /* olive drab */
+ {107, 142, 35, 5577}, /* OliveDrab */
+ {192, 255, 62, 5587}, /* OliveDrab1 */
+ {179, 238, 58, 5598}, /* OliveDrab2 */
+ {154, 205, 50, 5609}, /* OliveDrab3 */
+ {105, 139, 34, 5620}, /* OliveDrab4 */
+ {255, 165, 0, 5631}, /* orange */
+ {255, 69, 0, 5638}, /* orange red */
+ {255, 165, 0, 5649}, /* orange1 */
+ {238, 154, 0, 5657}, /* orange2 */
+ {205, 133, 0, 5665}, /* orange3 */
+ {139, 90, 0, 5673}, /* orange4 */
+ {255, 69, 0, 5681}, /* OrangeRed */
+ {255, 69, 0, 5691}, /* OrangeRed1 */
+ {238, 64, 0, 5702}, /* OrangeRed2 */
+ {205, 55, 0, 5713}, /* OrangeRed3 */
+ {139, 37, 0, 5724}, /* OrangeRed4 */
+ {218, 112, 214, 5735}, /* orchid */
+ {255, 131, 250, 5742}, /* orchid1 */
+ {238, 122, 233, 5750}, /* orchid2 */
+ {205, 105, 201, 5758}, /* orchid3 */
+ {139, 71, 137, 5766}, /* orchid4 */
+ {238, 232, 170, 5774}, /* pale goldenrod */
+ {152, 251, 152, 5789}, /* pale green */
+ {175, 238, 238, 5800}, /* pale turquoise */
+ {219, 112, 147, 5815}, /* pale violet red */
+ {238, 232, 170, 5831}, /* PaleGoldenrod */
+ {152, 251, 152, 5845}, /* PaleGreen */
+ {154, 255, 154, 5855}, /* PaleGreen1 */
+ {144, 238, 144, 5866}, /* PaleGreen2 */
+ {124, 205, 124, 5877}, /* PaleGreen3 */
+ {84, 139, 84, 5888}, /* PaleGreen4 */
+ {175, 238, 238, 5899}, /* PaleTurquoise */
+ {187, 255, 255, 5913}, /* PaleTurquoise1 */
+ {174, 238, 238, 5928}, /* PaleTurquoise2 */
+ {150, 205, 205, 5943}, /* PaleTurquoise3 */
+ {102, 139, 139, 5958}, /* PaleTurquoise4 */
+ {219, 112, 147, 5973}, /* PaleVioletRed */
+ {255, 130, 171, 5987}, /* PaleVioletRed1 */
+ {238, 121, 159, 6002}, /* PaleVioletRed2 */
+ {205, 104, 137, 6017}, /* PaleVioletRed3 */
+ {139, 71, 93, 6032}, /* PaleVioletRed4 */
+ {255, 239, 213, 6047}, /* papaya whip */
+ {255, 239, 213, 6059}, /* PapayaWhip */
+ {255, 218, 185, 6070}, /* peach puff */
+ {255, 218, 185, 6081}, /* PeachPuff */
+ {255, 218, 185, 6091}, /* PeachPuff1 */
+ {238, 203, 173, 6102}, /* PeachPuff2 */
+ {205, 175, 149, 6113}, /* PeachPuff3 */
+ {139, 119, 101, 6124}, /* PeachPuff4 */
+ {205, 133, 63, 6135}, /* peru */
+ {255, 192, 203, 6140}, /* pink */
+ {255, 181, 197, 6145}, /* pink1 */
+ {238, 169, 184, 6151}, /* pink2 */
+ {205, 145, 158, 6157}, /* pink3 */
+ {139, 99, 108, 6163}, /* pink4 */
+ {221, 160, 221, 6169}, /* plum */
+ {255, 187, 255, 6174}, /* plum1 */
+ {238, 174, 238, 6180}, /* plum2 */
+ {205, 150, 205, 6186}, /* plum3 */
+ {139, 102, 139, 6192}, /* plum4 */
+ {176, 224, 230, 6198}, /* powder blue */
+ {176, 224, 230, 6210}, /* PowderBlue */
+ {160, 32, 240, 6221}, /* purple */
+ {155, 48, 255, 6228}, /* purple1 */
+ {145, 44, 238, 6236}, /* purple2 */
+ {125, 38, 205, 6244}, /* purple3 */
+ {85, 26, 139, 6252}, /* purple4 */
+ {102, 51, 153, 6260}, /* rebecca purple */
+ {102, 51, 153, 6275}, /* RebeccaPurple */
+ {255, 0, 0, 6289}, /* red */
+ {255, 0, 0, 6293}, /* red1 */
+ {238, 0, 0, 6298}, /* red2 */
+ {205, 0, 0, 6303}, /* red3 */
+ {139, 0, 0, 6308}, /* red4 */
+ {188, 143, 143, 6313}, /* rosy brown */
+ {188, 143, 143, 6324}, /* RosyBrown */
+ {255, 193, 193, 6334}, /* RosyBrown1 */
+ {238, 180, 180, 6345}, /* RosyBrown2 */
+ {205, 155, 155, 6356}, /* RosyBrown3 */
+ {139, 105, 105, 6367}, /* RosyBrown4 */
+ {65, 105, 225, 6378}, /* royal blue */
+ {65, 105, 225, 6389}, /* RoyalBlue */
+ {72, 118, 255, 6399}, /* RoyalBlue1 */
+ {67, 110, 238, 6410}, /* RoyalBlue2 */
+ {58, 95, 205, 6421}, /* RoyalBlue3 */
+ {39, 64, 139, 6432}, /* RoyalBlue4 */
+ {139, 69, 19, 6443}, /* saddle brown */
+ {139, 69, 19, 6456}, /* SaddleBrown */
+ {250, 128, 114, 6468}, /* salmon */
+ {255, 140, 105, 6475}, /* salmon1 */
+ {238, 130, 98, 6483}, /* salmon2 */
+ {205, 112, 84, 6491}, /* salmon3 */
+ {139, 76, 57, 6499}, /* salmon4 */
+ {244, 164, 96, 6507}, /* sandy brown */
+ {244, 164, 96, 6519}, /* SandyBrown */
+ {46, 139, 87, 6530}, /* sea green */
+ {46, 139, 87, 6540}, /* SeaGreen */
+ {84, 255, 159, 6549}, /* SeaGreen1 */
+ {78, 238, 148, 6559}, /* SeaGreen2 */
+ {67, 205, 128, 6569}, /* SeaGreen3 */
+ {46, 139, 87, 6579}, /* SeaGreen4 */
+ {255, 245, 238, 6589}, /* seashell */
+ {255, 245, 238, 6598}, /* seashell1 */
+ {238, 229, 222, 6608}, /* seashell2 */
+ {205, 197, 191, 6618}, /* seashell3 */
+ {139, 134, 130, 6628}, /* seashell4 */
+ {160, 82, 45, 6638}, /* sienna */
+ {255, 130, 71, 6645}, /* sienna1 */
+ {238, 121, 66, 6653}, /* sienna2 */
+ {205, 104, 57, 6661}, /* sienna3 */
+ {139, 71, 38, 6669}, /* sienna4 */
+ {192, 192, 192, 6677}, /* silver */
+ {135, 206, 235, 6684}, /* sky blue */
+ {135, 206, 235, 6693}, /* SkyBlue */
+ {135, 206, 255, 6701}, /* SkyBlue1 */
+ {126, 192, 238, 6710}, /* SkyBlue2 */
+ {108, 166, 205, 6719}, /* SkyBlue3 */
+ {74, 112, 139, 6728}, /* SkyBlue4 */
+ {106, 90, 205, 6737}, /* slate blue */
+ {112, 128, 144, 6748}, /* slate gray */
+ {112, 128, 144, 6759}, /* slate grey */
+ {106, 90, 205, 6770}, /* SlateBlue */
+ {131, 111, 255, 6780}, /* SlateBlue1 */
+ {122, 103, 238, 6791}, /* SlateBlue2 */
+ {105, 89, 205, 6802}, /* SlateBlue3 */
+ {71, 60, 139, 6813}, /* SlateBlue4 */
+ {112, 128, 144, 6824}, /* SlateGray */
+ {198, 226, 255, 6834}, /* SlateGray1 */
+ {185, 211, 238, 6845}, /* SlateGray2 */
+ {159, 182, 205, 6856}, /* SlateGray3 */
+ {108, 123, 139, 6867}, /* SlateGray4 */
+ {112, 128, 144, 6878}, /* SlateGrey */
+ {255, 250, 250, 6888}, /* snow */
+ {255, 250, 250, 6893}, /* snow1 */
+ {238, 233, 233, 6899}, /* snow2 */
+ {205, 201, 201, 6905}, /* snow3 */
+ {139, 137, 137, 6911}, /* snow4 */
+ {0, 255, 127, 6917}, /* spring green */
+ {0, 255, 127, 6930}, /* SpringGreen */
+ {0, 255, 127, 6942}, /* SpringGreen1 */
+ {0, 238, 118, 6955}, /* SpringGreen2 */
+ {0, 205, 102, 6968}, /* SpringGreen3 */
+ {0, 139, 69, 6981}, /* SpringGreen4 */
+ {70, 130, 180, 6994}, /* steel blue */
+ {70, 130, 180, 7005}, /* SteelBlue */
+ {99, 184, 255, 7015}, /* SteelBlue1 */
+ {92, 172, 238, 7026}, /* SteelBlue2 */
+ {79, 148, 205, 7037}, /* SteelBlue3 */
+ {54, 100, 139, 7048}, /* SteelBlue4 */
+ {210, 180, 140, 7059}, /* tan */
+ {255, 165, 79, 7063}, /* tan1 */
+ {238, 154, 73, 7068}, /* tan2 */
+ {205, 133, 63, 7073}, /* tan3 */
+ {139, 90, 43, 7078}, /* tan4 */
+ {0, 128, 128, 7083}, /* teal */
+ {216, 191, 216, 7088}, /* thistle */
+ {255, 225, 255, 7096}, /* thistle1 */
+ {238, 210, 238, 7105}, /* thistle2 */
+ {205, 181, 205, 7114}, /* thistle3 */
+ {139, 123, 139, 7123}, /* thistle4 */
+ {255, 99, 71, 7132}, /* tomato */
+ {255, 99, 71, 7139}, /* tomato1 */
+ {238, 92, 66, 7147}, /* tomato2 */
+ {205, 79, 57, 7155}, /* tomato3 */
+ {139, 54, 38, 7163}, /* tomato4 */
+ {64, 224, 208, 7171}, /* turquoise */
+ {0, 245, 255, 7181}, /* turquoise1 */
+ {0, 229, 238, 7192}, /* turquoise2 */
+ {0, 197, 205, 7203}, /* turquoise3 */
+ {0, 134, 139, 7214}, /* turquoise4 */
+ {238, 130, 238, 7225}, /* violet */
+ {208, 32, 144, 7232}, /* violet red */
+ {208, 32, 144, 7243}, /* VioletRed */
+ {255, 62, 150, 7253}, /* VioletRed1 */
+ {238, 58, 140, 7264}, /* VioletRed2 */
+ {205, 50, 120, 7275}, /* VioletRed3 */
+ {139, 34, 82, 7286}, /* VioletRed4 */
+ {128, 128, 128, 7297}, /* web gray */
+ {0, 128, 0, 7306}, /* web green */
+ {128, 128, 128, 7316}, /* web grey */
+ {128, 0, 0, 7325}, /* web maroon */
+ {128, 0, 128, 7336}, /* web purple */
+ {128, 128, 128, 7347}, /* WebGray */
+ {0, 128, 0, 7355}, /* WebGreen */
+ {128, 128, 128, 7364}, /* WebGrey */
+ {128, 0, 0, 7372}, /* WebMaroon */
+ {128, 0, 128, 7382}, /* WebPurple */
+ {245, 222, 179, 7392}, /* wheat */
+ {255, 231, 186, 7398}, /* wheat1 */
+ {238, 216, 174, 7405}, /* wheat2 */
+ {205, 186, 150, 7412}, /* wheat3 */
+ {139, 126, 102, 7419}, /* wheat4 */
+ {255, 255, 255, 7426}, /* white */
+ {245, 245, 245, 7432}, /* white smoke */
+ {245, 245, 245, 7444}, /* WhiteSmoke */
+ {190, 190, 190, 7455}, /* x11 gray */
+ {0, 255, 0, 7464}, /* x11 green */
+ {190, 190, 190, 7474}, /* x11 grey */
+ {176, 48, 96, 7483}, /* x11 maroon */
+ {160, 32, 240, 7494}, /* x11 purple */
+ {190, 190, 190, 7505}, /* X11Gray */
+ {0, 255, 0, 7513}, /* X11Green */
+ {190, 190, 190, 7522}, /* X11Grey */
+ {176, 48, 96, 7530}, /* X11Maroon */
+ {160, 32, 240, 7540}, /* X11Purple */
+ {255, 255, 0, 7550}, /* yellow */
+ {154, 205, 50, 7557}, /* yellow green */
+ {255, 255, 0, 7570}, /* yellow1 */
+ {238, 238, 0, 7578}, /* yellow2 */
+ {205, 205, 0, 7586}, /* yellow3 */
+ {139, 139, 0, 7594}, /* yellow4 */
+ {154, 205, 50, 7602}, /* YellowGreen */
+};
+
+#define NUM_BUILTIN_COLORS (sizeof (BuiltinColors) / sizeof (BuiltinColors[0]))
+
+Bool
+OsLookupColor(int screen,
+ char *name,
+ unsigned int len,
+ unsigned short *pred,
+ unsigned short *pgreen, unsigned short *pblue)
+{
+ const BuiltinColor *c;
+ int low, mid, high;
+ int r;
+
+ low = 0;
+ high = NUM_BUILTIN_COLORS - 1;
+ while (high >= low) {
+ mid = (low + high) / 2;
+ c = &BuiltinColors[mid];
+ r = strncasecmp(&BuiltinColorNames[c->name], name, len);
+ if (r == 0 && len == strlen(&BuiltinColorNames[c->name])) {
+ *pred = c->red * 0x101;
+ *pgreen = c->green * 0x101;
+ *pblue = c->blue * 0x101;
+ return TRUE;
+ }
+ if (r < 0)
+ low = mid + 1;
+ else
+ high = mid - 1;
+ }
+ return FALSE;
+}
diff --git a/nx-X11/programs/Xserver/os/osdep.h b/nx-X11/programs/Xserver/os/osdep.h
new file mode 100644
index 000000000..d3e9d0b33
--- /dev/null
+++ b/nx-X11/programs/Xserver/os/osdep.h
@@ -0,0 +1,313 @@
+/***********************************************************
+
+Copyright 1987, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef _OSDEP_H_
+#define _OSDEP_H_ 1
+
+#define BUFSIZE 4096
+#define BUFWATERMARK 8192
+#ifndef MAXBUFSIZE
+#define MAXBUFSIZE (1 << 22)
+#endif
+
+#include <X11/Xdmcp.h>
+
+#ifndef X_NOT_POSIX
+#ifdef _POSIX_SOURCE
+#include <limits.h>
+#else
+#define _POSIX_SOURCE
+#include <limits.h>
+#undef _POSIX_SOURCE
+#endif
+#else /* X_NOT_POSIX */
+#ifdef WIN32
+#define _POSIX_
+#include <limits.h>
+#undef _POSIX_
+#endif
+#endif /* X_NOT_POSIX */
+
+#ifndef OPEN_MAX
+#ifdef SVR4
+#define OPEN_MAX 256
+#else
+#include <sys/param.h>
+#ifndef OPEN_MAX
+#if defined(NOFILE) && !defined(NOFILES_MAX)
+#define OPEN_MAX NOFILE
+#else
+#if !defined(WIN32)
+#define OPEN_MAX NOFILES_MAX
+#else
+#define OPEN_MAX 256
+#endif
+#endif
+#endif
+#endif
+#endif
+
+#include <nx-X11/Xpoll.h>
+
+/*
+ * MAXSOCKS is used only for initialising MaxClients when no other method
+ * like sysconf(_SC_OPEN_MAX) is not supported.
+ */
+
+#if OPEN_MAX <= 256
+#define MAXSOCKS (OPEN_MAX - 1)
+#else
+#define MAXSOCKS 256
+#endif
+
+/* MAXSELECT is the number of fds that select() can handle */
+#define MAXSELECT (sizeof(fd_set) * NBBY)
+
+#if !defined(SVR4) && !defined(SYSV)
+#define HAS_GETDTABLESIZE
+#endif
+
+#include <stddef.h>
+
+typedef Bool (*ValidatorFunc)(ARRAY8Ptr Auth, ARRAY8Ptr Data, int packet_type);
+typedef Bool (*GeneratorFunc)(ARRAY8Ptr Auth, ARRAY8Ptr Data, int packet_type);
+typedef Bool (*AddAuthorFunc)(unsigned name_length, char *name, unsigned data_length, char *data);
+
+typedef struct _connectionInput {
+ struct _connectionInput *next;
+ char *buffer; /* contains current client input */
+ char *bufptr; /* pointer to current start of data */
+ int bufcnt; /* count of bytes in buffer */
+ int lenLastReq;
+ int size;
+ unsigned int ignoreBytes; /* bytes to ignore before the next request */
+} ConnectionInput, *ConnectionInputPtr;
+
+typedef struct _connectionOutput {
+ struct _connectionOutput *next;
+ int size;
+ unsigned char *buf;
+ int count;
+} ConnectionOutput, *ConnectionOutputPtr;
+
+struct _osComm;
+
+#define AuthInitArgs void
+typedef void (*AuthInitFunc) (AuthInitArgs);
+
+#define AuthAddCArgs unsigned short data_length, char *data, XID id
+typedef int (*AuthAddCFunc) (AuthAddCArgs);
+
+#define AuthCheckArgs unsigned short data_length, char *data, ClientPtr client, char **reason
+typedef XID (*AuthCheckFunc) (AuthCheckArgs);
+
+#define AuthFromIDArgs XID id, unsigned short *data_lenp, char **datap
+typedef int (*AuthFromIDFunc) (AuthFromIDArgs);
+
+#define AuthGenCArgs unsigned data_length, char *data, XID id, unsigned *data_length_return, char **data_return
+typedef XID (*AuthGenCFunc) (AuthGenCArgs);
+
+#define AuthRemCArgs unsigned short data_length, char *data
+typedef int (*AuthRemCFunc) (AuthRemCArgs);
+
+#define AuthRstCArgs void
+typedef int (*AuthRstCFunc) (AuthRstCArgs);
+
+#define AuthToIDArgs unsigned short data_length, char *data
+typedef XID (*AuthToIDFunc) (AuthToIDArgs);
+
+typedef void (*OsCloseFunc)(ClientPtr);
+
+typedef int (*OsFlushFunc)(ClientPtr who, struct _osComm * oc, char* extraBuf, int extraCount);
+
+typedef struct _osComm {
+ int fd;
+ ConnectionInputPtr input;
+ ConnectionOutputPtr output;
+ XID auth_id; /* authorization id */
+ CARD32 conn_time; /* timestamp if not established, else 0 */
+ struct _XtransConnInfo *trans_conn; /* transport connection object */
+} OsCommRec, *OsCommPtr;
+
+extern int FlushClient(
+ ClientPtr /*who*/,
+ OsCommPtr /*oc*/,
+ const void * /*__extraBuf*/,
+ int /*extraCount*/
+);
+
+extern void FreeOsBuffers(
+ OsCommPtr /*oc*/
+);
+
+extern void InitNotifyFds(void);
+
+extern void HandleNotifyFds(void);
+
+#include "dix.h"
+
+extern ConnectionInputPtr AllocateInputBuffer(void);
+
+extern ConnectionOutputPtr AllocateOutputBuffer(void);
+
+extern fd_set AllSockets;
+extern fd_set AllClients;
+extern fd_set LastSelectMask;
+extern fd_set LastSelectWriteMask;
+extern fd_set WellKnownConnections;
+extern fd_set EnabledDevices;
+extern fd_set NotifyReadFds;
+extern fd_set NotifyWriteFds;
+extern fd_set ClientsWithInput;
+extern fd_set ClientsWriteBlocked;
+extern fd_set OutputPending;
+extern fd_set IgnoredClientsWithInput;
+
+#ifndef WIN32
+extern int *ConnectionTranslation;
+#else
+extern int GetConnectionTranslation(int conn);
+extern void SetConnectionTranslation(int conn, int client);
+extern void ClearConnectionTranslation();
+#endif
+
+extern Bool NewOutputPending;
+extern Bool AnyWritesPending;
+extern Bool NumNotifyWriteFd;
+extern Bool CriticalOutputPending;
+
+extern int timesThisConnection;
+extern ConnectionInputPtr FreeInputs;
+extern ConnectionOutputPtr FreeOutputs;
+extern OsCommPtr AvailableInput;
+
+extern WorkQueuePtr workQueue;
+
+/* added by raphael */
+#ifdef WIN32
+typedef long int fd_mask;
+#endif
+#define ffs mffs
+extern int mffs(fd_mask);
+
+/* in access.c */
+extern Bool ComputeLocalClient(ClientPtr client);
+
+/* in auth.c */
+extern void GenerateRandomData (int len, char *buf);
+
+/* in mitauth.c */
+extern XID MitCheckCookie (AuthCheckArgs);
+extern XID MitGenerateCookie (AuthGenCArgs);
+extern XID MitToID (AuthToIDArgs);
+extern int MitAddCookie (AuthAddCArgs);
+extern int MitFromID (AuthFromIDArgs);
+extern int MitRemoveCookie (AuthRemCArgs);
+extern int MitResetCookie (AuthRstCArgs);
+
+/* in xdmauth.c */
+#ifdef HASXDMAUTH
+extern XID XdmCheckCookie (AuthCheckArgs);
+extern XID XdmToID (AuthToIDArgs);
+extern int XdmAddCookie (AuthAddCArgs);
+extern int XdmFromID (AuthFromIDArgs);
+extern int XdmRemoveCookie (AuthRemCArgs);
+extern int XdmResetCookie (AuthRstCArgs);
+#endif
+
+/* in rpcauth.c */
+#ifdef SECURE_RPC
+extern void SecureRPCInit (AuthInitArgs);
+extern XID SecureRPCCheck (AuthCheckArgs);
+extern XID SecureRPCToID (AuthToIDArgs);
+extern int SecureRPCAdd (AuthAddCArgs);
+extern int SecureRPCFromID (AuthFromIDArgs);
+extern int SecureRPCRemove (AuthRemCArgs);
+extern int SecureRPCReset (AuthRstCArgs);
+#endif
+
+/* in secauth.c */
+extern XID AuthSecurityCheck (AuthCheckArgs);
+
+/* in xdmcp.c */
+extern void XdmcpUseMsg (void);
+extern int XdmcpOptions(int argc, char **argv, int i);
+extern void XdmcpSetAuthentication (ARRAY8Ptr name);
+extern void XdmcpRegisterConnection (
+ int type,
+ char *address,
+ int addrlen);
+extern void XdmcpRegisterAuthorizations (void);
+extern void XdmcpRegisterAuthorization (char *name, int namelen);
+extern void XdmcpRegisterDisplayClass (char *name, int length);
+extern void XdmcpInit (void);
+extern void XdmcpReset (void);
+extern void XdmcpOpenDisplay(int sock);
+extern void XdmcpCloseDisplay(int sock);
+extern void XdmcpRegisterAuthentication (
+ char *name,
+ int namelen,
+ char *data,
+ int datalen,
+ ValidatorFunc Validator,
+ GeneratorFunc Generator,
+ AddAuthorFunc AddAuth);
+extern int XdmcpCheckAuthentication (ARRAY8Ptr Name, ARRAY8Ptr Data, int packet_type);
+extern int XdmcpAddAuthorization (ARRAY8Ptr name, ARRAY8Ptr data);
+
+struct sockaddr_in;
+extern void XdmcpRegisterBroadcastAddress (struct sockaddr_in *addr);
+
+#ifdef HASXDMAUTH
+extern void XdmAuthenticationInit (char *cookie, int cookie_length);
+#endif
+
+#endif /* _OSDEP_H_ */
diff --git a/nx-X11/programs/Xserver/os/osinit.c b/nx-X11/programs/Xserver/os/osinit.c
new file mode 100644
index 000000000..a660337ca
--- /dev/null
+++ b/nx-X11/programs/Xserver/os/osinit.c
@@ -0,0 +1,234 @@
+/***********************************************************
+
+Copyright 1987, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <stdio.h>
+#include <nx-X11/X.h>
+#include "os.h"
+#include "osdep.h"
+#include <nx-X11/Xos.h>
+
+#include "dixstruct.h"
+
+#ifndef PATH_MAX
+#ifdef MAXPATHLEN
+#define PATH_MAX MAXPATHLEN
+#else
+#define PATH_MAX 1024
+#endif
+#endif
+
+#if defined(__SCO__)
+#include <sys/wait.h>
+#endif
+
+#if !defined(SYSV) && !defined(WIN32)
+#include <sys/resource.h>
+#endif
+
+#ifndef ADMPATH
+#define ADMPATH "/usr/adm/X%smsgs"
+#endif
+
+extern char *display;
+#ifdef RLIMIT_DATA
+int limitDataSpace = -1;
+#endif
+#ifdef RLIMIT_STACK
+int limitStackSpace = -1;
+#endif
+#ifdef RLIMIT_NOFILE
+int limitNoFile = -1;
+#endif
+
+void
+OsInit(void)
+{
+ static Bool been_here = FALSE;
+ static char* admpath = ADMPATH;
+ static char* devnull = "/dev/null";
+ char fname[PATH_MAX];
+
+#ifdef macII
+ set42sig();
+#endif
+
+ if (!been_here) {
+
+ InitNotifyFds();
+
+#if !defined(__SCO__) && !defined(__CYGWIN__) && !defined(__UNIXWARE__)
+ fclose(stdin);
+ fclose(stdout);
+#endif
+
+
+ /*
+ * If a write of zero bytes to stderr returns non-zero, i.e. -1,
+ * then writing to stderr failed, and we'll write somewhere else
+ * instead. (Apparently this never happens in the Real World.)
+ */
+ if (write (2, fname, 0) == -1)
+ {
+ FILE *err;
+
+ if (strlen (display) + strlen (admpath) + 1 < sizeof fname)
+ sprintf (fname, admpath, display);
+ else
+ strcpy (fname, devnull);
+ /*
+ * uses stdio to avoid os dependencies here,
+ * a real os would use
+ * open (fname, O_WRONLY|O_APPEND|O_CREAT, 0666)
+ */
+ if (!(err = fopen (fname, "a+")))
+ err = fopen (devnull, "w");
+ if (err && (fileno(err) != 2)) {
+ dup2 (fileno (err), 2);
+ fclose (err);
+ }
+#if defined(SYSV) || defined(SVR4) || defined(WIN32) || defined(__CYGWIN__)
+ {
+ static char buf[BUFSIZ];
+ setvbuf (stderr, buf, _IOLBF, BUFSIZ);
+ }
+#else
+ setlinebuf(stderr);
+#endif
+ }
+
+#ifndef X_NOT_POSIX
+ if (getpgrp () == 0)
+ setpgid (0, 0);
+#else
+#if !defined(SYSV) && !defined(WIN32)
+ if (getpgrp (0) == 0)
+ setpgrp (0, getpid ());
+#endif
+#endif
+
+#ifdef RLIMIT_DATA
+ if (limitDataSpace >= 0)
+ {
+ struct rlimit rlim;
+
+ if (!getrlimit(RLIMIT_DATA, &rlim))
+ {
+ if ((limitDataSpace > 0) && (limitDataSpace < rlim.rlim_max))
+ rlim.rlim_cur = limitDataSpace;
+ else
+ rlim.rlim_cur = rlim.rlim_max;
+ (void)setrlimit(RLIMIT_DATA, &rlim);
+ }
+ }
+#endif
+#ifdef RLIMIT_STACK
+ if (limitStackSpace >= 0)
+ {
+ struct rlimit rlim;
+
+ if (!getrlimit(RLIMIT_STACK, &rlim))
+ {
+ if ((limitStackSpace > 0) && (limitStackSpace < rlim.rlim_max))
+ rlim.rlim_cur = limitStackSpace;
+ else
+ rlim.rlim_cur = rlim.rlim_max;
+ (void)setrlimit(RLIMIT_STACK, &rlim);
+ }
+ }
+#endif
+#ifdef RLIMIT_NOFILE
+ if (limitNoFile >= 0)
+ {
+ struct rlimit rlim;
+
+ if (!getrlimit(RLIMIT_NOFILE, &rlim))
+ {
+ if ((limitNoFile > 0) && (limitNoFile < rlim.rlim_max))
+ rlim.rlim_cur = limitNoFile;
+ else
+ rlim.rlim_cur = rlim.rlim_max;
+#if 0
+ if (rlim.rlim_cur > MAXSOCKS)
+ rlim.rlim_cur = MAXSOCKS;
+#endif
+ (void)setrlimit(RLIMIT_NOFILE, &rlim);
+ }
+ }
+#endif
+#ifdef SERVER_LOCK
+ LockServer();
+#endif
+ been_here = TRUE;
+ }
+ TimerInit();
+#ifdef DDXOSINIT
+ OsVendorInit();
+#endif
+ /*
+ * No log file by default. OsVendorInit() should call LogInit() with the
+ * log file name if logging to a file is desired.
+ */
+ LogInit(NULL, NULL);
+ SmartScheduleInit();
+
+ OsInitAllocator();
+}
+
+void
+OsCleanup(Bool terminating)
+{
+#ifdef SERVER_LOCK
+ if (terminating)
+ {
+ UnlockServer();
+ }
+#endif
+}
diff --git a/nx-X11/programs/Xserver/os/reallocarray.c b/nx-X11/programs/Xserver/os/reallocarray.c
new file mode 100644
index 000000000..c415e09af
--- /dev/null
+++ b/nx-X11/programs/Xserver/os/reallocarray.c
@@ -0,0 +1,43 @@
+/* $OpenBSD: reallocarray.c,v 1.2 2014/12/08 03:45:00 bcook Exp $ */
+/*
+ * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <sys/types.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include "os.h"
+
+/*
+ * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
+ * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
+ */
+#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
+
+void *
+reallocarray(void *optr, size_t nmemb, size_t size)
+{
+ if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
+ nmemb > 0 && SIZE_MAX / nmemb < size) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ return realloc(optr, size * nmemb);
+}
diff --git a/nx-X11/programs/Xserver/os/rpcauth.c b/nx-X11/programs/Xserver/os/rpcauth.c
new file mode 100644
index 000000000..678bedf6c
--- /dev/null
+++ b/nx-X11/programs/Xserver/os/rpcauth.c
@@ -0,0 +1,201 @@
+/*
+
+Copyright 1991, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+
+/*
+ * SUN-DES-1 authentication mechanism
+ * Author: Mayank Choudhary, Sun Microsystems
+ */
+
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifdef SECURE_RPC
+
+#include <nx-X11/X.h>
+#include <nx-X11/Xauth.h>
+#include "misc.h"
+#include "os.h"
+#include "dixstruct.h"
+
+#include <rpc/rpc.h>
+
+#ifdef sun
+/* <rpc/auth.h> only includes this if _KERNEL is #defined... */
+extern bool_t xdr_opaque_auth(XDR *, struct opaque_auth *);
+#endif
+
+#ifdef ultrix
+#include <time.h>
+#include <rpc/auth_des.h>
+#endif
+
+static enum auth_stat why;
+
+static char *
+authdes_ezdecode(char *inmsg, int len)
+{
+ struct rpc_msg msg;
+ char cred_area[MAX_AUTH_BYTES];
+ char verf_area[MAX_AUTH_BYTES];
+ char *temp_inmsg;
+ struct svc_req r;
+ bool_t res0, res1;
+ XDR xdr;
+ SVCXPRT xprt;
+
+ temp_inmsg = (char *) malloc(len);
+ if (temp_inmsg == NULL) {
+ why = AUTH_FAILED; /* generic error, since there is no AUTH_BADALLOC */
+ return NULL;
+ }
+ memmove(temp_inmsg, inmsg, len);
+
+ memset((char *)&msg, 0, sizeof(msg));
+ memset((char *)&r, 0, sizeof(r));
+ memset(cred_area, 0, sizeof(cred_area));
+ memset(verf_area, 0, sizeof(verf_area));
+
+ msg.rm_call.cb_cred.oa_base = cred_area;
+ msg.rm_call.cb_verf.oa_base = verf_area;
+ why = AUTH_FAILED;
+ xdrmem_create(&xdr, temp_inmsg, len, XDR_DECODE);
+
+ if ((r.rq_clntcred = (caddr_t) malloc(MAX_AUTH_BYTES)) == NULL)
+ goto bad1;
+ r.rq_xprt = &xprt;
+
+ /* decode into msg */
+ res0 = xdr_opaque_auth(&xdr, &(msg.rm_call.cb_cred));
+ res1 = xdr_opaque_auth(&xdr, &(msg.rm_call.cb_verf));
+ if ( ! (res0 && res1) )
+ goto bad2;
+
+ /* do the authentication */
+
+ r.rq_cred = msg.rm_call.cb_cred; /* read by opaque stuff */
+ if (r.rq_cred.oa_flavor != AUTH_DES) {
+ why = AUTH_TOOWEAK;
+ goto bad2;
+ }
+#ifdef SVR4
+ if ((why = __authenticate(&r, &msg)) != AUTH_OK) {
+#else
+ if ((why = _authenticate(&r, &msg)) != AUTH_OK) {
+#endif
+ goto bad2;
+ }
+ return (((struct authdes_cred *) r.rq_clntcred)->adc_fullname.name);
+
+bad2:
+ free(r.rq_clntcred);
+bad1:
+ return ((char *)0); /* ((struct authdes_cred *) NULL); */
+}
+
+static XID rpc_id = (XID) ~0L;
+
+static Bool
+CheckNetName (
+ unsigned char *addr,
+ short len,
+ void * closure
+)
+{
+ return (len == strlen ((char *) closure) &&
+ strncmp ((char *) addr, (char *) closure, len) == 0);
+}
+
+static char rpc_error[MAXNETNAMELEN+50];
+
+XID
+SecureRPCCheck (unsigned short data_length, char *data,
+ ClientPtr client, char **reason)
+{
+ char *fullname;
+
+ if (rpc_id == (XID) ~0L) {
+ *reason = "Secure RPC authorization not initialized";
+ } else {
+ fullname = authdes_ezdecode(data, data_length);
+ if (fullname == (char *)0) {
+ sprintf(rpc_error, "Unable to authenticate secure RPC client (why=%d)", why);
+ *reason = rpc_error;
+ } else {
+ if (ForEachHostInFamily (FamilyNetname, CheckNetName, fullname))
+ return rpc_id;
+ sprintf(rpc_error, "Principal \"%s\" is not authorized to connect",
+ fullname);
+ *reason = rpc_error;
+ }
+ }
+ return (XID) ~0L;
+}
+
+void
+SecureRPCInit (void)
+{
+ if (rpc_id == ~0L)
+ AddAuthorization (9, "SUN-DES-1", 0, (char *) 0);
+}
+
+int
+SecureRPCAdd (unsigned short data_length, char *data, XID id)
+{
+ if (data_length)
+ AddHost ((void *) 0, FamilyNetname, data_length, data);
+ rpc_id = id;
+ return 1;
+}
+
+int
+SecureRPCReset (void)
+{
+ rpc_id = (XID) ~0L;
+ return 1;
+}
+
+XID
+SecureRPCToID (unsigned short data_length, char *data)
+{
+ return rpc_id;
+}
+
+int
+SecureRPCFromID (XID id, unsigned short *data_lenp, char **datap)
+{
+ return 0;
+}
+
+int
+SecureRPCRemove (unsigned short data_length, char *data)
+{
+ return 0;
+}
+#endif /* SECURE_RPC */
diff --git a/nx-X11/programs/Xserver/os/secauth.c b/nx-X11/programs/Xserver/os/secauth.c
new file mode 100644
index 000000000..5219b488a
--- /dev/null
+++ b/nx-X11/programs/Xserver/os/secauth.c
@@ -0,0 +1,203 @@
+/*
+Copyright 1996, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+*/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <nx-X11/X.h>
+#include "os.h"
+#include "osdep.h"
+#include "dixstruct.h"
+#include "swaprep.h"
+
+#ifdef XCSECURITY
+#define _SECURITY_SERVER
+#include <nx-X11/extensions/security.h>
+#endif
+
+static char InvalidPolicyReason[] = "invalid policy specification";
+static char PolicyViolationReason[] = "policy violation";
+
+static Bool
+AuthCheckSitePolicy(
+ unsigned short *data_lengthP,
+ char **dataP,
+ ClientPtr client,
+ char **reason)
+{
+ CARD8 *policy = *(CARD8 **)dataP;
+ int length;
+ Bool permit;
+ int nPolicies;
+ char **sitePolicies;
+ int nSitePolicies;
+ Bool found = FALSE;
+
+ if ((length = *data_lengthP) < 2) {
+ *reason = InvalidPolicyReason;
+ return FALSE;
+ }
+
+ permit = (*policy++ == 0);
+ nPolicies = (CARD8) *policy++;
+
+ length -= 2;
+
+ sitePolicies = SecurityGetSitePolicyStrings(&nSitePolicies);
+
+ while (nPolicies) {
+ int strLen, sitePolicy;
+
+ if (length == 0) {
+ *reason = InvalidPolicyReason;
+ return FALSE;
+ }
+
+ strLen = (CARD8) *policy++;
+ if (--length < strLen) {
+ *reason = InvalidPolicyReason;
+ return FALSE;
+ }
+
+ if (!found)
+ {
+ for (sitePolicy = 0; sitePolicy < nSitePolicies; sitePolicy++)
+ {
+ char *testPolicy = sitePolicies[sitePolicy];
+ if ((strLen == strlen(testPolicy)) &&
+ (strncmp((char *)policy, testPolicy, strLen) == 0))
+ {
+ found = TRUE; /* need to continue parsing the policy... */
+ break;
+ }
+ }
+ }
+
+ policy += strLen;
+ length -= strLen;
+ nPolicies--;
+ }
+
+ if (found != permit)
+ {
+ *reason = PolicyViolationReason;
+ return FALSE;
+ }
+
+ *data_lengthP = length;
+ *dataP = (char *)policy;
+ return TRUE;
+}
+
+XID
+AuthSecurityCheck (
+ unsigned short data_length,
+ char *data,
+ ClientPtr client,
+ char **reason)
+{
+#ifdef XCSECURITY
+ xConnSetupPrefix csp;
+ xReq freq;
+
+ if (client->clientState == ClientStateCheckedSecurity)
+ {
+ *reason = "repeated security check not permitted";
+ return (XID) -1;
+ }
+ else if (data_length > 0)
+ {
+ char policy_mask = *data++;
+
+ if (--data_length == 1) {
+ *reason = InvalidPolicyReason;
+ return (XID) -1;
+ }
+
+ if (policy_mask & 0x01) /* Extensions policy */
+ {
+ /* AuthCheckExtensionPolicy(&data_length, &data, client, reason) */
+ *reason = "security policy not implemented";
+ return (XID) -1;
+ }
+
+ if (policy_mask & 0x02) /* Site policy */
+ {
+ if (!AuthCheckSitePolicy(&data_length, &data, client, reason))
+ return (XID) -1;
+ }
+
+ if (data_length > 0) { /* did we consume the whole policy? */
+ *reason = InvalidPolicyReason;
+ return (XID) -1;
+ }
+
+ }
+ else if (!GetAccessControl())
+ {
+ /*
+ * The client - possibly the X FireWall Proxy - gave
+ * no auth data and host-based authorization is turned
+ * off. In this case, the client should be denied
+ * access to the X server.
+ */
+ *reason = "server host access control is disabled";
+ return (XID) -1;
+ }
+
+ client->clientState = ClientStateCheckingSecurity;
+
+ csp.success = 2 /* Authenticate */;
+ csp.lengthReason = 0;
+ csp.length = 0;
+ csp.majorVersion = X_PROTOCOL;
+ csp.minorVersion = X_PROTOCOL_REVISION;
+ if (client->swapped)
+ WriteSConnSetupPrefix(client, &csp);
+ else
+ WriteToClient(client, sz_xConnSetupPrefix, &csp);
+
+ /*
+ * Next time the client sends the real auth data, we want
+ * ProcEstablishConnection to be called.
+ */
+
+ freq.reqType = 1;
+ freq.length = (sz_xReq + sz_xConnClientPrefix) >> 2;
+ client->swapped = FALSE;
+ if (!InsertFakeRequest(client, (char *)&freq, sz_xReq))
+ {
+ *reason = "internal error";
+ return (XID) -1;
+ }
+
+ return (XID) 0;
+#else
+ *reason = "method not supported";
+ return (XID) -1;
+#endif
+}
diff --git a/nx-X11/programs/Xserver/os/strlcat.c b/nx-X11/programs/Xserver/os/strlcat.c
new file mode 100644
index 000000000..fc137cabb
--- /dev/null
+++ b/nx-X11/programs/Xserver/os/strlcat.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE
+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include <sys/types.h>
+#include <string.h>
+
+/*
+ * Appends src to string dst of size siz (unlike strncat, siz is the
+ * full size of dst, not space left). At most siz-1 characters
+ * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
+ * Returns strlen(src) + MIN(siz, strlen(initial dst)).
+ * If retval >= siz, truncation occurred.
+ */
+size_t
+strlcat(char *dst, const char *src, size_t siz)
+{
+ register char *d = dst;
+ register const char *s = src;
+ register size_t n = siz;
+ size_t dlen;
+
+ /* Find the end of dst and adjust bytes left but don't go past end */
+ while (n-- != 0 && *d != '\0')
+ d++;
+ dlen = d - dst;
+ n = siz - dlen;
+
+ if (n == 0)
+ return(dlen + strlen(s));
+ while (*s != '\0') {
+ if (n != 1) {
+ *d++ = *s;
+ n--;
+ }
+ s++;
+ }
+ *d = '\0';
+
+ return(dlen + (s - src)); /* count does not include NUL */
+}
diff --git a/nx-X11/programs/Xserver/os/strlcpy.c b/nx-X11/programs/Xserver/os/strlcpy.c
new file mode 100644
index 000000000..989d0385e
--- /dev/null
+++ b/nx-X11/programs/Xserver/os/strlcpy.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE
+ * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include <sys/types.h>
+#include <string.h>
+
+/*
+ * Copy src to string dst of size siz. At most siz-1 characters
+ * will be copied. Always NUL terminates (unless siz == 0).
+ * Returns strlen(src); if retval >= siz, truncation occurred.
+ */
+size_t
+strlcpy(char *dst, const char *src, size_t siz)
+{
+ register char *d = dst;
+ register const char *s = src;
+ register size_t n = siz;
+
+ /* Copy as many bytes as will fit */
+ if (n != 0 && --n != 0) {
+ do {
+ if ((*d++ = *s++) == 0)
+ break;
+ } while (--n != 0);
+ }
+
+ /* Not enough room in dst, add NUL and traverse rest of src */
+ if (n == 0) {
+ if (siz != 0)
+ *d = '\0'; /* NUL-terminate dst */
+ while (*s++)
+ ;
+ }
+
+ return(s - src - 1); /* count does not include NUL */
+}
diff --git a/nx-X11/programs/Xserver/os/timingsafe_memcmp.c b/nx-X11/programs/Xserver/os/timingsafe_memcmp.c
new file mode 100644
index 000000000..fe87de7bc
--- /dev/null
+++ b/nx-X11/programs/Xserver/os/timingsafe_memcmp.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2014 Google Inc.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <limits.h>
+#include <string.h>
+#include <nx-X11/Xfuncproto.h>
+#include "os.h"
+
+int
+timingsafe_memcmp(const void *b1, const void *b2, size_t len)
+{
+ const unsigned char *p1 = b1, *p2 = b2;
+ size_t i;
+ int res = 0, done = 0;
+
+ for (i = 0; i < len; i++) {
+ /* lt is -1 if p1[i] < p2[i]; else 0. */
+ int lt = (p1[i] - p2[i]) >> CHAR_BIT;
+
+ /* gt is -1 if p1[i] > p2[i]; else 0. */
+ int gt = (p2[i] - p1[i]) >> CHAR_BIT;
+
+ /* cmp is 1 if p1[i] > p2[i]; -1 if p1[i] < p2[i]; else 0. */
+ int cmp = lt - gt;
+
+ /* set res = cmp if !done. */
+ res |= cmp & ~done;
+
+ /* set done if p1[i] != p2[i]. */
+ done |= lt | gt;
+ }
+
+ return (res);
+}
diff --git a/nx-X11/programs/Xserver/os/utils.c b/nx-X11/programs/Xserver/os/utils.c
new file mode 100644
index 000000000..dd637ca4b
--- /dev/null
+++ b/nx-X11/programs/Xserver/os/utils.c
@@ -0,0 +1,2260 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* nx-X11, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+
+Copyright 1987, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
+Copyright 1994 Quarterdeck Office Systems.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Digital and
+Quarterdeck not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+DIGITAL AND QUARTERDECK DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT
+OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
+OR PERFORMANCE OF THIS SOFTWARE.
+
+*/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifdef __CYGWIN__
+#include <stdlib.h>
+#include <signal.h>
+#endif
+
+#if defined(WIN32) && !defined(__CYGWIN__)
+#include <nx-X11/Xwinsock.h>
+#endif
+#include <nx-X11/Xos.h>
+#include <stdio.h>
+#include "misc.h"
+#include <nx-X11/X.h>
+#define XSERV_t
+#define TRANS_SERVER
+#define TRANS_REOPEN
+#include <nx-X11/Xtrans/Xtrans.h>
+#include "input.h"
+#include "dixfont.h"
+#ifdef HAS_XFONT2
+# include <X11/fonts/libxfont2.h>
+#else
+# include <X11/fonts/fontutil.h>
+#endif /* HAS_XFONT2 */
+#include "osdep.h"
+#ifdef X_POSIX_C_SOURCE
+#define _POSIX_C_SOURCE X_POSIX_C_SOURCE
+#include <signal.h>
+#undef _POSIX_C_SOURCE
+#else
+#if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE)
+#include <signal.h>
+#else
+#define _POSIX_SOURCE
+#include <signal.h>
+#undef _POSIX_SOURCE
+#endif
+#endif
+#ifndef WIN32
+#include <sys/wait.h>
+#endif
+#if !defined(SYSV) && !defined(WIN32)
+#include <sys/resource.h>
+#endif
+#include <time.h>
+#include <sys/stat.h>
+#include <ctype.h> /* for isspace */
+#include <stdarg.h>
+#include <sys/types.h>
+#include <grp.h>
+#include <pwd.h>
+
+#include <stdlib.h> /* for malloc() */
+
+#if defined(TCPCONN)
+# ifndef WIN32
+# include <netdb.h>
+# endif
+#endif
+
+#include "opaque.h"
+
+#include "dixstruct.h"
+
+#ifdef XKB
+#include "xkbsrv.h"
+#endif
+#ifdef XCSECURITY
+#define _SECURITY_SERVER
+#include <nx-X11/extensions/security.h>
+#endif
+
+#ifdef RENDER
+#include "picture.h"
+#endif
+
+Bool noTestExtensions;
+#ifdef BIGREQS
+Bool noBigReqExtension = FALSE;
+#endif
+#ifdef COMPOSITE
+/* COMPOSITE is disabled by default for now until the
+ * interface is stable */
+Bool noCompositeExtension = TRUE;
+#endif
+#ifdef DAMAGE
+Bool noDamageExtension = FALSE;
+#endif
+#ifdef DBE
+Bool noDbeExtension = FALSE;
+#endif
+#ifdef DPSEXT
+Bool noDPSExtension = FALSE;
+#endif
+#ifdef DPMSExtension
+Bool noDPMSExtension = FALSE;
+#endif
+#ifdef GLXEXT
+Bool noGlxExtension = FALSE;
+#endif
+#ifdef SCREENSAVER
+Bool noScreenSaverExtension = FALSE;
+#endif
+#ifdef MITSHM
+Bool noMITShmExtension = FALSE;
+#endif
+#ifdef RANDR
+Bool noRRExtension = FALSE;
+Bool noRRXineramaExtension = FALSE;
+#endif
+#ifdef RENDER
+Bool noRenderExtension = FALSE;
+#endif
+#ifdef SHAPE
+Bool noShapeExtension = FALSE;
+#endif
+#ifdef XCSECURITY
+Bool noSecurityExtension = FALSE;
+#endif
+#ifdef XSYNC
+Bool noSyncExtension = FALSE;
+#endif
+#ifdef RES
+Bool noResExtension = FALSE;
+#endif
+#ifdef XCMISC
+Bool noXCMiscExtension = FALSE;
+#endif
+#ifdef XF86BIGFONT
+Bool noXFree86BigfontExtension = FALSE;
+#endif
+#ifdef XF86DRI
+Bool noXFree86DRIExtension = FALSE;
+#endif
+#ifdef XFIXES
+Bool noXFixesExtension = FALSE;
+#endif
+/* |noXkbExtension| is defined in xc/programs/Xserver/xkb/xkbInit.c */
+#ifdef PANORAMIX
+/* Xinerama is disabled by default unless enabled via +xinerama */
+Bool noPanoramiXExtension = TRUE;
+#endif
+#ifdef XINPUT
+Bool noXInputExtension = FALSE;
+#endif
+#ifdef XIDLE
+Bool noXIdleExtension = FALSE;
+#endif
+#ifdef XV
+Bool noXvExtension = FALSE;
+#endif
+
+#define X_INCLUDE_NETDB_H
+#include <nx-X11/Xos_r.h>
+
+#include <errno.h>
+
+#ifdef NX_TRANS_SOCKET
+
+#include <nx/NX.h>
+#include <nx/NXvars.h>
+
+#endif
+
+#ifdef NX_TRANS_EXIT
+
+void (*OsVendorStartRedirectErrorFProc)() = NULL;
+void (*OsVendorEndRedirectErrorFProc)() = NULL;
+
+#endif
+
+Bool CoreDump;
+
+#ifdef PANORAMIX
+Bool PanoramiXVisibilityNotifySent = FALSE;
+Bool PanoramiXMapped = FALSE;
+Bool PanoramiXWindowExposureSent = FALSE;
+Bool PanoramiXOneExposeRequest = FALSE;
+Bool PanoramiXExtensionDisabledHack = FALSE;
+#endif
+
+int auditTrailLevel = 1;
+
+Bool Must_have_memory = FALSE;
+
+#if defined(SVR4) || defined(__linux__) || defined(CSRG_BASED)
+#define HAS_SAVED_IDS_AND_SETEUID
+#endif
+
+#ifdef MEMBUG
+#define MEM_FAIL_SCALE 100000
+long Memory_fail = 0;
+#include <stdlib.h> /* for random() */
+#endif
+
+char *dev_tty_from_init = NULL; /* since we need to parse it anyway */
+
+extern char dispatchExceptionAtReset;
+
+/* Extension enable/disable in miinitext.c */
+extern Bool EnableDisableExtension(char *name, Bool enable);
+extern void EnableDisableExtensionError(char *name, Bool enable);
+
+OsSigHandlerPtr
+OsSignal(sig, handler)
+ int sig;
+ OsSigHandlerPtr handler;
+{
+#ifdef X_NOT_POSIX
+ return signal(sig, handler);
+#else
+ struct sigaction act, oact;
+
+ sigemptyset(&act.sa_mask);
+ if (handler != SIG_IGN)
+ sigaddset(&act.sa_mask, sig);
+ act.sa_flags = 0;
+ act.sa_handler = handler;
+ if (sigaction(sig, &act, &oact))
+ perror("sigaction");
+ return oact.sa_handler;
+#endif
+}
+
+#ifdef SERVER_LOCK
+/*
+ * Explicit support for a server lock file like the ones used for UUCP.
+ * For architectures with virtual terminals that can run more than one
+ * server at a time. This keeps the servers from stomping on each other
+ * if the user forgets to give them different display numbers.
+ */
+#define LOCK_DIR "/tmp"
+#define LOCK_TMP_PREFIX "/.tX"
+#define LOCK_PREFIX "/.X"
+#define LOCK_SUFFIX "-lock"
+
+#ifndef PATH_MAX
+#include <sys/param.h>
+#ifndef PATH_MAX
+#ifdef MAXPATHLEN
+#define PATH_MAX MAXPATHLEN
+#else
+#define PATH_MAX 1024
+#endif
+#endif
+#endif
+
+static Bool StillLocking = FALSE;
+static char LockFile[PATH_MAX];
+static Bool nolock = FALSE;
+
+/*
+ * LockServer --
+ * Check if the server lock file exists. If so, check if the PID
+ * contained inside is valid. If so, then die. Otherwise, create
+ * the lock file containing the PID.
+ */
+void
+LockServer(void)
+{
+ char tmp[PATH_MAX], pid_str[12];
+ int lfd, i, haslock, l_pid, t;
+ char *tmppath = NULL;
+ int len;
+ char port[20];
+
+ if (nolock || NoListenAll) return;
+ /*
+ * Path names
+ */
+ tmppath = LOCK_DIR;
+
+ sprintf(port, "%d", atoi(display));
+ len = strlen(LOCK_PREFIX) > strlen(LOCK_TMP_PREFIX) ? strlen(LOCK_PREFIX) :
+ strlen(LOCK_TMP_PREFIX);
+ len += strlen(tmppath) + strlen(port) + strlen(LOCK_SUFFIX) + 1;
+ if (len > sizeof(LockFile))
+ FatalError("Display name `%s' is too long\n", port);
+ (void)sprintf(tmp, "%s" LOCK_TMP_PREFIX "%s" LOCK_SUFFIX, tmppath, port);
+ (void)sprintf(LockFile, "%s" LOCK_PREFIX "%s" LOCK_SUFFIX, tmppath, port);
+
+ /*
+ * Create a temporary file containing our PID. Attempt three times
+ * to create the file.
+ */
+ StillLocking = TRUE;
+ i = 0;
+ do {
+ i++;
+ lfd = open(tmp, O_CREAT | O_EXCL | O_WRONLY, 0644);
+ if (lfd < 0)
+ sleep(2);
+ else
+ break;
+ } while (i < 3);
+ if (lfd < 0) {
+ unlink(tmp);
+ i = 0;
+ do {
+ i++;
+ lfd = open(tmp, O_CREAT | O_EXCL | O_WRONLY, 0644);
+ if (lfd < 0)
+ sleep(2);
+ else
+ break;
+ } while (i < 3);
+ }
+ if (lfd < 0)
+ FatalError("Could not create lock file in %s\n", tmp);
+ (void) sprintf(pid_str, "%10ld\n", (long)getpid());
+ if (write(lfd, pid_str, 11) != 11)
+ FatalError("Could not write pid to lock file in %s\n", tmp);
+
+#ifndef USE_CHMOD
+ (void) fchmod(lfd, 0444);
+#else
+ (void) chmod(tmp, 0444);
+#endif
+ (void) close(lfd);
+
+ /*
+ * OK. Now the tmp file exists. Try three times to move it in place
+ * for the lock.
+ */
+ i = 0;
+ haslock = 0;
+ while ((!haslock) && (i++ < 3)) {
+ haslock = (link(tmp,LockFile) == 0);
+ if (haslock) {
+ /*
+ * We're done.
+ */
+ break;
+ }
+ else {
+ /*
+ * Read the pid from the existing file
+ */
+ lfd = open(LockFile, O_RDONLY|O_NOFOLLOW);
+ if (lfd < 0) {
+ unlink(tmp);
+ FatalError("Can't read lock file %s\n", LockFile);
+ }
+ pid_str[0] = '\0';
+ if (read(lfd, pid_str, 11) != 11) {
+ /*
+ * Bogus lock file.
+ */
+ unlink(LockFile);
+ close(lfd);
+ continue;
+ }
+ pid_str[11] = '\0';
+ sscanf(pid_str, "%d", &l_pid);
+ close(lfd);
+
+ /*
+ * Now try to kill the PID to see if it exists.
+ */
+ errno = 0;
+ t = kill(l_pid, 0);
+ if ((t< 0) && (errno == ESRCH)) {
+ /*
+ * Stale lock file.
+ */
+ unlink(LockFile);
+ continue;
+ }
+ else if (((t < 0) && (errno == EPERM)) || (t == 0)) {
+ /*
+ * Process is still active.
+ */
+ unlink(tmp);
+ FatalError("Server is already active for display %s\n%s %s\n%s\n",
+ port, "\tIf this server is no longer running, remove",
+ LockFile, "\tand start again.");
+ }
+ }
+ }
+ unlink(tmp);
+ if (!haslock)
+ FatalError("Could not create server lock file: %s\n", LockFile);
+ StillLocking = FALSE;
+}
+
+/*
+ * UnlockServer --
+ * Remove the server lock file.
+ */
+void
+UnlockServer(void)
+{
+ if (nolock || NoListenAll) return;
+
+ if (!StillLocking){
+
+ (void) unlink(LockFile);
+ }
+}
+#endif /* SERVER_LOCK */
+
+/* Force connections to close on SIGHUP from init */
+
+/*ARGSUSED*/
+SIGVAL
+AutoResetServer (int sig)
+{
+ int olderrno = errno;
+
+ dispatchException |= DE_RESET;
+ isItTimeToYield = TRUE;
+#ifdef GPROF
+ chdir ("/tmp");
+ exit (0);
+#endif
+#if defined(SYSV) && defined(X_NOT_POSIX)
+ OsSignal (SIGHUP, AutoResetServer);
+#endif
+ errno = olderrno;
+}
+
+/* Force connections to close and then exit on SIGTERM, SIGINT */
+
+/*ARGSUSED*/
+SIGVAL
+GiveUp(int sig)
+{
+ int olderrno = errno;
+
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
+ fprintf(stderr, "GiveUp: Called with signal [%d].\n", sig);
+#endif
+
+ dispatchException |= DE_TERMINATE;
+ isItTimeToYield = TRUE;
+#if defined(SYSV) && defined(X_NOT_POSIX)
+ if (sig)
+ OsSignal(sig, SIG_IGN);
+#endif
+ errno = olderrno;
+}
+
+#ifndef DDXTIME
+CARD32
+GetTimeInMillis(void)
+{
+ struct timeval tp;
+
+ X_GETTIMEOFDAY(&tp);
+ return(tp.tv_sec * 1000) + (tp.tv_usec / 1000);
+}
+#endif
+
+void
+AdjustWaitForDelay (void * waitTime, unsigned long newdelay)
+{
+ static struct timeval delay_val;
+ struct timeval **wt = (struct timeval **) waitTime;
+ unsigned long olddelay;
+
+ if (*wt == NULL)
+ {
+ delay_val.tv_sec = newdelay / 1000;
+ delay_val.tv_usec = 1000 * (newdelay % 1000);
+ *wt = &delay_val;
+ }
+ else
+ {
+ olddelay = (*wt)->tv_sec * 1000 + (*wt)->tv_usec / 1000;
+ if (newdelay < olddelay)
+ {
+ (*wt)->tv_sec = newdelay / 1000;
+ (*wt)->tv_usec = 1000 * (newdelay % 1000);
+ }
+ }
+}
+
+void UseMsg(void)
+{
+ ErrorF("use: X [:<display>] [option]\n");
+ ErrorF("-a # mouse acceleration (pixels)\n");
+ ErrorF("-ac disable access control restrictions\n");
+#ifdef MEMBUG
+ ErrorF("-alloc int chance alloc should fail\n");
+#endif
+ ErrorF("-audit int set audit trail level\n");
+ ErrorF("-auth file select authorization file\n");
+ ErrorF("bc enable bug compatibility\n");
+ ErrorF("-br create root window with black background\n");
+ ErrorF("+bs enable any backing store support\n");
+ ErrorF("-bs disable any backing store support\n");
+ ErrorF("-c turns off key-click\n");
+ ErrorF("c # key-click volume (0-100)\n");
+ ErrorF("-cc int default color visual class\n");
+#ifdef COMMANDLINE_CHALLENGED_OPERATING_SYSTEMS
+ ErrorF("-config file read options from file\n");
+#endif
+ ErrorF("-core generate core dump on fatal error\n");
+ ErrorF("-dpi int screen resolution in dots per inch\n");
+#ifdef DPMSExtension
+ ErrorF("dpms enables VESA DPMS monitor control\n");
+ ErrorF("-dpms disables VESA DPMS monitor control\n");
+#endif
+ ErrorF("-deferglyphs [none|all|16] defer loading of [no|all|16-bit] glyphs\n");
+ ErrorF("-f # bell base (0-100)\n");
+ ErrorF("-fc string cursor font\n");
+ ErrorF("-fn string default font name\n");
+ ErrorF("-fp string default font path\n");
+ ErrorF("-help prints message with these options\n");
+ ErrorF("-I ignore all remaining arguments\n");
+#ifdef RLIMIT_DATA
+ ErrorF("-ld int limit data space to N Kb\n");
+#endif
+#ifdef RLIMIT_NOFILE
+ ErrorF("-lf int limit number of open files to N\n");
+#endif
+#ifdef RLIMIT_STACK
+ ErrorF("-ls int limit stack space to N Kb\n");
+#endif
+#ifdef SERVER_LOCK
+ ErrorF("-nolock disable the locking mechanism\n");
+#endif
+#ifndef NOLOGOHACK
+ ErrorF("-logo enable logo in screen saver\n");
+ ErrorF("nologo disable logo in screen saver\n");
+#endif
+ ErrorF("-nolisten string don't listen on protocol\n");
+ ErrorF("-noreset don't reset after last client exists\n");
+ ErrorF("-reset reset after last client exists\n");
+ ErrorF("-p # screen-saver pattern duration (minutes)\n");
+ ErrorF("-pn accept failure to listen on all ports\n");
+ ErrorF("-nopn reject failure to listen on all ports\n");
+ ErrorF("-r turns off auto-repeat\n");
+ ErrorF("r turns on auto-repeat \n");
+#ifdef RENDER
+ ErrorF("-render [default|mono|gray|color] set render color alloc policy\n");
+#endif
+ ErrorF("-s # screen-saver timeout (minutes)\n");
+#ifdef XCSECURITY
+ ErrorF("-sp file security policy file\n");
+#endif
+ ErrorF("-su disable any save under support\n");
+ ErrorF("-t # mouse threshold (pixels)\n");
+ ErrorF("-terminate terminate at server reset\n");
+ ErrorF("-to # connection time out\n");
+ ErrorF("-tst disable testing extensions\n");
+ ErrorF("ttyxx server started from init on /dev/ttyxx\n");
+ ErrorF("v video blanking for screen-saver\n");
+ ErrorF("-v screen-saver without video blanking\n");
+ ErrorF("-wm WhenMapped default backing-store\n");
+ ErrorF("-maxbigreqsize set maximal bigrequest size \n");
+#ifdef PANORAMIX
+ ErrorF("+xinerama Enable XINERAMA (PanoramiX) extension\n");
+ ErrorF("-xinerama Disable XINERAMA (PanoramiX) extension (default)\n");
+ ErrorF("-disablexineramaextension Disable XINERAMA extension\n");
+#endif
+#ifdef RANDR
+ ErrorF("+rrxinerama Enable XINERAMA (via RandR) extension (default)\n");
+ ErrorF("-rrxinerama Disable XINERAMA (via RandR) extension\n");
+#endif
+ ErrorF("-dumbSched Disable smart scheduling, enable old behavior\n");
+ ErrorF("-schedInterval int Set scheduler interval in msec\n");
+ ErrorF("+extension name Enable extension\n");
+ ErrorF("-extension name Disable extension\n");
+#ifdef XDMCP
+ XdmcpUseMsg();
+#endif
+#ifdef XKB
+ XkbUseMsg();
+#endif
+ ddxUseMsg();
+}
+
+/* This function performs a rudimentary sanity check
+ * on the display name passed in on the command-line,
+ * since this string is used to generate filenames.
+ * It is especially important that the display name
+ * not contain a "/" and not start with a "-".
+ * --kvajk
+ */
+static int
+VerifyDisplayName(const char *d)
+{
+ if ( d == (char *)0 ) return( 0 ); /* null */
+ if ( *d == '\0' ) return( 0 ); /* empty */
+ if ( *d == '-' ) return( 0 ); /* could be confused for an option */
+ if ( *d == '.' ) return( 0 ); /* must not equal "." or ".." */
+ if ( strchr(d, '/') != (char *)0 ) return( 0 ); /* very important!!! */
+ return( 1 );
+}
+
+/*
+ * This function is responsible for doing initalisation of any global
+ * variables at an very early point of server startup (even before
+ * |ProcessCommandLine()|.
+ */
+void InitGlobals(void)
+{
+ ddxInitGlobals();
+}
+
+
+/*
+ * This function parses the command line. Handles device-independent fields
+ * and allows ddx to handle additional fields. It is not allowed to modify
+ * argc or any of the strings pointed to by argv.
+ */
+void
+ProcessCommandLine(int argc, char *argv[])
+{
+ int i, skip;
+
+ defaultKeyboardControl.autoRepeat = TRUE;
+
+#ifdef NO_PART_NET
+ PartialNetwork = FALSE;
+#else
+ PartialNetwork = TRUE;
+#endif
+
+ for ( i = 1; i < argc; i++ )
+ {
+ /* call ddx first, so it can peek/override if it wants */
+ if((skip = ddxProcessArgument(argc, argv, i)))
+ {
+ i += (skip - 1);
+ }
+ else if(argv[i][0] == ':')
+ {
+ /* initialize display */
+ display = argv[i];
+ explicit_display = TRUE;
+ display++;
+ if( ! VerifyDisplayName( display ) ) {
+ ErrorF("Bad display name: %s\n", display);
+ UseMsg();
+ FatalError("Bad display name, exiting: %s\n", display);
+ }
+ }
+ else if ( strcmp( argv[i], "-a") == 0)
+ {
+ if(++i < argc)
+ defaultPointerControl.num = atoi(argv[i]);
+ else
+ UseMsg();
+ }
+ else if ( strcmp( argv[i], "-ac") == 0)
+ {
+ defeatAccessControl = TRUE;
+ }
+#ifdef MEMBUG
+ else if ( strcmp( argv[i], "-alloc") == 0)
+ {
+ if(++i < argc)
+ Memory_fail = atoi(argv[i]);
+ else
+ UseMsg();
+ }
+#endif
+ else if ( strcmp( argv[i], "-audit") == 0)
+ {
+ if(++i < argc)
+ auditTrailLevel = atoi(argv[i]);
+ else
+ UseMsg();
+ }
+ else if ( strcmp( argv[i], "-auth") == 0)
+ {
+ if(++i < argc)
+ InitAuthorization (argv[i]);
+ else
+ UseMsg();
+ }
+ else if ( strcmp( argv[i], "bc") == 0)
+ permitOldBugs = TRUE;
+ else if ( strcmp( argv[i], "-br") == 0)
+ blackRoot = TRUE;
+ else if ( strcmp( argv[i], "+bs") == 0)
+ enableBackingStore = TRUE;
+ else if ( strcmp( argv[i], "-bs") == 0)
+ disableBackingStore = TRUE;
+ else if ( strcmp( argv[i], "c") == 0)
+ {
+ if(++i < argc)
+ defaultKeyboardControl.click = atoi(argv[i]);
+ else
+ UseMsg();
+ }
+ else if ( strcmp( argv[i], "-c") == 0)
+ {
+ defaultKeyboardControl.click = 0;
+ }
+ else if ( strcmp( argv[i], "-cc") == 0)
+ {
+ if(++i < argc)
+ defaultColorVisualClass = atoi(argv[i]);
+ else
+ UseMsg();
+ }
+ else if ( strcmp( argv[i], "-core") == 0)
+ CoreDump = TRUE;
+ else if ( strcmp( argv[i], "-dpi") == 0)
+ {
+ if(++i < argc)
+ monitorResolution = atoi(argv[i]);
+ else
+ UseMsg();
+ }
+ else if (strcmp(argv[i], "-displayfd") == 0) {
+ if (++i < argc) {
+ displayfd = atoi(argv[i]);
+ nolock = TRUE;
+ }
+ else
+ UseMsg();
+ }
+
+#ifdef DPMSExtension
+ else if ( strcmp( argv[i], "dpms") == 0)
+ DPMSEnabledSwitch = TRUE;
+ else if ( strcmp( argv[i], "-dpms") == 0)
+ DPMSDisabledSwitch = TRUE;
+#endif
+ else if ( strcmp( argv[i], "-deferglyphs") == 0)
+ {
+#ifdef HAS_XFONT2
+ if(++i >= argc || !!xfont2_parse_glyph_caching_mode(argv[i]))
+#else
+ if(++i >= argc || !ParseGlyphCachingMode(argv[i]))
+#endif /* HAS_XFONT2 */
+ UseMsg();
+ }
+ else if ( strcmp( argv[i], "-f") == 0)
+ {
+ if(++i < argc)
+ defaultKeyboardControl.bell = atoi(argv[i]);
+ else
+ UseMsg();
+ }
+ else if ( strcmp( argv[i], "-fc") == 0)
+ {
+ if(++i < argc)
+ defaultCursorFont = argv[i];
+ else
+ UseMsg();
+ }
+ else if ( strcmp( argv[i], "-fn") == 0)
+ {
+ if(++i < argc)
+ defaultTextFont = argv[i];
+ else
+ UseMsg();
+ }
+ else if ( strcmp( argv[i], "-fp") == 0)
+ {
+ if(++i < argc)
+ {
+ defaultFontPath = argv[i];
+ }
+ else
+ UseMsg();
+ }
+ else if ( strcmp( argv[i], "-help") == 0)
+ {
+ UseMsg();
+ exit(0);
+ }
+#ifdef XKB
+ else if ( (skip=XkbProcessArguments(argc,argv,i))!=0 ) {
+ if (skip>0)
+ i+= skip-1;
+ else UseMsg();
+ }
+#endif
+#ifdef RLIMIT_DATA
+ else if ( strcmp( argv[i], "-ld") == 0)
+ {
+ if(++i < argc)
+ {
+ limitDataSpace = atoi(argv[i]);
+ if (limitDataSpace > 0)
+ limitDataSpace *= 1024;
+ }
+ else
+ UseMsg();
+ }
+#endif
+#ifdef RLIMIT_NOFILE
+ else if ( strcmp( argv[i], "-lf") == 0)
+ {
+ if(++i < argc)
+ limitNoFile = atoi(argv[i]);
+ else
+ UseMsg();
+ }
+#endif
+#ifdef RLIMIT_STACK
+ else if ( strcmp( argv[i], "-ls") == 0)
+ {
+ if(++i < argc)
+ {
+ limitStackSpace = atoi(argv[i]);
+ if (limitStackSpace > 0)
+ limitStackSpace *= 1024;
+ }
+ else
+ UseMsg();
+ }
+#endif
+#ifdef SERVER_LOCK
+ else if ( strcmp ( argv[i], "-nolock") == 0)
+ {
+#if !defined(WIN32) && !defined(__CYGWIN__)
+ if (getuid() != 0)
+ ErrorF("Warning: the -nolock option can only be used by root\n");
+ else
+#endif
+ nolock = TRUE;
+ }
+#endif
+#ifndef NOLOGOHACK
+ else if ( strcmp( argv[i], "-logo") == 0)
+ {
+ logoScreenSaver = 1;
+ }
+ else if ( strcmp( argv[i], "nologo") == 0)
+ {
+ logoScreenSaver = 0;
+ }
+#endif
+ else if ( strcmp( argv[i], "-nolisten") == 0)
+ {
+ if(++i < argc) {
+#ifdef NXAGENT_SERVER
+ if (strcmp( argv[i], "ANY" ) == 0)
+ NoListenAll = TRUE;
+ else
+#endif /* NXAGENT_SERVER */
+ if (_XSERVTransNoListen(argv[i]))
+ FatalError ("Failed to disable listen for %s transport",
+ argv[i]);
+ } else
+ UseMsg();
+ }
+ else if ( strcmp( argv[i], "-noreset") == 0)
+ {
+ dispatchExceptionAtReset = 0;
+ }
+ else if ( strcmp( argv[i], "-reset") == 0)
+ {
+ dispatchExceptionAtReset = DE_RESET;
+ }
+ else if ( strcmp( argv[i], "-p") == 0)
+ {
+ if(++i < argc)
+ defaultScreenSaverInterval = ((CARD32)atoi(argv[i])) *
+ MILLI_PER_MIN;
+ else
+ UseMsg();
+ }
+ else if ( strcmp( argv[i], "-pn") == 0)
+ PartialNetwork = TRUE;
+ else if ( strcmp( argv[i], "-nopn") == 0)
+ PartialNetwork = FALSE;
+ else if ( strcmp( argv[i], "r") == 0)
+ defaultKeyboardControl.autoRepeat = TRUE;
+ else if ( strcmp( argv[i], "-r") == 0)
+ defaultKeyboardControl.autoRepeat = FALSE;
+ else if ( strcmp( argv[i], "-s") == 0)
+ {
+ if(++i < argc)
+ defaultScreenSaverTime = ((CARD32)atoi(argv[i])) *
+ MILLI_PER_MIN;
+ else
+ UseMsg();
+ }
+ else if ( strcmp( argv[i], "-su") == 0)
+ disableSaveUnders = TRUE;
+ else if ( strcmp( argv[i], "-t") == 0)
+ {
+ if(++i < argc)
+ defaultPointerControl.threshold = atoi(argv[i]);
+ else
+ UseMsg();
+ }
+ else if ( strcmp( argv[i], "-terminate") == 0)
+ {
+ dispatchExceptionAtReset = DE_TERMINATE;
+ }
+ else if ( strcmp( argv[i], "-to") == 0)
+ {
+ if(++i < argc)
+ TimeOutValue = ((CARD32)atoi(argv[i])) * MILLI_PER_SECOND;
+ else
+ UseMsg();
+ }
+ else if ( strcmp( argv[i], "-tst") == 0)
+ {
+ noTestExtensions = TRUE;
+ }
+ else if ( strcmp( argv[i], "v") == 0)
+ defaultScreenSaverBlanking = PreferBlanking;
+ else if ( strcmp( argv[i], "-v") == 0)
+ defaultScreenSaverBlanking = DontPreferBlanking;
+ else if ( strcmp( argv[i], "-wm") == 0)
+ defaultBackingStore = WhenMapped;
+ else if ( strcmp( argv[i], "-maxbigreqsize") == 0) {
+ if(++i < argc) {
+ long reqSizeArg = atol(argv[i]);
+
+ /* Request size > 128MB does not make much sense... */
+ if( reqSizeArg > 0L && reqSizeArg < 128L ) {
+ maxBigRequestSize = (reqSizeArg * 1048576L) - 1L;
+ }
+ else
+ {
+ UseMsg();
+ }
+ }
+ else
+ {
+ UseMsg();
+ }
+ }
+#ifdef PANORAMIX
+ else if ( strcmp( argv[i], "+xinerama") == 0){
+ noPanoramiXExtension = FALSE;
+ }
+ else if ( strcmp( argv[i], "-xinerama") == 0){
+ noPanoramiXExtension = TRUE;
+ }
+ else if ( strcmp( argv[i], "-disablexineramaextension") == 0){
+ PanoramiXExtensionDisabledHack = TRUE;
+ }
+#endif
+#ifdef RANDR
+ else if ( strcmp( argv[i], "+rrxinerama") == 0){
+ noRRXineramaExtension = FALSE;
+ }
+ else if ( strcmp( argv[i], "-rrxinerama") == 0){
+ noRRXineramaExtension = TRUE;
+ }
+#endif
+ else if ( strcmp( argv[i], "-I") == 0)
+ {
+ /* ignore all remaining arguments */
+ break;
+ }
+ else if (strncmp (argv[i], "tty", 3) == 0)
+ {
+ /* just in case any body is interested */
+ dev_tty_from_init = argv[i];
+ }
+#ifdef XDMCP
+ else if ((skip = XdmcpOptions(argc, argv, i)) != i)
+ {
+ i = skip - 1;
+ }
+#endif
+#ifdef XCSECURITY
+ else if ((skip = XSecurityOptions(argc, argv, i)) != i)
+ {
+ i = skip - 1;
+ }
+#endif
+#if HAVE_SETITIMER
+ else if ( strcmp( argv[i], "-dumbSched") == 0)
+ {
+ SmartScheduleSignalEnable = FALSE;
+ }
+#endif
+ else if ( strcmp( argv[i], "-schedInterval") == 0)
+ {
+ if (++i < argc)
+ {
+ SmartScheduleInterval = atoi(argv[i]);
+ SmartScheduleSlice = SmartScheduleInterval;
+ }
+ else
+ UseMsg();
+ }
+ else if ( strcmp( argv[i], "-schedMax") == 0)
+ {
+ if (++i < argc)
+ {
+ SmartScheduleMaxSlice = atoi(argv[i]);
+ }
+ else
+ UseMsg();
+ }
+#ifdef RENDER
+ else if ( strcmp( argv[i], "-render" ) == 0)
+ {
+ if (++i < argc)
+ {
+ int policy = PictureParseCmapPolicy (argv[i]);
+
+ if (policy != PictureCmapPolicyInvalid)
+ PictureCmapPolicy = policy;
+ else
+ UseMsg ();
+ }
+ else
+ UseMsg ();
+ }
+#endif
+ else if ( strcmp( argv[i], "+extension") == 0)
+ {
+ if (++i < argc)
+ {
+ if (!EnableDisableExtension(argv[i], TRUE))
+ EnableDisableExtensionError(argv[i], TRUE);
+ }
+ else
+ UseMsg();
+ }
+ else if ( strcmp( argv[i], "-extension") == 0)
+ {
+ if (++i < argc)
+ {
+ if (!EnableDisableExtension(argv[i], FALSE))
+ EnableDisableExtensionError(argv[i], FALSE);
+ }
+ else
+ UseMsg();
+ }
+ else
+ {
+ ErrorF("Unrecognized option: %s\n", argv[i]);
+ UseMsg();
+ FatalError("Unrecognized option: %s\n", argv[i]);
+ }
+ }
+}
+
+#ifdef COMMANDLINE_CHALLENGED_OPERATING_SYSTEMS
+static void
+InsertFileIntoCommandLine(
+ int *resargc, char ***resargv,
+ int prefix_argc, char **prefix_argv,
+ char *filename,
+ int suffix_argc, char **suffix_argv)
+{
+ struct stat st;
+ FILE *f;
+ char *p;
+ char *q;
+ int insert_argc;
+ char *buf;
+ int len;
+ int i;
+
+ f = fopen(filename, "r");
+ if (!f)
+ FatalError("Can't open option file %s\n", filename);
+
+ fstat(fileno(f), &st);
+
+ buf = (char *) malloc((unsigned) st.st_size + 1);
+ if (!buf)
+ FatalError("Out of Memory\n");
+
+ len = fread(buf, 1, (unsigned) st.st_size, f);
+
+ fclose(f);
+
+ if (len < 0)
+ FatalError("Error reading option file %s\n", filename);
+
+ buf[len] = '\0';
+
+ p = buf;
+ q = buf;
+ insert_argc = 0;
+
+ while (*p)
+ {
+ while (isspace(*p))
+ p++;
+ if (!*p)
+ break;
+ if (*p == '#')
+ {
+ while (*p && *p != '\n')
+ p++;
+ } else
+ {
+ while (*p && !isspace(*p))
+ *q++ = *p++;
+ /* Since p and q might still be pointing at the same place, we */
+ /* need to step p over the whitespace now before we add the null. */
+ if (*p)
+ p++;
+ *q++ = '\0';
+ insert_argc++;
+ }
+ }
+
+ buf = (char *) realloc(buf, q - buf);
+ if (!buf)
+ FatalError("Out of memory reallocing option buf\n");
+
+ *resargc = prefix_argc + insert_argc + suffix_argc;
+ *resargv = (char **) malloc((*resargc + 1) * sizeof(char *));
+ if (!*resargv)
+ FatalError("Out of Memory\n");
+
+ memcpy(*resargv, prefix_argv, prefix_argc * sizeof(char *));
+
+ p = buf;
+ for (i = 0; i < insert_argc; i++)
+ {
+ (*resargv)[prefix_argc + i] = p;
+ p += strlen(p) + 1;
+ }
+
+ memcpy(*resargv + prefix_argc + insert_argc,
+ suffix_argv, suffix_argc * sizeof(char *));
+
+ (*resargv)[*resargc] = NULL;
+} /* end InsertFileIntoCommandLine */
+
+
+void
+ExpandCommandLine(int *pargc, char ***pargv)
+{
+ int i;
+
+#if !defined(WIN32) && !defined(__CYGWIN__)
+ if (getuid() != geteuid())
+ return;
+#endif
+
+ for (i = 1; i < *pargc; i++)
+ {
+ if ( (0 == strcmp((*pargv)[i], "-config")) && (i < (*pargc - 1)) )
+ {
+ InsertFileIntoCommandLine(pargc, pargv,
+ i, *pargv,
+ (*pargv)[i+1], /* filename */
+ *pargc - i - 2, *pargv + i + 2);
+ i--;
+ }
+ }
+} /* end ExpandCommandLine */
+#endif
+
+/* Implement a simple-minded font authorization scheme. The authorization
+ name is "hp-hostname-1", the contents are simply the host name. */
+int
+set_font_authorizations(char **authorizations, int *authlen, void * client)
+{
+#define AUTHORIZATION_NAME "hp-hostname-1"
+#if defined(TCPCONN)
+ static char *result = NULL;
+ static char *p = NULL;
+
+ if (p == NULL)
+ {
+ char hname[1024], *hnameptr;
+ unsigned int len;
+#if defined(IPv6) && defined(AF_INET6)
+ struct addrinfo hints, *ai = NULL;
+#else
+ struct hostent *host;
+#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
+ _Xgethostbynameparams hparams;
+#endif
+#endif
+
+ gethostname(hname, 1024);
+#if defined(IPv6) && defined(AF_INET6)
+ bzero(&hints, sizeof(hints));
+ hints.ai_flags = AI_CANONNAME;
+ if (getaddrinfo(hname, NULL, &hints, &ai) == 0) {
+ hnameptr = ai->ai_canonname;
+ } else {
+ hnameptr = hname;
+ }
+#else
+ host = _XGethostbyname(hname, hparams);
+ if (host == NULL)
+ hnameptr = hname;
+ else
+ hnameptr = host->h_name;
+#endif
+
+ len = strlen(hnameptr) + 1;
+ result = malloc(len + sizeof(AUTHORIZATION_NAME) + 4);
+
+ p = result;
+ *p++ = sizeof(AUTHORIZATION_NAME) >> 8;
+ *p++ = sizeof(AUTHORIZATION_NAME) & 0xff;
+ *p++ = (len) >> 8;
+ *p++ = (len & 0xff);
+
+ memmove(p, AUTHORIZATION_NAME, sizeof(AUTHORIZATION_NAME));
+ p += sizeof(AUTHORIZATION_NAME);
+ memmove(p, hnameptr, len);
+ p += len;
+#if defined(IPv6) && defined(AF_INET6)
+ if (ai) {
+ freeaddrinfo(ai);
+ }
+#endif
+ }
+ *authlen = p - result;
+ *authorizations = result;
+ return 1;
+#else /* TCPCONN */
+ return 0;
+#endif /* TCPCONN */
+}
+
+/*****************
+ * XNFalloc
+ * "no failure" alloc
+ *****************/
+
+void *
+XNFalloc(unsigned long amount)
+{
+ void *ptr = malloc(amount);
+ if (!ptr)
+ {
+ FatalError("Out of memory");
+ }
+ return ptr;
+}
+
+/*****************
+ * XNFcalloc
+ *****************/
+
+void *
+XNFcalloc(unsigned long amount)
+{
+ void *ret = calloc(1, amount);
+ if (!ret)
+ FatalError("XNFcalloc: Out of memory");
+ return ret;
+}
+
+/*****************
+ * XNFrealloc
+ * "no failure" realloc
+ *****************/
+
+void *
+XNFrealloc(void * ptr, unsigned long amount)
+{
+ void *ret = realloc(ptr, amount);
+ if (!ret)
+ FatalError("XNFrealloc: Out of memory");
+ return ret;
+}
+
+void
+OsInitAllocator (void)
+{
+#ifdef MEMBUG
+ static int been_here;
+
+ /* Check the memory system after each generation */
+ if (been_here)
+ CheckMemory ();
+ else
+ been_here = 1;
+#endif
+}
+
+char *
+Xstrdup(const char *s)
+{
+ if (s == NULL)
+ return NULL;
+ return strdup(s);
+}
+
+
+char *
+XNFstrdup(const char *s)
+{
+ char *ret;
+
+ if (s == NULL)
+ return NULL;
+
+ ret = strdup(s);
+ if (!ret)
+ FatalError("XNFstrdup: Out of memory");
+ return ret;
+}
+
+void
+SmartScheduleStopTimer (void)
+{
+#if HAVE_SETITIMER
+ struct itimerval timer;
+
+ if (!SmartScheduleSignalEnable)
+ return;
+
+ #ifdef NX_TRANS_TEST
+ fprintf(stderr, "SmartScheduleStopTimer: Stopping timer.\n");
+ #endif
+
+ timer.it_interval.tv_sec = 0;
+ timer.it_interval.tv_usec = 0;
+ timer.it_value.tv_sec = 0;
+ timer.it_value.tv_usec = 0;
+ (void) setitimer (ITIMER_REAL, &timer, 0);
+#endif
+}
+
+void
+SmartScheduleStartTimer (void)
+{
+#if HAVE_SETITIMER
+ struct itimerval timer;
+
+ if (!SmartScheduleSignalEnable)
+ return;
+
+ #ifdef NX_TRANS_TEST
+ fprintf(stderr, "SmartScheduleStartTimer: Starting timer with [%ld] ms.\n",
+ SmartScheduleInterval);
+ #endif
+
+ timer.it_interval.tv_sec = 0;
+ timer.it_interval.tv_usec = SmartScheduleInterval * 1000;
+ timer.it_value.tv_sec = 0;
+ timer.it_value.tv_usec = SmartScheduleInterval * 1000;
+ setitimer (ITIMER_REAL, &timer, 0);
+#endif
+}
+
+#if HAVE_SETITIMER
+static void
+SmartScheduleTimer (int sig)
+{
+ SmartScheduleTime += SmartScheduleInterval;
+
+ #ifdef NX_TRANS_TEST
+ fprintf(stderr, "SmartScheduleTimer: Got timer with time [%ld] ms.\n",
+ SmartScheduleTime);
+ #endif
+}
+
+int
+SmartScheduleEnable (void)
+{
+ int ret = 0;
+ struct sigaction act;
+
+ if (!SmartScheduleSignalEnable)
+ return 0;
+
+ #ifdef NX_TRANS_TEST
+ fprintf(stderr, "SmartScheduleEnable: Enabling the smart scheduler.\n");
+ #endif
+
+ memset((char *) &act, 0, sizeof(struct sigaction));
+
+ /* Set up the timer signal function */
+ act.sa_flags = SA_RESTART;
+ act.sa_handler = SmartScheduleTimer;
+ sigemptyset (&act.sa_mask);
+ sigaddset (&act.sa_mask, SIGALRM);
+ ret = sigaction(SIGALRM, &act, 0);
+ return ret;
+}
+
+static int
+SmartSchedulePause(void)
+{
+ int ret = 0;
+ struct sigaction act;
+
+ if (!SmartScheduleSignalEnable)
+ return 0;
+
+ #ifdef NX_TRANS_TEST
+ fprintf(stderr, "SmartSchedulePause: Pausing the smart scheduler.\n");
+ #endif
+
+ memset((char *) &act, 0, sizeof(struct sigaction));
+
+ act.sa_handler = SIG_IGN;
+ sigemptyset(&act.sa_mask);
+ ret = sigaction(SIGALRM, &act, 0);
+ return ret;
+}
+#endif
+
+void
+SmartScheduleInit(void)
+{
+#if HAVE_SETITIMER
+ #ifdef NX_TRANS_TEST
+ fprintf(stderr, "SmartScheduleInit: Initializing the smart scheduler.\n");
+ #endif
+
+ if (SmartScheduleEnable() < 0) {
+ perror("sigaction for smart scheduler");
+ SmartScheduleSignalEnable = FALSE;
+ }
+#endif
+}
+
+#ifdef SIG_BLOCK
+static sigset_t PreviousSignalMask;
+static int BlockedSignalCount;
+#endif
+
+void
+OsBlockSignals (void)
+{
+#ifdef SIG_BLOCK
+ if (BlockedSignalCount++ == 0)
+ {
+ sigset_t set;
+
+ sigemptyset (&set);
+#ifdef SIGALRM
+ sigaddset (&set, SIGALRM);
+#endif
+#ifdef SIGVTALRM
+ sigaddset (&set, SIGVTALRM);
+#endif
+#ifdef SIGWINCH
+ sigaddset (&set, SIGWINCH);
+#endif
+#ifdef SIGIO
+ sigaddset (&set, SIGIO);
+#endif
+#ifdef SIGTSTP
+ sigaddset (&set, SIGTSTP);
+#endif
+#ifdef SIGTTIN
+ sigaddset (&set, SIGTTIN);
+#endif
+#ifdef SIGTTOU
+ sigaddset (&set, SIGTTOU);
+#endif
+#ifdef SIGCHLD
+ sigaddset (&set, SIGCHLD);
+#endif
+ sigprocmask (SIG_BLOCK, &set, &PreviousSignalMask);
+ }
+#endif
+}
+
+void
+OsReleaseSignals (void)
+{
+#ifdef SIG_BLOCK
+ if (--BlockedSignalCount == 0)
+ {
+ sigprocmask (SIG_SETMASK, &PreviousSignalMask, 0);
+ }
+#endif
+}
+
+#if !defined(WIN32)
+/*
+ * "safer" versions of system(3), popen(3) and pclose(3) which give up
+ * all privs before running a command.
+ *
+ * This is based on the code in FreeBSD 2.2 libc.
+ *
+ * XXX It'd be good to redirect stderr so that it ends up in the log file
+ * as well. As it is now, xkbcomp messages don't end up in the log file.
+ */
+
+int
+System(char *command)
+{
+ int pid, p;
+#ifdef SIGCHLD
+ void (*csig)(int);
+#endif
+ int status;
+ struct passwd *pwent;
+
+ if (!command)
+ return(1);
+
+#ifdef SIGCHLD
+ csig = OsSignal(SIGCHLD, SIG_DFL);
+ if (csig == SIG_ERR) {
+ perror("signal");
+ return -1;
+ }
+#endif
+
+#ifdef DEBUG
+ ErrorF("System: `%s'\n", command);
+#endif
+
+#ifdef NX_TRANS_EXIT
+ if (OsVendorStartRedirectErrorFProc != NULL) {
+ OsVendorStartRedirectErrorFProc();
+ }
+#endif
+ switch (pid = fork()) {
+ case -1: /* error */
+ p = -1;
+ case 0: /* child */
+ pwent = getpwuid(getuid());
+ if (initgroups(pwent->pw_name,getgid()) == -1)
+ _exit(127);
+ if (setgid(getgid()) == -1)
+ _exit(127);
+ if (setuid(getuid()) == -1)
+ _exit(127);
+ execl("/bin/sh", "sh", "-c", command, (char *)NULL);
+ _exit(127);
+ default: /* parent */
+ do {
+ p = waitpid(pid, &status, 0);
+ } while (p == -1 && errno == EINTR);
+
+ }
+#ifdef NX_TRANS_EXIT
+ if (OsVendorEndRedirectErrorFProc != NULL) {
+ OsVendorEndRedirectErrorFProc();
+ }
+#endif
+
+#ifdef SIGCHLD
+ if (OsSignal(SIGCHLD, csig) == SIG_ERR) {
+ perror("signal");
+ return -1;
+ }
+#endif
+
+ return p == -1 ? -1 : status;
+}
+
+static struct pid {
+ struct pid *next;
+ FILE *fp;
+ int pid;
+} *pidlist;
+
+void *
+Popen(char *command, char *type)
+{
+ struct pid *cur;
+ FILE *iop;
+ int pdes[2], pid;
+
+ if (command == NULL || type == NULL)
+ return NULL;
+
+ if ((*type != 'r' && *type != 'w') || type[1])
+ return NULL;
+
+ if ((cur = (struct pid *)malloc(sizeof(struct pid))) == NULL)
+ return NULL;
+
+ if (pipe(pdes) < 0) {
+ free(cur);
+ return NULL;
+ }
+
+ /* Ignore the smart scheduler while this is going on */
+#if HAVE_SETITIMER
+ if (SmartSchedulePause() < 0) {
+ close(pdes[0]);
+ close(pdes[1]);
+ free(cur);
+ perror("signal");
+ return NULL;
+ }
+#endif
+
+#ifdef NX_TRANS_EXIT
+ if (OsVendorStartRedirectErrorFProc != NULL) {
+ OsVendorStartRedirectErrorFProc();
+ }
+ OsBlockSignals ();
+#endif
+ switch (pid = fork()) {
+ case -1: /* error */
+ close(pdes[0]);
+ close(pdes[1]);
+ free(cur);
+#if HAVE_SETITIMER
+ if (SmartScheduleEnable() < 0)
+ perror("signal");
+#endif
+#ifdef NX_TRANS_EXIT
+ if (OsVendorEndRedirectErrorFProc != NULL) {
+ OsVendorEndRedirectErrorFProc();
+ }
+ OsReleaseSignals ();
+#endif
+ return NULL;
+ case 0: /* child */
+ if (setgid(getgid()) == -1)
+ _exit(127);
+ if (setuid(getuid()) == -1)
+ _exit(127);
+ if (*type == 'r') {
+ if (pdes[1] != 1) {
+ /* stdout */
+ dup2(pdes[1], 1);
+ close(pdes[1]);
+ }
+ close(pdes[0]);
+ } else {
+ if (pdes[0] != 0) {
+ /* stdin */
+ dup2(pdes[0], 0);
+ close(pdes[0]);
+ }
+ close(pdes[1]);
+ }
+
+ #ifdef NX_TRANS_SOCKET
+
+ /*
+ * Check if the child process should not
+ * use the parent's libraries.
+ */
+
+ if (_NXUnsetLibraryPath)
+ {
+ #ifndef __sun
+
+ unsetenv ("LD_LIBRARY_PATH");
+
+ #else
+
+ extern char **environ;
+
+ char **ep = environ;
+
+ ep = environ;
+
+ while (*ep)
+ {
+ if (!strncmp("LD_LIBRARY_PATH=", *ep, strlen("LD_LIBRARY_PATH=")))
+ {
+ break;
+ }
+
+ *ep++;
+ }
+
+ while (*ep)
+ {
+ *ep = *(ep + 1);
+ ep++;
+ }
+
+ #endif
+ }
+
+ #endif
+
+ #ifdef NX_TRANS_EXIT
+ OsReleaseSignals ();
+ #endif
+
+#if HAVE_SETITIMER
+ if (SmartScheduleEnable() < 0) {
+ perror("signal");
+ return NULL;
+ }
+#endif
+
+ execl("/bin/sh", "sh", "-c", command, (char *)NULL);
+ _exit(127);
+ }
+
+#ifndef NX_TRANS_EXIT
+ /* Avoid EINTR during stdio calls */
+ OsBlockSignals ();
+#endif
+
+ /* parent */
+ if (*type == 'r') {
+ iop = fdopen(pdes[0], type);
+ close(pdes[1]);
+ } else {
+ iop = fdopen(pdes[1], type);
+ close(pdes[0]);
+ }
+
+ cur->fp = iop;
+ cur->pid = pid;
+ cur->next = pidlist;
+ pidlist = cur;
+
+#ifdef DEBUG
+ ErrorF("Popen: `%s', fp = %p\n", command, iop);
+#endif
+
+ return iop;
+}
+
+/* fopen that drops privileges */
+void *
+Fopen(char *file, char *type)
+{
+ FILE *iop;
+#ifndef HAS_SAVED_IDS_AND_SETEUID
+ struct pid *cur;
+ int pdes[2], pid;
+
+ if (file == NULL || type == NULL)
+ return NULL;
+
+ if ((*type != 'r' && *type != 'w') || type[1])
+ return NULL;
+
+ if ((cur = (struct pid *)malloc(sizeof(struct pid))) == NULL)
+ return NULL;
+
+ if (pipe(pdes) < 0) {
+ free(cur);
+ return NULL;
+ }
+
+ switch (pid = fork()) {
+ case -1: /* error */
+ close(pdes[0]);
+ close(pdes[1]);
+ free(cur);
+ return NULL;
+ case 0: /* child */
+ if (setgid(getgid()) == -1)
+ _exit(127);
+ if (setuid(getuid()) == -1)
+ _exit(127);
+ if (*type == 'r') {
+ if (pdes[1] != 1) {
+ /* stdout */
+ dup2(pdes[1], 1);
+ close(pdes[1]);
+ }
+ close(pdes[0]);
+ } else {
+ if (pdes[0] != 0) {
+ /* stdin */
+ dup2(pdes[0], 0);
+ close(pdes[0]);
+ }
+ close(pdes[1]);
+ }
+ execl("/bin/cat", "cat", file, (char *)NULL);
+ _exit(127);
+ }
+
+ /* Avoid EINTR during stdio calls */
+ OsBlockSignals ();
+
+ /* parent */
+ if (*type == 'r') {
+ iop = fdopen(pdes[0], type);
+ close(pdes[1]);
+ } else {
+ iop = fdopen(pdes[1], type);
+ close(pdes[0]);
+ }
+
+ cur->fp = iop;
+ cur->pid = pid;
+ cur->next = pidlist;
+ pidlist = cur;
+
+#ifdef DEBUG
+ ErrorF("Popen: `%s', fp = %p\n", command, iop);
+#endif
+
+ return iop;
+#else
+ int ruid, euid;
+
+ ruid = getuid();
+ euid = geteuid();
+
+ if (seteuid(ruid) == -1) {
+ return NULL;
+ }
+ iop = fopen(file, type);
+
+ if (seteuid(euid) == -1) {
+ fclose(iop);
+ return NULL;
+ }
+ return iop;
+#endif /* HAS_SAVED_IDS_AND_SETEUID */
+}
+
+int
+Pclose(void * iop)
+{
+ struct pid *cur, *last;
+ int pstat;
+ int pid;
+
+#ifdef DEBUG
+ ErrorF("Pclose: fp = %p\n", iop);
+#endif
+
+ fclose(iop);
+
+ for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next)
+ if (cur->fp == iop)
+ break;
+ if (cur == NULL)
+ return -1;
+
+ do {
+ pid = waitpid(cur->pid, &pstat, 0);
+ } while (pid == -1 && errno == EINTR);
+
+ if (last == NULL)
+ pidlist = cur->next;
+ else
+ last->next = cur->next;
+ free(cur);
+
+ /* allow EINTR again */
+ OsReleaseSignals ();
+
+#ifdef NX_TRANS_EXIT
+ if (OsVendorEndRedirectErrorFProc != NULL) {
+ OsVendorEndRedirectErrorFProc();
+ }
+#endif
+ return pid == -1 ? -1 : pstat;
+}
+
+int
+Fclose(void * iop)
+{
+#ifdef HAS_SAVED_IDS_AND_SETEUID
+ return fclose(iop);
+#else
+ return Pclose(iop);
+#endif
+}
+
+#endif /* !WIN32 */
+
+
+/*
+ * CheckUserParameters: check for long command line arguments and long
+ * environment variables. By default, these checks are only done when
+ * the server's euid != ruid. In 3.3.x, these checks were done in an
+ * external wrapper utility.
+ */
+
+/* Consider LD* variables insecure? */
+#ifndef REMOVE_ENV_LD
+#define REMOVE_ENV_LD 1
+#endif
+
+/* Remove long environment variables? */
+#ifndef REMOVE_LONG_ENV
+#define REMOVE_LONG_ENV 1
+#endif
+
+/*
+ * Disallow stdout or stderr as pipes? It's possible to block the X server
+ * when piping stdout+stderr to a pipe.
+ *
+ * Don't enable this because it looks like it's going to cause problems.
+ */
+#ifndef NO_OUTPUT_PIPES
+#define NO_OUTPUT_PIPES 0
+#endif
+
+
+/* Check args and env only if running setuid (euid == 0 && euid != uid) ? */
+#ifndef CHECK_EUID
+#ifndef WIN32
+#define CHECK_EUID 1
+#else
+#define CHECK_EUID 0
+#endif
+#endif
+
+/*
+ * Maybe the locale can be faked to make isprint(3) report that everything
+ * is printable? Avoid it by default.
+ */
+#ifndef USE_ISPRINT
+#define USE_ISPRINT 0
+#endif
+
+#define MAX_ARG_LENGTH 128
+#define MAX_ENV_LENGTH 256
+#define MAX_ENV_PATH_LENGTH 2048 /* Limit for *PATH and TERMCAP */
+
+#if USE_ISPRINT
+#include <ctype.h>
+#define checkPrintable(c) isprint(c)
+#else
+#define checkPrintable(c) (((c) & 0x7f) >= 0x20 && ((c) & 0x7f) != 0x7f)
+#endif
+
+enum BadCode {
+ NotBad = 0,
+ UnsafeArg,
+ ArgTooLong,
+ UnprintableArg,
+ EnvTooLong,
+ OutputIsPipe,
+ InternalError
+};
+
+#if defined(VENDORSUPPORT)
+#define BUGADDRESS VENDORSUPPORT
+#elif defined(BUILDERADDR)
+#define BUGADDRESS BUILDERADDR
+#else
+#define BUGADDRESS "xorg@freedesktop.org"
+#endif
+
+#define ARGMSG \
+ "\nIf the arguments used are valid, and have been rejected incorrectly\n" \
+ "please send details of the arguments and why they are valid to\n" \
+ "%s. In the meantime, you can start the Xserver as\n" \
+ "the \"super user\" (root).\n"
+
+#define ENVMSG \
+ "\nIf the environment is valid, and have been rejected incorrectly\n" \
+ "please send details of the environment and why it is valid to\n" \
+ "%s. In the meantime, you can start the Xserver as\n" \
+ "the \"super user\" (root).\n"
+
+void
+CheckUserParameters(int argc, char **argv, char **envp)
+{
+ enum BadCode bad = NotBad;
+ int i = 0, j;
+ char *a, *e = NULL;
+
+#if CHECK_EUID
+ if (geteuid() == 0 && getuid() != geteuid())
+#endif
+ {
+ /* Check each argv[] */
+ for (i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-fp") == 0)
+ {
+ i++; /* continue with next argument. skip the length check */
+ if (i >= argc)
+ break;
+ } else
+ {
+ if (strlen(argv[i]) > MAX_ARG_LENGTH) {
+ bad = ArgTooLong;
+ break;
+ }
+ }
+ a = argv[i];
+ while (*a) {
+ if (checkPrintable(*a) == 0) {
+ bad = UnprintableArg;
+ break;
+ }
+ a++;
+ }
+ if (bad)
+ break;
+ }
+ if (!bad) {
+ /* Check each envp[] */
+ for (i = 0; envp[i]; i++) {
+
+ /* Check for bad environment variables and values */
+#if REMOVE_ENV_LD
+ while (envp[i] && (strncmp(envp[i], "LD", 2) == 0)) {
+#ifdef ENVDEBUG
+ ErrorF("CheckUserParameters: removing %s from the "
+ "environment\n", strtok(envp[i], "="));
+#endif
+ for (j = i; envp[j]; j++) {
+ envp[j] = envp[j+1];
+ }
+ }
+#endif
+ if (envp[i] && (strlen(envp[i]) > MAX_ENV_LENGTH)) {
+#if REMOVE_LONG_ENV
+#ifdef ENVDEBUG
+ ErrorF("CheckUserParameters: removing %s from the "
+ "environment\n", strtok(envp[i], "="));
+#endif
+ for (j = i; envp[j]; j++) {
+ envp[j] = envp[j+1];
+ }
+ i--;
+#else
+ char *eq;
+ int len;
+
+ eq = strchr(envp[i], '=');
+ if (!eq)
+ continue;
+ len = eq - envp[i];
+ e = malloc(len + 1);
+ if (!e) {
+ bad = InternalError;
+ break;
+ }
+ strncpy(e, envp[i], len);
+ e[len] = 0;
+ if (len >= 4 &&
+ (strcmp(e + len - 4, "PATH") == 0 ||
+ strcmp(e, "TERMCAP") == 0)) {
+ if (strlen(envp[i]) > MAX_ENV_PATH_LENGTH) {
+ bad = EnvTooLong;
+ break;
+ } else {
+ free(e);
+ }
+ } else {
+ bad = EnvTooLong;
+ break;
+ }
+#endif
+ }
+ }
+ }
+#if NO_OUTPUT_PIPES
+ if (!bad) {
+ struct stat buf;
+
+ if (fstat(fileno(stdout), &buf) == 0 && S_ISFIFO(buf.st_mode))
+ bad = OutputIsPipe;
+ if (fstat(fileno(stderr), &buf) == 0 && S_ISFIFO(buf.st_mode))
+ bad = OutputIsPipe;
+ }
+#endif
+ }
+ switch (bad) {
+ case NotBad:
+ return;
+ case UnsafeArg:
+ ErrorF("Command line argument number %d is unsafe\n", i);
+ ErrorF(ARGMSG, BUGADDRESS);
+ break;
+ case ArgTooLong:
+ ErrorF("Command line argument number %d is too long\n", i);
+ ErrorF(ARGMSG, BUGADDRESS);
+ break;
+ case UnprintableArg:
+ ErrorF("Command line argument number %d contains unprintable"
+ " characters\n", i);
+ ErrorF(ARGMSG, BUGADDRESS);
+ break;
+ case EnvTooLong:
+ ErrorF("Environment variable `%s' is too long\n", e);
+ ErrorF(ENVMSG, BUGADDRESS);
+ break;
+ case OutputIsPipe:
+ ErrorF("Stdout and/or stderr is a pipe\n");
+ break;
+ case InternalError:
+ ErrorF("Internal Error\n");
+ break;
+ default:
+ ErrorF("Unknown error\n");
+ ErrorF(ARGMSG, BUGADDRESS);
+ ErrorF(ENVMSG, BUGADDRESS);
+ break;
+ }
+ FatalError("X server aborted because of unsafe environment\n");
+}
+
+/*
+ * CheckUserAuthorization: check if the user is allowed to start the
+ * X server. This usually means some sort of PAM checking, and it is
+ * usually only done for setuid servers (uid != euid).
+ */
+
+#ifdef USE_PAM
+#include <security/pam_appl.h>
+#include <security/pam_misc.h>
+#include <pwd.h>
+#endif /* USE_PAM */
+
+void
+CheckUserAuthorization(void)
+{
+#ifdef USE_PAM
+ static struct pam_conv conv = {
+ misc_conv,
+ NULL
+ };
+
+ pam_handle_t *pamh = NULL;
+ struct passwd *pw;
+ int retval;
+
+ if (getuid() != geteuid()) {
+ pw = getpwuid(getuid());
+ if (pw == NULL)
+ FatalError("getpwuid() failed for uid %d\n", getuid());
+
+ retval = pam_start("xserver", pw->pw_name, &conv, &pamh);
+ if (retval != PAM_SUCCESS)
+ FatalError("pam_start() failed.\n"
+ "\tMissing or mangled PAM config file or module?\n");
+
+ retval = pam_authenticate(pamh, 0);
+ if (retval != PAM_SUCCESS) {
+ pam_end(pamh, retval);
+ FatalError("PAM authentication failed, cannot start X server.\n"
+ "\tPerhaps you do not have console ownership?\n");
+ }
+
+ retval = pam_acct_mgmt(pamh, 0);
+ if (retval != PAM_SUCCESS) {
+ pam_end(pamh, retval);
+ FatalError("PAM authentication failed, cannot start X server.\n"
+ "\tPerhaps you do not have console ownership?\n");
+ }
+
+ /* this is not a session, so do not do session management */
+ pam_end(pamh, PAM_SUCCESS);
+ }
+#endif
+}
+
+#ifdef __SCO__
+#include <fcntl.h>
+
+static void
+lockit (int fd, short what)
+{
+ struct flock lck;
+
+ lck.l_whence = 0;
+ lck.l_start = 0;
+ lck.l_len = 1;
+ lck.l_type = what;
+
+ (void)fcntl (fd, F_SETLKW, &lck);
+}
+
+/* SCO OpenServer 5 lacks pread/pwrite. Emulate them. */
+ssize_t
+pread (int fd, void *buf, size_t nbytes, off_t offset)
+{
+ off_t saved;
+ ssize_t ret;
+
+ lockit (fd, F_RDLCK);
+ saved = lseek (fd, 0, SEEK_CUR);
+ lseek (fd, offset, SEEK_SET);
+ ret = read (fd, buf, nbytes);
+ lseek (fd, saved, SEEK_SET);
+ lockit (fd, F_UNLCK);
+
+ return ret;
+}
+
+ssize_t
+pwrite (int fd, const void *buf, size_t nbytes, off_t offset)
+{
+ off_t saved;
+ ssize_t ret;
+
+ lockit (fd, F_WRLCK);
+ saved = lseek (fd, 0, SEEK_CUR);
+ lseek (fd, offset, SEEK_SET);
+ ret = write (fd, buf, nbytes);
+ lseek (fd, saved, SEEK_SET);
+ lockit (fd, F_UNLCK);
+
+ return ret;
+}
+#endif /* __SCO__ */
diff --git a/nx-X11/programs/Xserver/os/xdmauth.c b/nx-X11/programs/Xserver/os/xdmauth.c
new file mode 100644
index 000000000..4a59b48f2
--- /dev/null
+++ b/nx-X11/programs/Xserver/os/xdmauth.c
@@ -0,0 +1,501 @@
+/*
+
+Copyright 1988, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+
+/*
+ * XDM-AUTHENTICATION-1 (XDMCP authentication) and
+ * XDM-AUTHORIZATION-1 (client authorization) protocols
+ *
+ * Author: Keith Packard, MIT X Consortium
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <stdio.h>
+#include <nx-X11/X.h>
+#define XSERV_t
+#define TRANS_SERVER
+#define TRANS_REOPEN
+#include <nx-X11/Xtrans/Xtrans.h>
+#include "os.h"
+#include "osdep.h"
+#include "dixstruct.h"
+
+#ifdef HASXDMAUTH
+
+static Bool authFromXDMCP;
+
+#ifdef XDMCP
+#include <nx-X11/Xmd.h>
+#undef REQUEST
+#include <X11/Xdmcp.h>
+
+/* XDM-AUTHENTICATION-1 */
+
+static XdmAuthKeyRec privateKey;
+static char XdmAuthenticationName[] = "XDM-AUTHENTICATION-1";
+#define XdmAuthenticationNameLen (sizeof XdmAuthenticationName - 1)
+static XdmAuthKeyRec rho;
+
+static Bool
+XdmAuthenticationValidator (ARRAY8Ptr privateData, ARRAY8Ptr incomingData,
+ xdmOpCode packet_type)
+{
+ XdmAuthKeyPtr incoming;
+
+ XdmcpUnwrap (incomingData->data, (unsigned char *)&privateKey,
+ incomingData->data,incomingData->length);
+ if (packet_type == ACCEPT) {
+ if (incomingData->length != 8)
+ return FALSE;
+ incoming = (XdmAuthKeyPtr) incomingData->data;
+ XdmcpDecrementKey (incoming);
+ return XdmcpCompareKeys (incoming, &rho);
+ }
+ return FALSE;
+}
+
+static Bool
+XdmAuthenticationGenerator (ARRAY8Ptr privateData, ARRAY8Ptr outgoingData,
+ xdmOpCode packet_type)
+{
+ outgoingData->length = 0;
+ outgoingData->data = 0;
+ if (packet_type == REQUEST) {
+ if (XdmcpAllocARRAY8 (outgoingData, 8))
+ XdmcpWrap ((unsigned char *)&rho, (unsigned char *)&privateKey,
+ outgoingData->data, 8);
+ }
+ return TRUE;
+}
+
+static Bool
+XdmAuthenticationAddAuth (int name_len, char *name,
+ int data_len, char *data)
+{
+ Bool ret;
+ XdmcpUnwrap ((unsigned char *)data, (unsigned char *)&privateKey,
+ (unsigned char *)data, data_len);
+ authFromXDMCP = TRUE;
+ ret = AddAuthorization (name_len, name, data_len, data);
+ authFromXDMCP = FALSE;
+ return ret;
+}
+
+
+#define atox(c) ('0' <= c && c <= '9' ? c - '0' : \
+ 'a' <= c && c <= 'f' ? c - 'a' + 10 : \
+ 'A' <= c && c <= 'F' ? c - 'A' + 10 : -1)
+
+static int
+HexToBinary (char *in, char *out, int len)
+{
+ int top, bottom;
+
+ while (len > 0)
+ {
+ top = atox(in[0]);
+ if (top == -1)
+ return 0;
+ bottom = atox(in[1]);
+ if (bottom == -1)
+ return 0;
+ *out++ = (top << 4) | bottom;
+ in += 2;
+ len -= 2;
+ }
+ if (len)
+ return 0;
+ *out++ = '\0';
+ return 1;
+}
+
+void
+XdmAuthenticationInit (char *cookie, int cookie_len)
+{
+ bzero (privateKey.data, 8);
+ if (!strncmp (cookie, "0x", 2) || !strncmp (cookie, "0X", 2))
+ {
+ if (cookie_len > 2 + 2 * 8)
+ cookie_len = 2 + 2 * 8;
+ HexToBinary (cookie + 2, (char *)privateKey.data, cookie_len - 2);
+ }
+ else
+ {
+ if (cookie_len > 7)
+ cookie_len = 7;
+ memmove (privateKey.data + 1, cookie, cookie_len);
+ }
+ XdmcpGenerateKey (&rho);
+ XdmcpRegisterAuthentication (XdmAuthenticationName, XdmAuthenticationNameLen,
+ (char *)&rho,
+ sizeof (rho),
+ (ValidatorFunc)XdmAuthenticationValidator,
+ (GeneratorFunc)XdmAuthenticationGenerator,
+ (AddAuthorFunc)XdmAuthenticationAddAuth);
+}
+
+#endif /* XDMCP */
+
+/* XDM-AUTHORIZATION-1 */
+typedef struct _XdmAuthorization {
+ struct _XdmAuthorization *next;
+ XdmAuthKeyRec rho;
+ XdmAuthKeyRec key;
+ XID id;
+} XdmAuthorizationRec, *XdmAuthorizationPtr;
+
+static XdmAuthorizationPtr xdmAuth;
+
+typedef struct _XdmClientAuth {
+ struct _XdmClientAuth *next;
+ XdmAuthKeyRec rho;
+ char client[6];
+ long time;
+} XdmClientAuthRec, *XdmClientAuthPtr;
+
+static XdmClientAuthPtr xdmClients;
+static long clockOffset;
+static Bool gotClock;
+
+#define TwentyMinutes (20 * 60)
+#define TwentyFiveMinutes (25 * 60)
+
+static Bool
+XdmClientAuthCompare (XdmClientAuthPtr a, XdmClientAuthPtr b)
+{
+ int i;
+
+ if (!XdmcpCompareKeys (&a->rho, &b->rho))
+ return FALSE;
+ for (i = 0; i < 6; i++)
+ if (a->client[i] != b->client[i])
+ return FALSE;
+ return a->time == b->time;
+}
+
+static void
+XdmClientAuthDecode (unsigned char *plain, XdmClientAuthPtr auth)
+{
+ int i, j;
+
+ j = 0;
+ for (i = 0; i < 8; i++)
+ {
+ auth->rho.data[i] = plain[j];
+ ++j;
+ }
+ for (i = 0; i < 6; i++)
+ {
+ auth->client[i] = plain[j];
+ ++j;
+ }
+ auth->time = 0;
+ for (i = 0; i < 4; i++)
+ {
+ auth->time |= plain[j] << ((3 - i) << 3);
+ j++;
+ }
+}
+
+static void
+XdmClientAuthTimeout (long now)
+{
+ XdmClientAuthPtr client, next, prev;
+
+ prev = 0;
+ for (client = xdmClients; client; client=next)
+ {
+ next = client->next;
+ if (abs (now - client->time) > TwentyFiveMinutes)
+ {
+ if (prev)
+ prev->next = next;
+ else
+ xdmClients = next;
+ free (client);
+ }
+ else
+ prev = client;
+ }
+}
+
+static XdmClientAuthPtr
+XdmAuthorizationValidate (unsigned char *plain, int length,
+ XdmAuthKeyPtr rho, ClientPtr xclient, char **reason)
+{
+ XdmClientAuthPtr client, existing;
+ long now;
+ int i;
+
+ if (length != (192 / 8)) {
+ if (reason)
+ *reason = "Bad XDM authorization key length";
+ return NULL;
+ }
+ client = (XdmClientAuthPtr) malloc (sizeof (XdmClientAuthRec));
+ if (!client)
+ return NULL;
+ XdmClientAuthDecode (plain, client);
+ if (!XdmcpCompareKeys (&client->rho, rho))
+ {
+ free (client);
+ if (reason)
+ *reason = "Invalid XDM-AUTHORIZATION-1 key (failed key comparison)";
+ return NULL;
+ }
+ for (i = 18; i < 24; i++)
+ if (plain[i] != 0) {
+ free (client);
+ if (reason)
+ *reason = "Invalid XDM-AUTHORIZATION-1 key (failed NULL check)";
+ return NULL;
+ }
+ if (xclient) {
+ int family, addr_len;
+ Xtransaddr *addr;
+
+ if (_XSERVTransGetPeerAddr(((OsCommPtr)xclient->osPrivate)->trans_conn,
+ &family, &addr_len, &addr) == 0
+ && _XSERVTransConvertAddress(&family, &addr_len, &addr) == 0) {
+#if defined(TCPCONN)
+ if (family == FamilyInternet &&
+ memcmp((char *)addr, client->client, 4) != 0) {
+ free (client);
+ free (addr);
+ if (reason)
+ *reason = "Invalid XDM-AUTHORIZATION-1 key (failed address comparison)";
+ return NULL;
+
+ }
+#endif
+ free (addr);
+ }
+ }
+ now = time(0);
+ if (!gotClock)
+ {
+ clockOffset = client->time - now;
+ gotClock = TRUE;
+ }
+ now += clockOffset;
+ XdmClientAuthTimeout (now);
+ if (abs (client->time - now) > TwentyMinutes)
+ {
+ free (client);
+ if (reason)
+ *reason = "Excessive XDM-AUTHORIZATION-1 time offset";
+ return NULL;
+ }
+ for (existing = xdmClients; existing; existing=existing->next)
+ {
+ if (XdmClientAuthCompare (existing, client))
+ {
+ free (client);
+ if (reason)
+ *reason = "XDM authorization key matches an existing client!";
+ return NULL;
+ }
+ }
+ return client;
+}
+
+int
+XdmAddCookie (unsigned short data_length, char *data, XID id)
+{
+ XdmAuthorizationPtr new;
+ unsigned char *rho_bits, *key_bits;
+
+ switch (data_length)
+ {
+ case 16: /* auth from files is 16 bytes long */
+#ifdef XDMCP
+ if (authFromXDMCP)
+ {
+ /* R5 xdm sent bogus authorization data in the accept packet,
+ * but we can recover */
+ rho_bits = rho.data;
+ key_bits = (unsigned char *) data;
+ key_bits[0] = '\0';
+ }
+ else
+#endif
+ {
+ rho_bits = (unsigned char *) data;
+ key_bits = (unsigned char *) (data + 8);
+ }
+ break;
+#ifdef XDMCP
+ case 8: /* auth from XDMCP is 8 bytes long */
+ rho_bits = rho.data;
+ key_bits = (unsigned char *) data;
+ break;
+#endif
+ default:
+ return 0;
+ }
+ /* the first octet of the key must be zero */
+ if (key_bits[0] != '\0')
+ return 0;
+ new = (XdmAuthorizationPtr) malloc (sizeof (XdmAuthorizationRec));
+ if (!new)
+ return 0;
+ new->next = xdmAuth;
+ xdmAuth = new;
+ memmove (new->key.data, key_bits, (int) 8);
+ memmove (new->rho.data, rho_bits, (int) 8);
+ new->id = id;
+ return 1;
+}
+
+XID
+XdmCheckCookie (unsigned short cookie_length, char *cookie,
+ ClientPtr xclient, char **reason)
+{
+ XdmAuthorizationPtr auth;
+ XdmClientAuthPtr client;
+ unsigned char *plain;
+
+ /* Auth packets must be a multiple of 8 bytes long */
+ if (cookie_length & 7)
+ return (XID) -1;
+ plain = (unsigned char *) malloc (cookie_length);
+ if (!plain)
+ return (XID) -1;
+ for (auth = xdmAuth; auth; auth=auth->next) {
+ XdmcpUnwrap ((unsigned char *)cookie, (unsigned char *)&auth->key, plain, cookie_length);
+ if ((client = XdmAuthorizationValidate (plain, cookie_length, &auth->rho, xclient, reason)) != NULL)
+ {
+ client->next = xdmClients;
+ xdmClients = client;
+ free (plain);
+ return auth->id;
+ }
+ }
+ free (plain);
+ return (XID) -1;
+}
+
+int
+XdmResetCookie (void)
+{
+ XdmAuthorizationPtr auth, next_auth;
+ XdmClientAuthPtr client, next_client;
+
+ for (auth = xdmAuth; auth; auth=next_auth)
+ {
+ next_auth = auth->next;
+ free (auth);
+ }
+ xdmAuth = 0;
+ for (client = xdmClients; client; client=next_client)
+ {
+ next_client = client->next;
+ free (client);
+ }
+ xdmClients = (XdmClientAuthPtr) 0;
+ return 1;
+}
+
+XID
+XdmToID (unsigned short cookie_length, char *cookie)
+{
+ XdmAuthorizationPtr auth;
+ XdmClientAuthPtr client;
+ unsigned char *plain;
+
+ plain = (unsigned char *) malloc (cookie_length);
+ if (!plain)
+ return (XID) -1;
+ for (auth = xdmAuth; auth; auth=auth->next) {
+ XdmcpUnwrap ((unsigned char *)cookie, (unsigned char *)&auth->key, plain, cookie_length);
+ if ((client = XdmAuthorizationValidate (plain, cookie_length, &auth->rho, NULL, NULL)) != NULL)
+ {
+ free (client);
+ free (cookie);
+ return auth->id;
+ }
+ }
+ free (cookie);
+ return (XID) -1;
+}
+
+int
+XdmFromID (XID id, unsigned short *data_lenp, char **datap)
+{
+ XdmAuthorizationPtr auth;
+
+ for (auth = xdmAuth; auth; auth=auth->next) {
+ if (id == auth->id) {
+ *data_lenp = 16;
+ *datap = (char *) &auth->rho;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int
+XdmRemoveCookie (unsigned short data_length, char *data)
+{
+ XdmAuthorizationPtr auth, prev;
+ XdmAuthKeyPtr key_bits, rho_bits;
+
+ prev = 0;
+ switch (data_length)
+ {
+ case 16:
+ rho_bits = (XdmAuthKeyPtr) data;
+ key_bits = (XdmAuthKeyPtr) (data + 8);
+ break;
+#ifdef XDMCP
+ case 8:
+ rho_bits = &rho;
+ key_bits = (XdmAuthKeyPtr) data;
+ break;
+#endif
+ default:
+ return 0;
+ }
+ for (auth = xdmAuth; auth; auth=auth->next) {
+ if (XdmcpCompareKeys (rho_bits, &auth->rho) &&
+ XdmcpCompareKeys (key_bits, &auth->key))
+ {
+ if (prev)
+ prev->next = auth->next;
+ else
+ xdmAuth = auth->next;
+ free (auth);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+#endif
diff --git a/nx-X11/programs/Xserver/os/xdmcp.c b/nx-X11/programs/Xserver/os/xdmcp.c
new file mode 100644
index 000000000..c1aa57e95
--- /dev/null
+++ b/nx-X11/programs/Xserver/os/xdmcp.c
@@ -0,0 +1,1629 @@
+/*
+ * Copyright 1989 Network Computing Devices, Inc., Mountain View, California.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of N.C.D. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. N.C.D. makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifdef WIN32
+#include <nx-X11/Xwinsock.h>
+#define XSERV_t
+#define TRANS_SERVER
+#define TRANS_REOPEN
+#include <nx-X11/Xtrans/Xtrans.h>
+#endif
+
+#include <nx-X11/Xos.h>
+
+#if !defined(WIN32)
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <nx-X11/X.h>
+#include <nx-X11/Xmd.h>
+#include "misc.h"
+#include <nx-X11/Xpoll.h>
+#include "osdep.h"
+#include "input.h"
+#include "dixstruct.h"
+#include "opaque.h"
+
+
+#ifndef NX_TRANS_SOCKET
+
+#define NX_TRANS_SOCKET
+#define NX_TRANS_TEST
+
+#endif
+
+#ifdef XDMCP
+#undef REQUEST
+
+#ifdef XDMCP_NO_IPV6
+#undef IPv6
+#endif
+
+#include <X11/Xdmcp.h>
+
+#define X_INCLUDE_NETDB_H
+#include <nx-X11/Xos_r.h>
+
+#ifdef NX_TRANS_SOCKET
+
+xdmcp_states XdmcpState;
+
+int XdmcpStartTime;
+int XdmcpTimeOutRtx;
+
+#endif
+
+extern char *defaultDisplayClass;
+
+static int xdmcpSocket, sessionSocket;
+static xdmcp_states state;
+#if defined(IPv6) && defined(AF_INET6)
+static int xdmcpSocket6;
+static struct sockaddr_storage req_sockaddr;
+#else
+static struct sockaddr_in req_sockaddr;
+#endif
+static int req_socklen;
+static CARD32 SessionID;
+static CARD32 timeOutTime;
+static int timeOutRtx;
+static CARD16 DisplayNumber;
+static xdmcp_states XDM_INIT_STATE = XDM_OFF;
+#ifdef HASXDMAUTH
+static char *xdmAuthCookie;
+#endif
+
+static XdmcpBuffer buffer;
+
+#if defined(IPv6) && defined(AF_INET6)
+
+static struct addrinfo *mgrAddr;
+static struct addrinfo *mgrAddrFirst;
+
+#define SOCKADDR_TYPE struct sockaddr_storage
+#define SOCKADDR_FAMILY(s) ((struct sockaddr *)&(s))->sa_family
+
+#ifdef BSD44SOCKETS
+#define SOCKLEN_FIELD(s) ((struct sockaddr *)&(s))->sa_len
+#define SOCKLEN_TYPE unsigned char
+#else
+#define SOCKLEN_TYPE unsigned int
+#endif
+
+#else
+
+#define SOCKADDR_TYPE struct sockaddr_in
+#define SOCKADDR_FAMILY(s) (s).sin_family
+
+#ifdef BSD44SOCKETS
+#define SOCKLEN_FIELD(s) (s).sin_len
+#define SOCKLEN_TYPE unsigned char
+#else
+#define SOCKLEN_TYPE size_t
+#endif
+
+#endif
+
+static SOCKADDR_TYPE ManagerAddress;
+static SOCKADDR_TYPE FromAddress;
+
+#ifdef SOCKLEN_FIELD
+#define ManagerAddressLen SOCKLEN_FIELD(ManagerAddress)
+#define FromAddressLen SOCKLEN_FIELD(FromAddress)
+#else
+static SOCKLEN_TYPE ManagerAddressLen, FromAddressLen;
+#endif
+
+#if defined(IPv6) && defined(AF_INET6)
+static struct multicastinfo {
+ struct multicastinfo *next;
+ struct addrinfo *ai;
+ int hops;
+} *mcastlist;
+#endif
+
+static void XdmcpAddHost(
+ struct sockaddr *from,
+ int fromlen,
+ ARRAY8Ptr AuthenticationName,
+ ARRAY8Ptr hostname,
+ ARRAY8Ptr status);
+
+static void XdmcpSelectHost(
+ struct sockaddr *host_sockaddr,
+ int host_len,
+ ARRAY8Ptr AuthenticationName);
+
+static void get_xdmcp_sock(void);
+
+static void send_query_msg(void);
+
+static void recv_willing_msg(
+ struct sockaddr * /*from*/,
+ int /*fromlen*/,
+ unsigned /*length*/);
+
+static void send_request_msg(void);
+
+static void recv_accept_msg(unsigned /*length*/);
+
+static void recv_decline_msg(unsigned /*length*/);
+
+static void send_manage_msg(void);
+
+static void recv_refuse_msg(unsigned /*length*/);
+
+static void recv_failed_msg(unsigned /*length*/);
+
+static void send_keepalive_msg(void);
+
+static void recv_alive_msg(unsigned /*length*/);
+
+static void XdmcpFatal(
+ char * /*type*/,
+ ARRAY8Ptr /*status*/);
+
+static void XdmcpWarning(char * /*str*/);
+
+static void get_manager_by_name(
+ int /*argc*/,
+ char ** /*argv*/,
+ int /*i*/);
+
+static void get_fromaddr_by_name(int /*argc*/, char ** /*argv*/, int /*i*/);
+
+#if defined(IPv6) && defined(AF_INET6)
+static int get_mcast_options(int /*argc*/, char ** /*argv*/, int /*i*/);
+#endif
+
+static void receive_packet(int /*socketfd*/);
+
+static void send_packet(void);
+
+extern void XdmcpDeadSession(char * /*reason*/);
+
+static void timeout(void);
+
+static void XdmcpBlockHandler(
+ void * /*data*/,
+ struct timeval ** /*wt*/,
+ void * /*LastSelectMask*/);
+
+static void XdmcpWakeupHandler(
+ void * /*data*/,
+ int /*i*/,
+ void * /*LastSelectMask*/);
+
+void XdmcpRegisterManufacturerDisplayID(
+ char * /*name*/,
+ int /*length*/);
+
+
+static unsigned short xdm_udp_port = XDM_UDP_PORT;
+static Bool OneSession = FALSE;
+static const char *xdm_from = NULL;
+
+void
+XdmcpUseMsg (void)
+{
+ ErrorF("-query host-name contact named host for XDMCP\n");
+ ErrorF("-broadcast broadcast for XDMCP\n");
+#if defined(IPv6) && defined(AF_INET6)
+ ErrorF("-multicast [addr [hops]] IPv6 multicast for XDMCP\n");
+#endif
+ ErrorF("-indirect host-name contact named host for indirect XDMCP\n");
+ ErrorF("-port port-num UDP port number to send messages to\n");
+ ErrorF("-from local-address specify the local address to connect from\n");
+ ErrorF("-once Terminate server after one session\n");
+ ErrorF("-class display-class specify display class to send in manage\n");
+#ifdef HASXDMAUTH
+ ErrorF("-cookie xdm-auth-bits specify the magic cookie for XDMCP\n");
+#endif
+ ErrorF("-displayID display-id manufacturer display ID for request\n");
+}
+
+int
+XdmcpOptions(int argc, char **argv, int i)
+{
+ if (strcmp(argv[i], "-query") == 0) {
+ get_manager_by_name(argc, argv, i++);
+ XDM_INIT_STATE = XDM_QUERY;
+ AccessUsingXdmcp ();
+ return (i + 1);
+ }
+ if (strcmp(argv[i], "-broadcast") == 0) {
+ XDM_INIT_STATE = XDM_BROADCAST;
+ AccessUsingXdmcp ();
+ return (i + 1);
+ }
+#if defined(IPv6) && defined(AF_INET6)
+ if (strcmp(argv[i], "-multicast") == 0) {
+ i = get_mcast_options(argc, argv, ++i);
+ XDM_INIT_STATE = XDM_MULTICAST;
+ AccessUsingXdmcp ();
+ return (i + 1);
+ }
+#endif
+ if (strcmp(argv[i], "-indirect") == 0) {
+ get_manager_by_name(argc, argv, i++);
+ XDM_INIT_STATE = XDM_INDIRECT;
+ AccessUsingXdmcp ();
+ return (i + 1);
+ }
+ if (strcmp(argv[i], "-port") == 0) {
+ if (++i == argc) {
+ FatalError("Xserver: missing port number in command line\n");
+ }
+ xdm_udp_port = (unsigned short) atoi(argv[i]);
+ return (i + 1);
+ }
+ if (strcmp(argv[i], "-from") == 0) {
+ get_fromaddr_by_name(argc, argv, ++i);
+ return (i + 1);
+ }
+ if (strcmp(argv[i], "-once") == 0) {
+ OneSession = TRUE;
+ return (i + 1);
+ }
+ if (strcmp(argv[i], "-class") == 0) {
+ if (++i == argc) {
+ FatalError("Xserver: missing class name in command line\n");
+ }
+ defaultDisplayClass = argv[i];
+ return (i + 1);
+ }
+#ifdef HASXDMAUTH
+ if (strcmp(argv[i], "-cookie") == 0) {
+ if (++i == argc) {
+ FatalError("Xserver: missing cookie data in command line\n");
+ }
+ xdmAuthCookie = argv[i];
+ return (i + 1);
+ }
+#endif
+ if (strcmp(argv[i], "-displayID") == 0) {
+ if (++i == argc) {
+ FatalError("Xserver: missing displayID in command line\n");
+ }
+ XdmcpRegisterManufacturerDisplayID (argv[i], strlen (argv[i]));
+ return (i + 1);
+ }
+ return (i);
+}
+
+/*
+ * This section is a collection of routines for
+ * registering server-specific data with the XDMCP
+ * state machine.
+ */
+
+
+/*
+ * Save all broadcast addresses away so BroadcastQuery
+ * packets get sent everywhere
+ */
+
+#define MAX_BROADCAST 10
+
+/* This stays sockaddr_in since IPv6 doesn't support broadcast */
+static struct sockaddr_in BroadcastAddresses[MAX_BROADCAST];
+static int NumBroadcastAddresses;
+
+void
+XdmcpRegisterBroadcastAddress (struct sockaddr_in *addr)
+{
+ struct sockaddr_in *bcast;
+ if (NumBroadcastAddresses >= MAX_BROADCAST)
+ return;
+ bcast = &BroadcastAddresses[NumBroadcastAddresses++];
+ bzero (bcast, sizeof (struct sockaddr_in));
+#ifdef BSD44SOCKETS
+ bcast->sin_len = addr->sin_len;
+#endif
+ bcast->sin_family = addr->sin_family;
+ bcast->sin_port = htons (xdm_udp_port);
+ bcast->sin_addr = addr->sin_addr;
+}
+
+/*
+ * Each authentication type is registered here; Validator
+ * will be called to check all access attempts using
+ * the specified authentication type
+ */
+
+static ARRAYofARRAY8 AuthenticationNames, AuthenticationDatas;
+typedef struct _AuthenticationFuncs {
+ ValidatorFunc Validator;
+ GeneratorFunc Generator;
+ AddAuthorFunc AddAuth;
+} AuthenticationFuncsRec, *AuthenticationFuncsPtr;
+
+static AuthenticationFuncsPtr AuthenticationFuncsList;
+
+void
+XdmcpRegisterAuthentication (
+ char *name,
+ int namelen,
+ char *data,
+ int datalen,
+ ValidatorFunc Validator,
+ GeneratorFunc Generator,
+ AddAuthorFunc AddAuth)
+{
+ int i;
+ ARRAY8 AuthenticationName, AuthenticationData;
+ static AuthenticationFuncsPtr newFuncs;
+
+ if (!XdmcpAllocARRAY8 (&AuthenticationName, namelen))
+ return;
+ if (!XdmcpAllocARRAY8 (&AuthenticationData, datalen))
+ {
+ XdmcpDisposeARRAY8 (&AuthenticationName);
+ return;
+ }
+ for (i = 0; i < namelen; i++)
+ AuthenticationName.data[i] = name[i];
+ for (i = 0; i < datalen; i++)
+ AuthenticationData.data[i] = data[i];
+ if (!(XdmcpReallocARRAYofARRAY8 (&AuthenticationNames,
+ AuthenticationNames.length + 1) &&
+ XdmcpReallocARRAYofARRAY8 (&AuthenticationDatas,
+ AuthenticationDatas.length + 1) &&
+ (newFuncs = (AuthenticationFuncsPtr) malloc (
+ (AuthenticationNames.length + 1) * sizeof (AuthenticationFuncsRec)))))
+ {
+ XdmcpDisposeARRAY8 (&AuthenticationName);
+ XdmcpDisposeARRAY8 (&AuthenticationData);
+ return;
+ }
+ for (i = 0; i < AuthenticationNames.length - 1; i++)
+ newFuncs[i] = AuthenticationFuncsList[i];
+ newFuncs[AuthenticationNames.length-1].Validator = Validator;
+ newFuncs[AuthenticationNames.length-1].Generator = Generator;
+ newFuncs[AuthenticationNames.length-1].AddAuth = AddAuth;
+ free (AuthenticationFuncsList);
+ AuthenticationFuncsList = newFuncs;
+ AuthenticationNames.data[AuthenticationNames.length-1] = AuthenticationName;
+ AuthenticationDatas.data[AuthenticationDatas.length-1] = AuthenticationData;
+}
+
+/*
+ * Select the authentication type to be used; this is
+ * set by the manager of the host to be connected to.
+ */
+
+ARRAY8 noAuthenticationName = {(CARD16) 0, (CARD8Ptr) 0};
+ARRAY8 noAuthenticationData = {(CARD16) 0, (CARD8Ptr) 0};
+ARRAY8Ptr AuthenticationName = &noAuthenticationName;
+ARRAY8Ptr AuthenticationData = &noAuthenticationData;
+AuthenticationFuncsPtr AuthenticationFuncs;
+
+void
+XdmcpSetAuthentication (ARRAY8Ptr name)
+{
+ int i;
+
+ for (i = 0; i < AuthenticationNames.length; i++)
+ if (XdmcpARRAY8Equal (&AuthenticationNames.data[i], name))
+ {
+ AuthenticationName = &AuthenticationNames.data[i];
+ AuthenticationData = &AuthenticationDatas.data[i];
+ AuthenticationFuncs = &AuthenticationFuncsList[i];
+ break;
+ }
+}
+
+/*
+ * Register the host address for the display
+ */
+
+static ARRAY16 ConnectionTypes;
+static ARRAYofARRAY8 ConnectionAddresses;
+static long xdmcpGeneration;
+
+void
+XdmcpRegisterConnection (
+ int type,
+ char *address,
+ int addrlen)
+{
+ int i;
+ CARD8 *newAddress;
+
+ if (xdmcpGeneration != serverGeneration)
+ {
+ XdmcpDisposeARRAY16 (&ConnectionTypes);
+ XdmcpDisposeARRAYofARRAY8 (&ConnectionAddresses);
+ xdmcpGeneration = serverGeneration;
+ }
+ if (xdm_from != NULL) { /* Only register the requested address */
+ const void *regAddr = address;
+ const void *fromAddr = NULL;
+ int regAddrlen = addrlen;
+
+ if (addrlen == sizeof(struct in_addr)) {
+ if (SOCKADDR_FAMILY(FromAddress) == AF_INET) {
+ fromAddr = &((struct sockaddr_in *)&FromAddress)->sin_addr;
+ }
+#if defined(IPv6) && defined(AF_INET6)
+ else if ((SOCKADDR_FAMILY(FromAddress) == AF_INET6) &&
+ IN6_IS_ADDR_V4MAPPED(
+ &((struct sockaddr_in6 *)&FromAddress)->sin6_addr)) {
+ fromAddr = &((struct sockaddr_in6 *)&FromAddress)->sin6_addr.s6_addr[12];
+ }
+#endif
+ }
+#if defined(IPv6) && defined(AF_INET6)
+ else if (addrlen == sizeof(struct in6_addr)) {
+ if (SOCKADDR_FAMILY(FromAddress) == AF_INET6) {
+ fromAddr = &((struct sockaddr_in6 *)&FromAddress)->sin6_addr;
+ } else if ((SOCKADDR_FAMILY(FromAddress) == AF_INET) &&
+ IN6_IS_ADDR_V4MAPPED((struct in6_addr *) address)) {
+ fromAddr = &((struct sockaddr_in *)&FromAddress)->sin_addr;
+ regAddr = &((struct sockaddr_in6 *)&address)->sin6_addr.s6_addr[12];
+ regAddrlen = sizeof(struct in_addr);
+ }
+ }
+#endif
+ if (fromAddr && memcmp(regAddr, fromAddr, regAddrlen) != 0) {
+ return;
+ }
+ }
+ newAddress = (CARD8 *) malloc (addrlen * sizeof (CARD8));
+ if (!newAddress)
+ return;
+ if (!XdmcpReallocARRAY16 (&ConnectionTypes, ConnectionTypes.length + 1))
+ {
+ free (newAddress);
+ return;
+ }
+ if (!XdmcpReallocARRAYofARRAY8 (&ConnectionAddresses,
+ ConnectionAddresses.length + 1))
+ {
+ free (newAddress);
+ return;
+ }
+ ConnectionTypes.data[ConnectionTypes.length - 1] = (CARD16) type;
+ for (i = 0; i < addrlen; i++)
+ newAddress[i] = address[i];
+ ConnectionAddresses.data[ConnectionAddresses.length-1].data = newAddress;
+ ConnectionAddresses.data[ConnectionAddresses.length-1].length = addrlen;
+}
+
+/*
+ * Register an Authorization Name. XDMCP advertises this list
+ * to the manager.
+ */
+
+static ARRAYofARRAY8 AuthorizationNames;
+
+void
+XdmcpRegisterAuthorizations (void)
+{
+ XdmcpDisposeARRAYofARRAY8 (&AuthorizationNames);
+ RegisterAuthorizations ();
+}
+
+void
+XdmcpRegisterAuthorization (char *name, int namelen)
+{
+ ARRAY8 authName;
+ int i;
+
+ authName.data = (CARD8 *) malloc (namelen * sizeof (CARD8));
+ if (!authName.data)
+ return;
+ if (!XdmcpReallocARRAYofARRAY8 (&AuthorizationNames, AuthorizationNames.length +1))
+ {
+ free (authName.data);
+ return;
+ }
+ for (i = 0; i < namelen; i++)
+ authName.data[i] = (CARD8) name[i];
+ authName.length = namelen;
+ AuthorizationNames.data[AuthorizationNames.length-1] = authName;
+}
+
+/*
+ * Register the DisplayClass string
+ */
+
+ARRAY8 DisplayClass;
+
+void
+XdmcpRegisterDisplayClass (char *name, int length)
+{
+ int i;
+
+ XdmcpDisposeARRAY8 (&DisplayClass);
+ if (!XdmcpAllocARRAY8 (&DisplayClass, length))
+ return;
+ for (i = 0; i < length; i++)
+ DisplayClass.data[i] = (CARD8) name[i];
+}
+
+/*
+ * Register the Manufacturer display ID
+ */
+
+ARRAY8 ManufacturerDisplayID;
+
+void
+XdmcpRegisterManufacturerDisplayID (char *name, int length)
+{
+ int i;
+
+ XdmcpDisposeARRAY8 (&ManufacturerDisplayID);
+ if (!XdmcpAllocARRAY8 (&ManufacturerDisplayID, length))
+ return;
+ for (i = 0; i < length; i++)
+ ManufacturerDisplayID.data[i] = (CARD8) name[i];
+}
+
+/*
+ * initialize XDMCP; create the socket, compute the display
+ * number, set up the state machine
+ */
+
+void
+XdmcpInit(void)
+{
+#ifdef NX_TRANS_SOCKET
+
+ XdmcpStartTime = GetTimeInMillis();
+
+#endif
+
+ state = XDM_INIT_STATE;
+#ifdef HASXDMAUTH
+ if (xdmAuthCookie)
+ XdmAuthenticationInit (xdmAuthCookie, strlen (xdmAuthCookie));
+#endif
+ if (state != XDM_OFF)
+ {
+ XdmcpRegisterAuthorizations();
+ XdmcpRegisterDisplayClass (defaultDisplayClass, strlen (defaultDisplayClass));
+ AccessUsingXdmcp();
+ RegisterBlockAndWakeupHandlers (XdmcpBlockHandler, XdmcpWakeupHandler,
+ (void *) 0);
+ timeOutRtx = 0;
+ DisplayNumber = (CARD16) atoi(display);
+ get_xdmcp_sock();
+ send_packet();
+ }
+}
+
+void
+XdmcpReset (void)
+{
+ state = XDM_INIT_STATE;
+ if (state != XDM_OFF)
+ {
+ RegisterBlockAndWakeupHandlers (XdmcpBlockHandler, XdmcpWakeupHandler,
+ (void *) 0);
+ timeOutRtx = 0;
+ send_packet();
+ }
+}
+
+/*
+ * Called whenever a new connection is created; notices the
+ * first connection and saves it to terminate the session
+ * when it is closed
+ */
+
+void
+XdmcpOpenDisplay(int sock)
+{
+ if (state != XDM_AWAIT_MANAGE_RESPONSE)
+ return;
+ state = XDM_RUN_SESSION;
+ timeOutTime = GetTimeInMillis() + XDM_DEF_DORMANCY * 1000;
+ sessionSocket = sock;
+}
+
+void
+XdmcpCloseDisplay(int sock)
+{
+ if ((state != XDM_RUN_SESSION && state != XDM_AWAIT_ALIVE_RESPONSE)
+ || sessionSocket != sock)
+ return;
+ state = XDM_INIT_STATE;
+ if (OneSession)
+ dispatchException |= DE_TERMINATE;
+ else
+ dispatchException |= DE_RESET;
+ isItTimeToYield = TRUE;
+}
+
+/*
+ * called before going to sleep, this routine
+ * may modify the timeout value about to be sent
+ * to select; in this way XDMCP can do appropriate things
+ * dynamically while starting up
+ */
+
+/*ARGSUSED*/
+static void
+XdmcpBlockHandler(
+ void * data, /* unused */
+ struct timeval **wt,
+ void * pReadmask)
+{
+ fd_set *LastSelectMask = (fd_set*)pReadmask;
+ CARD32 millisToGo;
+
+ if (state == XDM_OFF)
+ return;
+ FD_SET(xdmcpSocket, LastSelectMask);
+#if defined(IPv6) && defined(AF_INET6)
+ if (xdmcpSocket6 >= 0)
+ FD_SET(xdmcpSocket6, LastSelectMask);
+#endif
+ if (timeOutTime == 0)
+ return;
+ millisToGo = timeOutTime - GetTimeInMillis();
+ if ((int) millisToGo < 0)
+ millisToGo = 0;
+ AdjustWaitForDelay (wt, millisToGo);
+}
+
+/*
+ * called after select returns; this routine will
+ * recognise when XDMCP packets await and
+ * process them appropriately
+ */
+
+/*ARGSUSED*/
+static void
+XdmcpWakeupHandler(
+ void * data, /* unused */
+ int i,
+ void * pReadmask)
+{
+ fd_set* LastSelectMask = (fd_set*)pReadmask;
+
+#ifdef NX_TRANS_SOCKET
+
+ XdmcpState = state;
+ XdmcpTimeOutRtx = timeOutRtx;
+
+#endif
+
+ if (state == XDM_OFF)
+ return;
+ if (i > 0)
+ {
+ if (FD_ISSET(xdmcpSocket, LastSelectMask))
+ {
+ receive_packet(xdmcpSocket);
+ FD_CLR(xdmcpSocket, LastSelectMask);
+ }
+#if defined(IPv6) && defined(AF_INET6)
+ if (xdmcpSocket6 >= 0 && FD_ISSET(xdmcpSocket6, LastSelectMask))
+ {
+ receive_packet(xdmcpSocket6);
+ FD_CLR(xdmcpSocket6, LastSelectMask);
+ }
+#endif
+ }
+ else if (timeOutTime && (int) (GetTimeInMillis() - timeOutTime) >= 0)
+ {
+ if (state == XDM_RUN_SESSION)
+ {
+ state = XDM_KEEPALIVE;
+ send_packet();
+ }
+ else
+ timeout();
+ }
+}
+
+/*
+ * This routine should be called from the routine that drives the
+ * user's host menu when the user selects a host
+ */
+
+static void
+XdmcpSelectHost(
+ struct sockaddr *host_sockaddr,
+ int host_len,
+ ARRAY8Ptr AuthenticationName)
+{
+ state = XDM_START_CONNECTION;
+ memmove(&req_sockaddr, host_sockaddr, host_len);
+ req_socklen = host_len;
+ XdmcpSetAuthentication (AuthenticationName);
+ send_packet();
+}
+
+/*
+ * !!! this routine should be replaced by a routine that adds
+ * the host to the user's host menu. the current version just
+ * selects the first host to respond with willing message.
+ */
+
+/*ARGSUSED*/
+static void
+XdmcpAddHost(
+ struct sockaddr *from,
+ int fromlen,
+ ARRAY8Ptr AuthenticationName,
+ ARRAY8Ptr hostname,
+ ARRAY8Ptr status)
+{
+ XdmcpSelectHost(from, fromlen, AuthenticationName);
+}
+
+/*
+ * A message is queued on the socket; read it and
+ * do the appropriate thing
+ */
+
+ARRAY8 UnwillingMessage = { (CARD8) 14, (CARD8 *) "Host unwilling" };
+
+static void
+receive_packet(int socketfd)
+{
+#if defined(IPv6) && defined(AF_INET6)
+ struct sockaddr_storage from;
+#else
+ struct sockaddr_in from;
+#endif
+ int fromlen = sizeof(from);
+ XdmcpHeader header;
+
+ /* read message off socket */
+ if (!XdmcpFill (socketfd, &buffer, (XdmcpNetaddr) &from, &fromlen))
+ return;
+
+ /* reset retransmission backoff */
+ timeOutRtx = 0;
+
+ if (!XdmcpReadHeader (&buffer, &header))
+ return;
+
+ if (header.version != XDM_PROTOCOL_VERSION)
+ return;
+
+ switch (header.opcode) {
+ case WILLING:
+ recv_willing_msg((struct sockaddr *) &from, fromlen, header.length);
+ break;
+ case UNWILLING:
+ XdmcpFatal("Manager unwilling", &UnwillingMessage);
+ break;
+ case ACCEPT:
+ recv_accept_msg(header.length);
+ break;
+ case DECLINE:
+ recv_decline_msg(header.length);
+ break;
+ case REFUSE:
+ recv_refuse_msg(header.length);
+ break;
+ case FAILED:
+ recv_failed_msg(header.length);
+ break;
+ case ALIVE:
+ recv_alive_msg(header.length);
+ break;
+ }
+}
+
+/*
+ * send the appropriate message given the current state
+ */
+
+static void
+send_packet(void)
+{
+ int rtx;
+ switch (state) {
+ case XDM_QUERY:
+ case XDM_BROADCAST:
+ case XDM_INDIRECT:
+#if defined(IPv6) && defined(AF_INET6)
+ case XDM_MULTICAST:
+#endif
+ send_query_msg();
+ break;
+ case XDM_START_CONNECTION:
+ send_request_msg();
+ break;
+ case XDM_MANAGE:
+ send_manage_msg();
+ break;
+ case XDM_KEEPALIVE:
+ send_keepalive_msg();
+ break;
+ default:
+ break;
+ }
+ rtx = (XDM_MIN_RTX << timeOutRtx);
+ if (rtx > XDM_MAX_RTX)
+ rtx = XDM_MAX_RTX;
+ timeOutTime = GetTimeInMillis() + rtx * 1000;
+}
+
+/*
+ * The session is declared dead for some reason; too many
+ * timeouts, or Keepalive failure.
+ */
+
+void
+XdmcpDeadSession (char *reason)
+{
+ ErrorF ("XDM: %s, declaring session dead\n", reason);
+ state = XDM_INIT_STATE;
+ isItTimeToYield = TRUE;
+ dispatchException |= DE_RESET;
+ timeOutTime = 0;
+ timeOutRtx = 0;
+ send_packet();
+}
+
+/*
+ * Timeout waiting for an XDMCP response.
+ */
+
+static void
+timeout(void)
+{
+ timeOutRtx++;
+ if (state == XDM_AWAIT_ALIVE_RESPONSE && timeOutRtx >= XDM_KA_RTX_LIMIT )
+ {
+ XdmcpDeadSession ("too many keepalive retransmissions");
+ return;
+ }
+ else if (timeOutRtx >= XDM_RTX_LIMIT)
+ {
+ /* Quit if "-once" specified, otherwise reset and try again. */
+ if (OneSession) {
+ dispatchException |= DE_TERMINATE;
+ ErrorF("XDM: too many retransmissions\n");
+ } else {
+ XdmcpDeadSession("too many retransmissions");
+ }
+ return;
+ }
+
+#if defined(IPv6) && defined(AF_INET6)
+ if (state == XDM_COLLECT_QUERY || state == XDM_COLLECT_INDIRECT_QUERY) {
+ /* Try next address */
+ for (mgrAddr = mgrAddr->ai_next; ; mgrAddr = mgrAddr->ai_next) {
+ if (mgrAddr == NULL) {
+ mgrAddr = mgrAddrFirst;
+ }
+ if (mgrAddr->ai_family == AF_INET
+ || mgrAddr->ai_family == AF_INET6)
+ break;
+ }
+#ifndef SIN6_LEN
+ ManagerAddressLen = mgrAddr->ai_addrlen;
+#endif
+ memcpy(&ManagerAddress, mgrAddr->ai_addr, mgrAddr->ai_addrlen);
+ }
+#endif
+
+ switch (state) {
+ case XDM_COLLECT_QUERY:
+ state = XDM_QUERY;
+ break;
+ case XDM_COLLECT_BROADCAST_QUERY:
+ state = XDM_BROADCAST;
+ break;
+#if defined(IPv6) && defined(AF_INET6)
+ case XDM_COLLECT_MULTICAST_QUERY:
+ state = XDM_MULTICAST;
+ break;
+#endif
+ case XDM_COLLECT_INDIRECT_QUERY:
+ state = XDM_INDIRECT;
+ break;
+ case XDM_AWAIT_REQUEST_RESPONSE:
+ state = XDM_START_CONNECTION;
+ break;
+ case XDM_AWAIT_MANAGE_RESPONSE:
+ state = XDM_MANAGE;
+ break;
+ case XDM_AWAIT_ALIVE_RESPONSE:
+ state = XDM_KEEPALIVE;
+ break;
+ default:
+ break;
+ }
+ send_packet();
+}
+
+int
+XdmcpCheckAuthentication (
+ ARRAY8Ptr Name,
+ ARRAY8Ptr Data,
+ int packet_type)
+{
+ return (XdmcpARRAY8Equal (Name, AuthenticationName) &&
+ (AuthenticationName->length == 0 ||
+ (*AuthenticationFuncs->Validator) (AuthenticationData, Data, packet_type)));
+}
+
+int
+XdmcpAddAuthorization (
+ ARRAY8Ptr name,
+ ARRAY8Ptr data)
+{
+ AddAuthorFunc AddAuth;
+
+ if (AuthenticationFuncs && AuthenticationFuncs->AddAuth)
+ AddAuth = AuthenticationFuncs->AddAuth;
+ else
+ AddAuth = AddAuthorization;
+ return (*AddAuth) ((unsigned short)name->length,
+ (char *)name->data,
+ (unsigned short)data->length,
+ (char *)data->data);
+}
+
+/*
+ * from here to the end of this file are routines private
+ * to the state machine.
+ */
+
+static void
+get_xdmcp_sock(void)
+{
+ int soopts = 1;
+
+#if defined(IPv6) && defined(AF_INET6)
+ if ((xdmcpSocket6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
+ XdmcpWarning("INET6 UDP socket creation failed");
+#endif
+ if ((xdmcpSocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+ XdmcpWarning("UDP socket creation failed");
+#ifdef SO_BROADCAST
+ else if (setsockopt(xdmcpSocket, SOL_SOCKET, SO_BROADCAST, (char *)&soopts,
+ sizeof(soopts)) < 0)
+ XdmcpWarning("UDP set broadcast socket-option failed");
+#endif /* SO_BROADCAST */
+ if (xdmcpSocket >= 0 && xdm_from != NULL) {
+ if (bind(xdmcpSocket, (struct sockaddr *)&FromAddress,
+ FromAddressLen) < 0) {
+ FatalError("Xserver: failed to bind to -from address: %s\n", xdm_from);
+ }
+ }
+}
+
+static void
+send_query_msg(void)
+{
+ XdmcpHeader header;
+ Bool broadcast = FALSE;
+#if defined(IPv6) && defined(AF_INET6)
+ Bool multicast = FALSE;
+#endif
+ int i;
+ int socketfd = xdmcpSocket;
+
+ header.version = XDM_PROTOCOL_VERSION;
+ switch(state){
+ case XDM_QUERY:
+ header.opcode = (CARD16) QUERY;
+ state = XDM_COLLECT_QUERY;
+ break;
+ case XDM_BROADCAST:
+ header.opcode = (CARD16) BROADCAST_QUERY;
+ state = XDM_COLLECT_BROADCAST_QUERY;
+ broadcast = TRUE;
+ break;
+#if defined(IPv6) && defined(AF_INET6)
+ case XDM_MULTICAST:
+ header.opcode = (CARD16) BROADCAST_QUERY;
+ state = XDM_COLLECT_MULTICAST_QUERY;
+ multicast = TRUE;
+ break;
+#endif
+ case XDM_INDIRECT:
+ header.opcode = (CARD16) INDIRECT_QUERY;
+ state = XDM_COLLECT_INDIRECT_QUERY;
+ break;
+ default:
+ break;
+ }
+ header.length = 1;
+ for (i = 0; i < AuthenticationNames.length; i++)
+ header.length += 2 + AuthenticationNames.data[i].length;
+
+ XdmcpWriteHeader (&buffer, &header);
+ XdmcpWriteARRAYofARRAY8 (&buffer, &AuthenticationNames);
+ if (broadcast)
+ {
+ int i;
+
+ for (i = 0; i < NumBroadcastAddresses; i++)
+ XdmcpFlush (xdmcpSocket, &buffer, (XdmcpNetaddr) &BroadcastAddresses[i],
+ sizeof (struct sockaddr_in));
+ }
+#if defined(IPv6) && defined(AF_INET6)
+ else if (multicast)
+ {
+ struct multicastinfo *mcl;
+ struct addrinfo *ai;
+
+ for (mcl = mcastlist; mcl != NULL; mcl = mcl->next) {
+ for (ai = mcl->ai ; ai != NULL; ai = ai->ai_next) {
+ if (ai->ai_family == AF_INET) {
+ unsigned char hopflag = (unsigned char) mcl->hops;
+ socketfd = xdmcpSocket;
+ setsockopt(socketfd, IPPROTO_IP, IP_MULTICAST_TTL,
+ &hopflag, sizeof(hopflag));
+ } else if (ai->ai_family == AF_INET6) {
+ int hopflag6 = mcl->hops;
+ socketfd = xdmcpSocket6;
+ setsockopt(socketfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
+ &hopflag6, sizeof(hopflag6));
+ } else {
+ continue;
+ }
+ XdmcpFlush (socketfd, &buffer,
+ (XdmcpNetaddr) ai->ai_addr, ai->ai_addrlen);
+ break;
+ }
+ }
+ }
+#endif
+ else
+ {
+#if defined(IPv6) && defined(AF_INET6)
+ if (SOCKADDR_FAMILY(ManagerAddress) == AF_INET6)
+ socketfd = xdmcpSocket6;
+#endif
+ XdmcpFlush (socketfd, &buffer, (XdmcpNetaddr) &ManagerAddress,
+ ManagerAddressLen);
+ }
+}
+
+static void
+recv_willing_msg(
+ struct sockaddr *from,
+ int fromlen,
+ unsigned length)
+{
+ ARRAY8 authenticationName;
+ ARRAY8 hostname;
+ ARRAY8 status;
+
+ authenticationName.data = 0;
+ hostname.data = 0;
+ status.data = 0;
+ if (XdmcpReadARRAY8 (&buffer, &authenticationName) &&
+ XdmcpReadARRAY8 (&buffer, &hostname) &&
+ XdmcpReadARRAY8 (&buffer, &status))
+ {
+ if (length == 6 + authenticationName.length +
+ hostname.length + status.length)
+ {
+ switch (state)
+ {
+ case XDM_COLLECT_QUERY:
+ XdmcpSelectHost(from, fromlen, &authenticationName);
+ break;
+ case XDM_COLLECT_BROADCAST_QUERY:
+#if defined(IPv6) && defined(AF_INET6)
+ case XDM_COLLECT_MULTICAST_QUERY:
+#endif
+ case XDM_COLLECT_INDIRECT_QUERY:
+ XdmcpAddHost(from, fromlen, &authenticationName, &hostname, &status);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ XdmcpDisposeARRAY8 (&authenticationName);
+ XdmcpDisposeARRAY8 (&hostname);
+ XdmcpDisposeARRAY8 (&status);
+}
+
+static void
+send_request_msg(void)
+{
+ XdmcpHeader header;
+ int length;
+ int i;
+ CARD16 XdmcpConnectionType;
+ ARRAY8 authenticationData;
+ int socketfd = xdmcpSocket;
+
+ switch (SOCKADDR_FAMILY(ManagerAddress))
+ {
+ case AF_INET: XdmcpConnectionType=FamilyInternet; break;
+#if defined(IPv6) && defined(AF_INET6)
+ case AF_INET6: XdmcpConnectionType=FamilyInternet6; break;
+#endif
+ default: XdmcpConnectionType=0xffff; break;
+ }
+
+ header.version = XDM_PROTOCOL_VERSION;
+ header.opcode = (CARD16) REQUEST;
+
+ length = 2; /* display number */
+ length += 1 + 2 * ConnectionTypes.length; /* connection types */
+ length += 1; /* connection addresses */
+ for (i = 0; i < ConnectionAddresses.length; i++)
+ length += 2 + ConnectionAddresses.data[i].length;
+ authenticationData.length = 0;
+ authenticationData.data = 0;
+ if (AuthenticationFuncs)
+ {
+ (*AuthenticationFuncs->Generator) (AuthenticationData,
+ &authenticationData,
+ REQUEST);
+ }
+ length += 2 + AuthenticationName->length; /* authentication name */
+ length += 2 + authenticationData.length; /* authentication data */
+ length += 1; /* authorization names */
+ for (i = 0; i < AuthorizationNames.length; i++)
+ length += 2 + AuthorizationNames.data[i].length;
+ length += 2 + ManufacturerDisplayID.length; /* display ID */
+ header.length = length;
+
+ if (!XdmcpWriteHeader (&buffer, &header))
+ {
+ XdmcpDisposeARRAY8 (&authenticationData);
+ return;
+ }
+ XdmcpWriteCARD16 (&buffer, DisplayNumber);
+ XdmcpWriteCARD8 (&buffer, ConnectionTypes.length);
+
+ /* The connection array is send reordered, so that connections of */
+ /* the same address type as the XDMCP manager connection are send */
+ /* first. This works around a bug in xdm. mario@klebsch.de */
+ for (i = 0; i < (int)ConnectionTypes.length; i++)
+ if (ConnectionTypes.data[i]==XdmcpConnectionType)
+ XdmcpWriteCARD16 (&buffer, ConnectionTypes.data[i]);
+ for (i = 0; i < (int)ConnectionTypes.length; i++)
+ if (ConnectionTypes.data[i]!=XdmcpConnectionType)
+ XdmcpWriteCARD16 (&buffer, ConnectionTypes.data[i]);
+
+ XdmcpWriteCARD8 (&buffer, ConnectionAddresses.length);
+ for (i = 0; i < (int)ConnectionAddresses.length; i++)
+ if ( (i<ConnectionTypes.length) &&
+ (ConnectionTypes.data[i]==XdmcpConnectionType) )
+ XdmcpWriteARRAY8 (&buffer, &ConnectionAddresses.data[i]);
+ for (i = 0; i < (int)ConnectionAddresses.length; i++)
+ if ( (i>=ConnectionTypes.length) ||
+ (ConnectionTypes.data[i]!=XdmcpConnectionType) )
+ XdmcpWriteARRAY8 (&buffer, &ConnectionAddresses.data[i]);
+
+ XdmcpWriteARRAY8 (&buffer, AuthenticationName);
+ XdmcpWriteARRAY8 (&buffer, &authenticationData);
+ XdmcpDisposeARRAY8 (&authenticationData);
+ XdmcpWriteARRAYofARRAY8 (&buffer, &AuthorizationNames);
+ XdmcpWriteARRAY8 (&buffer, &ManufacturerDisplayID);
+#if defined(IPv6) && defined(AF_INET6)
+ if (SOCKADDR_FAMILY(req_sockaddr) == AF_INET6)
+ socketfd = xdmcpSocket6;
+#endif
+ if (XdmcpFlush (socketfd, &buffer,
+ (XdmcpNetaddr) &req_sockaddr, req_socklen))
+ state = XDM_AWAIT_REQUEST_RESPONSE;
+}
+
+static void
+recv_accept_msg(unsigned length)
+{
+ CARD32 AcceptSessionID;
+ ARRAY8 AcceptAuthenticationName, AcceptAuthenticationData;
+ ARRAY8 AcceptAuthorizationName, AcceptAuthorizationData;
+
+ if (state != XDM_AWAIT_REQUEST_RESPONSE)
+ return;
+ AcceptAuthenticationName.data = 0;
+ AcceptAuthenticationData.data = 0;
+ AcceptAuthorizationName.data = 0;
+ AcceptAuthorizationData.data = 0;
+ if (XdmcpReadCARD32 (&buffer, &AcceptSessionID) &&
+ XdmcpReadARRAY8 (&buffer, &AcceptAuthenticationName) &&
+ XdmcpReadARRAY8 (&buffer, &AcceptAuthenticationData) &&
+ XdmcpReadARRAY8 (&buffer, &AcceptAuthorizationName) &&
+ XdmcpReadARRAY8 (&buffer, &AcceptAuthorizationData))
+ {
+ if (length == 12 + AcceptAuthenticationName.length +
+ AcceptAuthenticationData.length +
+ AcceptAuthorizationName.length +
+ AcceptAuthorizationData.length)
+ {
+ if (!XdmcpCheckAuthentication (&AcceptAuthenticationName,
+ &AcceptAuthenticationData, ACCEPT))
+ {
+ XdmcpFatal ("Authentication Failure", &AcceptAuthenticationName);
+ }
+ /* permit access control manipulations from this host */
+ AugmentSelf (&req_sockaddr, req_socklen);
+ /* if the authorization specified in the packet fails
+ * to be acceptable, enable the local addresses
+ */
+ if (!XdmcpAddAuthorization (&AcceptAuthorizationName,
+ &AcceptAuthorizationData))
+ {
+ AddLocalHosts ();
+ }
+ SessionID = AcceptSessionID;
+ state = XDM_MANAGE;
+ send_packet();
+ }
+ }
+ XdmcpDisposeARRAY8 (&AcceptAuthenticationName);
+ XdmcpDisposeARRAY8 (&AcceptAuthenticationData);
+ XdmcpDisposeARRAY8 (&AcceptAuthorizationName);
+ XdmcpDisposeARRAY8 (&AcceptAuthorizationData);
+}
+
+static void
+recv_decline_msg(unsigned length)
+{
+ ARRAY8 status, DeclineAuthenticationName, DeclineAuthenticationData;
+
+ status.data = 0;
+ DeclineAuthenticationName.data = 0;
+ DeclineAuthenticationData.data = 0;
+ if (XdmcpReadARRAY8 (&buffer, &status) &&
+ XdmcpReadARRAY8 (&buffer, &DeclineAuthenticationName) &&
+ XdmcpReadARRAY8 (&buffer, &DeclineAuthenticationData))
+ {
+ if (length == 6 + status.length +
+ DeclineAuthenticationName.length +
+ DeclineAuthenticationData.length &&
+ XdmcpCheckAuthentication (&DeclineAuthenticationName,
+ &DeclineAuthenticationData, DECLINE))
+ {
+ XdmcpFatal ("Session declined", &status);
+ }
+ }
+ XdmcpDisposeARRAY8 (&status);
+ XdmcpDisposeARRAY8 (&DeclineAuthenticationName);
+ XdmcpDisposeARRAY8 (&DeclineAuthenticationData);
+}
+
+static void
+send_manage_msg(void)
+{
+ XdmcpHeader header;
+ int socketfd = xdmcpSocket;
+
+ header.version = XDM_PROTOCOL_VERSION;
+ header.opcode = (CARD16) MANAGE;
+ header.length = 8 + DisplayClass.length;
+
+ if (!XdmcpWriteHeader (&buffer, &header))
+ return;
+ XdmcpWriteCARD32 (&buffer, SessionID);
+ XdmcpWriteCARD16 (&buffer, DisplayNumber);
+ XdmcpWriteARRAY8 (&buffer, &DisplayClass);
+ state = XDM_AWAIT_MANAGE_RESPONSE;
+#if defined(IPv6) && defined(AF_INET6)
+ if (SOCKADDR_FAMILY(req_sockaddr) == AF_INET6)
+ socketfd = xdmcpSocket6;
+#endif
+ XdmcpFlush (socketfd, &buffer, (XdmcpNetaddr) &req_sockaddr, req_socklen);
+}
+
+static void
+recv_refuse_msg(unsigned length)
+{
+ CARD32 RefusedSessionID;
+
+ if (state != XDM_AWAIT_MANAGE_RESPONSE)
+ return;
+ if (length != 4)
+ return;
+ if (XdmcpReadCARD32 (&buffer, &RefusedSessionID))
+ {
+ if (RefusedSessionID == SessionID)
+ {
+ state = XDM_START_CONNECTION;
+ send_packet();
+ }
+ }
+}
+
+static void
+recv_failed_msg(unsigned length)
+{
+ CARD32 FailedSessionID;
+ ARRAY8 status;
+
+ if (state != XDM_AWAIT_MANAGE_RESPONSE)
+ return;
+ status.data = 0;
+ if (XdmcpReadCARD32 (&buffer, &FailedSessionID) &&
+ XdmcpReadARRAY8 (&buffer, &status))
+ {
+ if (length == 6 + status.length &&
+ SessionID == FailedSessionID)
+ {
+ XdmcpFatal ("Session failed", &status);
+ }
+ }
+ XdmcpDisposeARRAY8 (&status);
+}
+
+static void
+send_keepalive_msg(void)
+{
+ XdmcpHeader header;
+ int socketfd = xdmcpSocket;
+
+ header.version = XDM_PROTOCOL_VERSION;
+ header.opcode = (CARD16) KEEPALIVE;
+ header.length = 6;
+
+ XdmcpWriteHeader (&buffer, &header);
+ XdmcpWriteCARD16 (&buffer, DisplayNumber);
+ XdmcpWriteCARD32 (&buffer, SessionID);
+
+ state = XDM_AWAIT_ALIVE_RESPONSE;
+#if defined(IPv6) && defined(AF_INET6)
+ if (SOCKADDR_FAMILY(req_sockaddr) == AF_INET6)
+ socketfd = xdmcpSocket6;
+#endif
+ XdmcpFlush (socketfd, &buffer, (XdmcpNetaddr) &req_sockaddr, req_socklen);
+}
+
+static void
+recv_alive_msg (unsigned length)
+{
+ CARD8 SessionRunning;
+ CARD32 AliveSessionID;
+
+ if (state != XDM_AWAIT_ALIVE_RESPONSE)
+ return;
+ if (length != 5)
+ return;
+ if (XdmcpReadCARD8 (&buffer, &SessionRunning) &&
+ XdmcpReadCARD32 (&buffer, &AliveSessionID))
+ {
+ if (SessionRunning && AliveSessionID == SessionID)
+ {
+ state = XDM_RUN_SESSION;
+ timeOutTime = GetTimeInMillis() + XDM_DEF_DORMANCY * 1000;
+ }
+ else
+ {
+ XdmcpDeadSession ("Alive response indicates session dead");
+ }
+ }
+}
+
+static void
+XdmcpFatal (
+ char *type,
+ ARRAY8Ptr status)
+{
+ FatalError ("XDMCP fatal error: %s %*.*s\n", type,
+ status->length, status->length, status->data);
+}
+
+static void
+XdmcpWarning(char *str)
+{
+ ErrorF("XDMCP warning: %s\n", str);
+}
+
+static void
+get_addr_by_name(
+ char * argtype,
+ char * namestr,
+ int port,
+ int socktype,
+ SOCKADDR_TYPE *addr,
+ SOCKLEN_TYPE *addrlen
+#if defined(IPv6) && defined(AF_INET6)
+ ,
+ struct addrinfo **aip,
+ struct addrinfo **aifirstp
+#endif
+ )
+{
+#if defined(IPv6) && defined(AF_INET6)
+ struct addrinfo *ai;
+ struct addrinfo hints;
+ char portstr[6];
+ char *pport = portstr;
+ int gaierr;
+
+ bzero(&hints, sizeof(hints));
+ hints.ai_socktype = socktype;
+
+ if (port == 0) {
+ pport = NULL;
+ } else if (port > 0 && port < 65535) {
+ sprintf(portstr, "%d", port);
+ } else {
+ FatalError("Xserver: port out of range: %d\n", port);
+ }
+
+ if (*aifirstp != NULL) {
+ freeaddrinfo(*aifirstp);
+ *aifirstp = NULL;
+ }
+
+ if ((gaierr = getaddrinfo(namestr, pport, &hints, aifirstp)) == 0) {
+ for (ai = *aifirstp; ai != NULL; ai = ai->ai_next) {
+ if (ai->ai_family == AF_INET || ai->ai_family == AF_INET6)
+ break;
+ }
+ if ((ai == NULL) || (ai->ai_addrlen > sizeof(SOCKADDR_TYPE))) {
+ FatalError ("Xserver: %s host %s not on supported network type\n",
+ argtype, namestr);
+ } else {
+ *aip = ai;
+ *addrlen = ai->ai_addrlen;
+ memcpy(addr, ai->ai_addr, ai->ai_addrlen);
+ }
+ } else {
+ FatalError("Xserver: %s: %s %s\n", gai_strerror(gaierr), argtype, namestr);
+ }
+#else
+ struct hostent *hep;
+#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
+ _Xgethostbynameparams hparams;
+#endif
+#if defined(WIN32) && defined(TCPCONN)
+ _XSERVTransWSAStartup();
+#endif
+ if (!(hep = _XGethostbyname(namestr, hparams)))
+ {
+ FatalError("Xserver: %s unknown host: %s\n", argtype, namestr);
+ }
+ if (hep->h_length == sizeof (struct in_addr))
+ {
+ memmove(&addr->sin_addr, hep->h_addr, hep->h_length);
+ *addrlen = sizeof(struct sockaddr_in);
+ addr->sin_family = AF_INET;
+ addr->sin_port = htons (port);
+ }
+ else
+ {
+ FatalError("Xserver: %s host on strange network %s\n", argtype, namestr);
+ }
+#endif
+}
+
+static void
+get_manager_by_name(
+ int argc,
+ char **argv,
+ int i)
+{
+
+ if ((i + 1) == argc)
+ {
+ FatalError("Xserver: missing %s host name in command line\n", argv[i]);
+ }
+
+ get_addr_by_name(argv[i], argv[i+1], xdm_udp_port, SOCK_DGRAM,
+ &ManagerAddress, &ManagerAddressLen
+#if defined(IPv6) && defined(AF_INET6)
+ , &mgrAddr, &mgrAddrFirst
+#endif
+ );
+}
+
+
+static void
+get_fromaddr_by_name(
+ int argc,
+ char **argv,
+ int i)
+{
+#if defined(IPv6) && defined(AF_INET6)
+ struct addrinfo *ai = NULL;
+ struct addrinfo *aifirst = NULL;
+#endif
+ if (i == argc)
+ {
+ FatalError("Xserver: missing -from host name in command line\n");
+ }
+ get_addr_by_name("-from", argv[i], 0, 0, &FromAddress, &FromAddressLen
+#if defined(IPv6) && defined(AF_INET6)
+ , &ai, &aifirst
+#endif
+ );
+ xdm_from = argv[i];
+}
+
+
+#if defined(IPv6) && defined(AF_INET6)
+static int
+get_mcast_options(argc, argv, i)
+ int argc, i;
+ char **argv;
+{
+ char *address = XDM_DEFAULT_MCAST_ADDR6;
+ int hopcount = 1;
+ struct addrinfo hints;
+ char portstr[6];
+ int gaierr;
+ struct addrinfo *ai, *firstai;
+
+ if ((i < argc) && (argv[i][0] != '-') && (argv[i][0] != '+')) {
+ address = argv[i++];
+ if ((i < argc) && (argv[i][0] != '-') && (argv[i][0] != '+')) {
+ hopcount = strtol(argv[i++], NULL, 10);
+ if ((hopcount < 1) || (hopcount > 255)) {
+ FatalError("Xserver: multicast hop count out of range: %d\n",
+ hopcount);
+ }
+ }
+ }
+
+ if (xdm_udp_port > 0 && xdm_udp_port < 65535) {
+ sprintf(portstr, "%d", xdm_udp_port);
+ } else {
+ FatalError("Xserver: port out of range: %d\n", xdm_udp_port);
+ }
+ bzero(&hints, sizeof(hints));
+ hints.ai_socktype = SOCK_DGRAM;
+
+ if ((gaierr = getaddrinfo(address, portstr, &hints, &firstai)) == 0) {
+ for (ai = firstai; ai != NULL; ai = ai->ai_next) {
+ if (((ai->ai_family == AF_INET) &&
+ IN_MULTICAST(((struct sockaddr_in *) ai->ai_addr)
+ ->sin_addr.s_addr))
+ || ((ai->ai_family == AF_INET6) &&
+ IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *) ai->ai_addr)
+ ->sin6_addr)))
+ break;
+ }
+ if (ai == NULL) {
+ FatalError ("Xserver: address not supported multicast type %s\n",
+ address);
+ } else {
+ struct multicastinfo *mcastinfo, *mcl;
+
+ mcastinfo = malloc(sizeof(struct multicastinfo));
+ mcastinfo->next = NULL;
+ mcastinfo->ai = firstai;
+ mcastinfo->hops = hopcount;
+
+ if (mcastlist == NULL) {
+ mcastlist = mcastinfo;
+ } else {
+ for (mcl = mcastlist; mcl->next != NULL; mcl = mcl->next) {
+ /* Do nothing - just find end of list */
+ }
+ mcl->next = mcastinfo;
+ }
+ }
+ } else {
+ FatalError("Xserver: %s: %s\n", gai_strerror(gaierr), address);
+ }
+ return i;
+}
+#endif
+
+#else
+static int xdmcp_non_empty; /* avoid complaint by ranlib */
+#endif /* XDMCP */
diff --git a/nx-X11/programs/Xserver/os/xprintf.c b/nx-X11/programs/Xserver/os/xprintf.c
new file mode 100644
index 000000000..1bcb36d3c
--- /dev/null
+++ b/nx-X11/programs/Xserver/os/xprintf.c
@@ -0,0 +1,163 @@
+/*
+ * printf routines which malloc their buffer
+ */
+/*
+ * Copyright (c) 2004 Alexander Gottwald
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above copyright
+ * holders shall not be used in advertising or otherwise to promote the sale,
+ * use or other dealings in this Software without prior written authorization.
+ */
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <nx-X11/Xos.h>
+#include "os.h"
+#include <stdarg.h>
+#include <stdio.h>
+
+#ifndef va_copy
+# ifdef __va_copy
+# define va_copy __va_copy
+# else
+# error "no working va_copy was found"
+# endif
+#endif
+
+#ifdef NX_TRANS_SOCKET
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+#define START_SIZE 256
+#define END_SIZE 2048
+
+char *
+Xvprintf(const char *format, va_list va)
+{
+ char *ret;
+ char *newret;
+ int size;
+ int r;
+
+ size = 0;
+
+ for (;;)
+ {
+ if (size == 0)
+ {
+ ret = (char *)malloc(START_SIZE);
+ if (ret == NULL)
+ return NULL;
+ size = START_SIZE;
+ }
+ else if (size < END_SIZE &&
+ (newret = (char *) realloc(ret, 2 * size)) != NULL)
+ {
+ ret = newret;
+ size = 2 * size;
+ }
+ else
+ {
+ free(ret);
+ return NULL;
+ }
+
+ r = vsnprintf(ret, size, format, va);
+
+ if (r == -1 || r == size || r > size || r == size - 1)
+ {
+ continue;
+ }
+ else
+ {
+ ret[r] = 0;
+ return ret;
+ }
+ }
+}
+
+#else
+
+char *
+Xvprintf(const char *format, va_list va)
+{
+ char *ret;
+ int size;
+ va_list va2;
+
+ va_copy(va2, va);
+ size = vsnprintf(NULL, 0, format, va2);
+ va_end(va2);
+
+ ret = (char *)malloc(size + 1);
+ if (ret == NULL)
+ return NULL;
+
+ vsnprintf(ret, size + 1, format, va);
+ ret[size] = 0;
+ return ret;
+}
+
+#endif
+
+char *Xprintf(const char *format, ...)
+{
+ char *ret;
+ va_list va;
+ va_start(va, format);
+ ret = Xvprintf(format, va);
+ va_end(va);
+ return ret;
+}
+
+char *
+XNFvprintf(const char *format, va_list va)
+{
+ char *ret;
+ int size;
+ va_list va2;
+
+ va_copy(va2, va);
+ size = vsnprintf(NULL, 0, format, va2);
+ va_end(va2);
+
+ ret = (char *)XNFalloc(size + 1);
+ if (ret == NULL)
+ return NULL;
+
+ vsnprintf(ret, size + 1, format, va);
+ ret[size] = 0;
+ return ret;
+}
+
+char *XNFprintf(const char *format, ...)
+{
+ char *ret;
+ va_list va;
+ va_start(va, format);
+ ret = XNFvprintf(format, va);
+ va_end(va);
+ return ret;
+}
diff --git a/nx-X11/programs/Xserver/os/xstrans.c b/nx-X11/programs/Xserver/os/xstrans.c
new file mode 100644
index 000000000..cdb664430
--- /dev/null
+++ b/nx-X11/programs/Xserver/os/xstrans.c
@@ -0,0 +1,17 @@
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <nx-X11/Xfuncproto.h>
+
+/* ErrorF is used by xtrans */
+#ifndef HAVE_DIX_CONFIG_H
+extern _X_EXPORT void
+ErrorF(const char *f, ...)
+_X_ATTRIBUTE_PRINTF(1, 2);
+#endif
+
+#define TRANS_REOPEN
+#define TRANS_SERVER
+#define XSERV_t
+#include <nx-X11/Xtrans/transport.c>