summaryrefslogtreecommitdiff
path: root/os
diff options
context:
space:
mode:
authorroot <root@zombrain.(none)>2011-07-25 08:54:41 (GMT)
committerroot <root@zombrain.(none)>2011-07-25 08:54:41 (GMT)
commitab4fcaad149d4bdccefa8f693c2a8e044b40dd4c (patch)
treec95c280caabc70e7aedbde723e38820047357be7 /os
initial state (xorg-server 1.10.2)
Diffstat (limited to 'os')
-rw-r--r--os/Makefile.am67
-rw-r--r--os/Makefile.in802
-rw-r--r--os/WaitFor.c687
-rw-r--r--os/access.c2095
-rw-r--r--os/auth.c328
-rw-r--r--os/backtrace.c213
-rw-r--r--os/connection.c1308
-rw-r--r--os/io.c1147
-rw-r--r--os/log.c598
-rw-r--r--os/mitauth.c197
-rw-r--r--os/os.c0
-rw-r--r--os/oscolor.c1606
-rw-r--r--os/osdep.h288
-rw-r--r--os/osinit.c315
-rw-r--r--os/rpcauth.c193
-rw-r--r--os/strcasecmp.c70
-rw-r--r--os/strcasestr.c64
-rw-r--r--os/strlcat.c59
-rw-r--r--os/strlcpy.c54
-rw-r--r--os/utils.c1825
-rw-r--r--os/xdmauth.c499
-rw-r--r--os/xdmcp.c1661
-rw-r--r--os/xprintf.c226
-rw-r--r--os/xsha1.c168
-rw-r--r--os/xstrans.c13
25 files changed, 14483 insertions, 0 deletions
diff --git a/os/Makefile.am b/os/Makefile.am
new file mode 100644
index 0000000..3e4f2c5
--- /dev/null
+++ b/os/Makefile.am
@@ -0,0 +1,67 @@
+noinst_LTLIBRARIES = libos.la liblog.la
+
+AM_CFLAGS = $(DIX_CFLAGS) $(SHA1_CFLAGS)
+
+SECURERPC_SRCS = rpcauth.c
+XDMCP_SRCS = xdmcp.c
+STRLCAT_SRCS = strlcat.c strlcpy.c
+
+# Build a convenience library liblog.la that will be added into
+# libos.la. The split is done so that log.c can be built with
+# different compiler options.
+liblog_la_SOURCES = log.c
+# Add flags needed for proper backtraces of functions marked with GCC
+# __attribute__((noreturn)). Currently those flags are needed for
+# FatalError and AbortServer in log.c.
+liblog_la_CFLAGS = $(AM_CFLAGS) $(ARM_BACKTRACE_CFLAGS)
+
+libos_la_SOURCES = \
+ WaitFor.c \
+ access.c \
+ auth.c \
+ backtrace.c \
+ connection.c \
+ io.c \
+ mitauth.c \
+ oscolor.c \
+ osdep.h \
+ osinit.c \
+ utils.c \
+ strcasecmp.c \
+ strcasestr.c \
+ xdmauth.c \
+ xsha1.c \
+ xstrans.c \
+ xprintf.c
+libos_la_LIBADD = @SHA1_LIBS@ $(DLOPEN_LIBS) liblog.la
+
+if SECURE_RPC
+libos_la_SOURCES += $(SECURERPC_SRCS)
+endif
+
+if XDMCP
+libos_la_SOURCES += $(XDMCP_SRCS)
+endif
+
+if NEED_STRLCAT
+libos_la_SOURCES += $(STRLCAT_SRCS)
+endif
+
+EXTRA_DIST = $(SECURERPC_SRCS) $(INTERNALMALLOC_SRCS) \
+ $(XDMCP_SRCS) $(STRLCAT_SRCS)
+
+if SPECIAL_DTRACE_OBJECTS
+# Generate dtrace object code for probes in libos & libdix
+dtrace.o: $(top_srcdir)/dix/Xserver.d $(am_libos_la_OBJECTS)
+ $(AM_V_GEN)$(DTRACE) -G -C -o $@ -s $(top_srcdir)/dix/Xserver.d .libs/*.o ../dix/.libs/*.o
+
+noinst_PROGRAMS = os.O
+
+os.O: dtrace.o $(am_libos_la_OBJECTS)
+ $(AM_V_GEN)ld -r -o $@ dtrace.o .libs/*.o
+endif
+
+os.c:
+ touch $@
+
+CLEANFILES = os.c
diff --git a/os/Makefile.in b/os/Makefile.in
new file mode 100644
index 0000000..66937d7
--- /dev/null
+++ b/os/Makefile.in
@@ -0,0 +1,802 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@SECURE_RPC_TRUE@am__append_1 = $(SECURERPC_SRCS)
+@XDMCP_TRUE@am__append_2 = $(XDMCP_SRCS)
+@NEED_STRLCAT_TRUE@am__append_3 = $(STRLCAT_SRCS)
+@SPECIAL_DTRACE_OBJECTS_TRUE@noinst_PROGRAMS = os.O$(EXEEXT)
+subdir = os
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ac_define_dir.m4 \
+ $(top_srcdir)/m4/ax_tls.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/include/do-not-use-config.h \
+ $(top_builddir)/include/xorg-server.h \
+ $(top_builddir)/include/dix-config.h \
+ $(top_builddir)/include/xorg-config.h \
+ $(top_builddir)/include/xkb-config.h \
+ $(top_builddir)/include/xwin-config.h \
+ $(top_builddir)/include/kdrive-config.h \
+ $(top_builddir)/include/version-config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+liblog_la_LIBADD =
+am_liblog_la_OBJECTS = liblog_la-log.lo
+liblog_la_OBJECTS = $(am_liblog_la_OBJECTS)
+AM_V_lt = $(am__v_lt_$(V))
+am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
+am__v_lt_0 = --silent
+liblog_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(liblog_la_CFLAGS) \
+ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+am__DEPENDENCIES_1 =
+libos_la_DEPENDENCIES = $(am__DEPENDENCIES_1) liblog.la
+am__libos_la_SOURCES_DIST = WaitFor.c access.c auth.c backtrace.c \
+ connection.c io.c mitauth.c oscolor.c osdep.h osinit.c utils.c \
+ strcasecmp.c strcasestr.c xdmauth.c xsha1.c xstrans.c \
+ xprintf.c rpcauth.c xdmcp.c strlcat.c strlcpy.c
+am__objects_1 = rpcauth.lo
+@SECURE_RPC_TRUE@am__objects_2 = $(am__objects_1)
+am__objects_3 = xdmcp.lo
+@XDMCP_TRUE@am__objects_4 = $(am__objects_3)
+am__objects_5 = strlcat.lo strlcpy.lo
+@NEED_STRLCAT_TRUE@am__objects_6 = $(am__objects_5)
+am_libos_la_OBJECTS = WaitFor.lo access.lo auth.lo backtrace.lo \
+ connection.lo io.lo mitauth.lo oscolor.lo osinit.lo utils.lo \
+ strcasecmp.lo strcasestr.lo xdmauth.lo xsha1.lo xstrans.lo \
+ xprintf.lo $(am__objects_2) $(am__objects_4) $(am__objects_6)
+libos_la_OBJECTS = $(am_libos_la_OBJECTS)
+PROGRAMS = $(noinst_PROGRAMS)
+os_O_SOURCES = os.c
+os_O_OBJECTS = os.$(OBJEXT)
+os_O_LDADD = $(LDADD)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_$(V))
+am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_$(V))
+am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
+am__v_CCLD_0 = @echo " CCLD " $@;
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo " GEN " $@;
+SOURCES = $(liblog_la_SOURCES) $(libos_la_SOURCES) os.c
+DIST_SOURCES = $(liblog_la_SOURCES) $(am__libos_la_SOURCES_DIST) os.c
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ADMIN_MAN_DIR = @ADMIN_MAN_DIR@
+ADMIN_MAN_SUFFIX = @ADMIN_MAN_SUFFIX@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+APPLE_APPLICATIONS_DIR = @APPLE_APPLICATIONS_DIR@
+APPLE_APPLICATION_NAME = @APPLE_APPLICATION_NAME@
+APP_MAN_DIR = @APP_MAN_DIR@
+APP_MAN_SUFFIX = @APP_MAN_SUFFIX@
+AR = @AR@
+ARM_BACKTRACE_CFLAGS = @ARM_BACKTRACE_CFLAGS@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BASE_FONT_PATH = @BASE_FONT_PATH@
+BUILD_DATE = @BUILD_DATE@
+BUILD_TIME = @BUILD_TIME@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CHANGELOG_CMD = @CHANGELOG_CMD@
+COMPILEDDEFAULTFONTPATH = @COMPILEDDEFAULTFONTPATH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CWARNFLAGS = @CWARNFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DARWIN_LIBS = @DARWIN_LIBS@
+DBUS_CFLAGS = @DBUS_CFLAGS@
+DBUS_LIBS = @DBUS_LIBS@
+DEFAULT_LIBRARY_PATH = @DEFAULT_LIBRARY_PATH@
+DEFAULT_LOGDIR = @DEFAULT_LOGDIR@
+DEFAULT_LOGPREFIX = @DEFAULT_LOGPREFIX@
+DEFAULT_MODULE_PATH = @DEFAULT_MODULE_PATH@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DGA_CFLAGS = @DGA_CFLAGS@
+DGA_LIBS = @DGA_LIBS@
+DIX_CFLAGS = @DIX_CFLAGS@
+DIX_LIB = @DIX_LIB@
+DLLTOOL = @DLLTOOL@
+DLOPEN_LIBS = @DLOPEN_LIBS@
+DMXEXAMPLES_DEP_CFLAGS = @DMXEXAMPLES_DEP_CFLAGS@
+DMXEXAMPLES_DEP_LIBS = @DMXEXAMPLES_DEP_LIBS@
+DMXMODULES_CFLAGS = @DMXMODULES_CFLAGS@
+DMXMODULES_LIBS = @DMXMODULES_LIBS@
+DMXXIEXAMPLES_DEP_CFLAGS = @DMXXIEXAMPLES_DEP_CFLAGS@
+DMXXIEXAMPLES_DEP_LIBS = @DMXXIEXAMPLES_DEP_LIBS@
+DMXXMUEXAMPLES_DEP_CFLAGS = @DMXXMUEXAMPLES_DEP_CFLAGS@
+DMXXMUEXAMPLES_DEP_LIBS = @DMXXMUEXAMPLES_DEP_LIBS@
+DOXYGEN = @DOXYGEN@
+DRI2PROTO_CFLAGS = @DRI2PROTO_CFLAGS@
+DRI2PROTO_LIBS = @DRI2PROTO_LIBS@
+DRIPROTO_CFLAGS = @DRIPROTO_CFLAGS@
+DRIPROTO_LIBS = @DRIPROTO_LIBS@
+DRIVER_MAN_DIR = @DRIVER_MAN_DIR@
+DRIVER_MAN_SUFFIX = @DRIVER_MAN_SUFFIX@
+DRI_CFLAGS = @DRI_CFLAGS@
+DRI_DRIVER_PATH = @DRI_DRIVER_PATH@
+DRI_LIBS = @DRI_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DTRACE = @DTRACE@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FILE_MAN_DIR = @FILE_MAN_DIR@
+FILE_MAN_SUFFIX = @FILE_MAN_SUFFIX@
+FONT100DPIDIR = @FONT100DPIDIR@
+FONT75DPIDIR = @FONT75DPIDIR@
+FONTMISCDIR = @FONTMISCDIR@
+FONTOTFDIR = @FONTOTFDIR@
+FONTROOTDIR = @FONTROOTDIR@
+FONTTTFDIR = @FONTTTFDIR@
+FONTTYPE1DIR = @FONTTYPE1DIR@
+FOP = @FOP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GLX_ARCH_DEFINES = @GLX_ARCH_DEFINES@
+GLX_DEFINES = @GLX_DEFINES@
+GLX_TLS = @GLX_TLS@
+GL_CFLAGS = @GL_CFLAGS@
+GL_LIBS = @GL_LIBS@
+GREP = @GREP@
+HAL_CFLAGS = @HAL_CFLAGS@
+HAL_LIBS = @HAL_LIBS@
+INSTALL = @INSTALL@
+INSTALL_CMD = @INSTALL_CMD@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+KDRIVE_CFLAGS = @KDRIVE_CFLAGS@
+KDRIVE_INCS = @KDRIVE_INCS@
+KDRIVE_LIBS = @KDRIVE_LIBS@
+KDRIVE_LOCAL_LIBS = @KDRIVE_LOCAL_LIBS@
+KDRIVE_PURE_INCS = @KDRIVE_PURE_INCS@
+KDRIVE_PURE_LIBS = @KDRIVE_PURE_LIBS@
+LAUNCHD_ID_PREFIX = @LAUNCHD_ID_PREFIX@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LD_EXPORT_SYMBOLS_FLAG = @LD_EXPORT_SYMBOLS_FLAG@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBDRM_CFLAGS = @LIBDRM_CFLAGS@
+LIBDRM_LIBS = @LIBDRM_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBSHA1_CFLAGS = @LIBSHA1_CFLAGS@
+LIBSHA1_LIBS = @LIBSHA1_LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_MAN_DIR = @LIB_MAN_DIR@
+LIB_MAN_SUFFIX = @LIB_MAN_SUFFIX@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAIN_LIB = @MAIN_LIB@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MAN_SUBSTS = @MAN_SUBSTS@
+MISC_MAN_DIR = @MISC_MAN_DIR@
+MISC_MAN_SUFFIX = @MISC_MAN_SUFFIX@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJC = @OBJC@
+OBJCCLD = @OBJCCLD@
+OBJCDEPMODE = @OBJCDEPMODE@
+OBJCFLAGS = @OBJCFLAGS@
+OBJCLINK = @OBJCLINK@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_CFLAGS = @OPENSSL_CFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OS_LIB = @OS_LIB@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PCIACCESS_CFLAGS = @PCIACCESS_CFLAGS@
+PCIACCESS_LIBS = @PCIACCESS_LIBS@
+PCI_TXT_IDS_PATH = @PCI_TXT_IDS_PATH@
+PERL = @PERL@
+PIXMAN_CFLAGS = @PIXMAN_CFLAGS@
+PIXMAN_LIBS = @PIXMAN_LIBS@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PROJECTROOT = @PROJECTROOT@
+RANLIB = @RANLIB@
+RAWCPP = @RAWCPP@
+RAWCPPFLAGS = @RAWCPPFLAGS@
+RELEASE_DATE = @RELEASE_DATE@
+SDK_REQUIRED_MODULES = @SDK_REQUIRED_MODULES@
+SED = @SED@
+SELINUX_CFLAGS = @SELINUX_CFLAGS@
+SELINUX_LIBS = @SELINUX_LIBS@
+SERVER_MISC_CONFIG_PATH = @SERVER_MISC_CONFIG_PATH@
+SET_MAKE = @SET_MAKE@
+SHA1_CFLAGS = @SHA1_CFLAGS@
+SHA1_LIBS = @SHA1_LIBS@
+SHELL = @SHELL@
+SOLARIS_ASM_CFLAGS = @SOLARIS_ASM_CFLAGS@
+SOLARIS_INOUT_ARCH = @SOLARIS_INOUT_ARCH@
+STRIP = @STRIP@
+STYLESHEET_SRCDIR = @STYLESHEET_SRCDIR@
+SYSCONFDIR = @SYSCONFDIR@
+TSLIB_CFLAGS = @TSLIB_CFLAGS@
+TSLIB_LIBS = @TSLIB_LIBS@
+UDEV_CFLAGS = @UDEV_CFLAGS@
+UDEV_LIBS = @UDEV_LIBS@
+UTILS_SYS_LIBS = @UTILS_SYS_LIBS@
+VENDOR_NAME_SHORT = @VENDOR_NAME_SHORT@
+VERSION = @VERSION@
+WINDOWSWM_CFLAGS = @WINDOWSWM_CFLAGS@
+WINDOWSWM_LIBS = @WINDOWSWM_LIBS@
+WINDRES = @WINDRES@
+X11EXAMPLES_DEP_CFLAGS = @X11EXAMPLES_DEP_CFLAGS@
+X11EXAMPLES_DEP_LIBS = @X11EXAMPLES_DEP_LIBS@
+XDMCP_CFLAGS = @XDMCP_CFLAGS@
+XDMCP_LIBS = @XDMCP_LIBS@
+XDMXCONFIG_DEP_CFLAGS = @XDMXCONFIG_DEP_CFLAGS@
+XDMXCONFIG_DEP_LIBS = @XDMXCONFIG_DEP_LIBS@
+XDMX_CFLAGS = @XDMX_CFLAGS@
+XDMX_LIBS = @XDMX_LIBS@
+XDMX_SYS_LIBS = @XDMX_SYS_LIBS@
+XEPHYR_CFLAGS = @XEPHYR_CFLAGS@
+XEPHYR_INCS = @XEPHYR_INCS@
+XEPHYR_LIBS = @XEPHYR_LIBS@
+XF86CONFIGDIR = @XF86CONFIGDIR@
+XF86CONFIGFILE = @XF86CONFIGFILE@
+XF86VIDMODE_CFLAGS = @XF86VIDMODE_CFLAGS@
+XF86VIDMODE_LIBS = @XF86VIDMODE_LIBS@
+XKB_BASE_DIRECTORY = @XKB_BASE_DIRECTORY@
+XKB_BIN_DIRECTORY = @XKB_BIN_DIRECTORY@
+XKB_COMPILED_DIR = @XKB_COMPILED_DIR@
+XKM_OUTPUT_DIR = @XKM_OUTPUT_DIR@
+XLIB_CFLAGS = @XLIB_CFLAGS@
+XLIB_LIBS = @XLIB_LIBS@
+XMLTO = @XMLTO@
+XNESTMODULES_CFLAGS = @XNESTMODULES_CFLAGS@
+XNESTMODULES_LIBS = @XNESTMODULES_LIBS@
+XNEST_LIBS = @XNEST_LIBS@
+XNEST_SYS_LIBS = @XNEST_SYS_LIBS@
+XORG_CFLAGS = @XORG_CFLAGS@
+XORG_INCS = @XORG_INCS@
+XORG_LIBS = @XORG_LIBS@
+XORG_MAN_PAGE = @XORG_MAN_PAGE@
+XORG_MODULES_CFLAGS = @XORG_MODULES_CFLAGS@
+XORG_MODULES_LIBS = @XORG_MODULES_LIBS@
+XORG_OS = @XORG_OS@
+XORG_OS_SUBDIR = @XORG_OS_SUBDIR@
+XORG_SGML_PATH = @XORG_SGML_PATH@
+XORG_SYS_LIBS = @XORG_SYS_LIBS@
+XPBPROXY_CFLAGS = @XPBPROXY_CFLAGS@
+XPBPROXY_LIBS = @XPBPROXY_LIBS@
+XQUARTZ_SPARKLE = @XQUARTZ_SPARKLE@
+XRESEXAMPLES_DEP_CFLAGS = @XRESEXAMPLES_DEP_CFLAGS@
+XRESEXAMPLES_DEP_LIBS = @XRESEXAMPLES_DEP_LIBS@
+XSERVERCFLAGS_CFLAGS = @XSERVERCFLAGS_CFLAGS@
+XSERVERCFLAGS_LIBS = @XSERVERCFLAGS_LIBS@
+XSERVERLIBS_CFLAGS = @XSERVERLIBS_CFLAGS@
+XSERVERLIBS_LIBS = @XSERVERLIBS_LIBS@
+XSERVER_LIBS = @XSERVER_LIBS@
+XSERVER_SYS_LIBS = @XSERVER_SYS_LIBS@
+XSL_STYLESHEET = @XSL_STYLESHEET@
+XTSTEXAMPLES_DEP_CFLAGS = @XTSTEXAMPLES_DEP_CFLAGS@
+XTSTEXAMPLES_DEP_LIBS = @XTSTEXAMPLES_DEP_LIBS@
+XVFB_LIBS = @XVFB_LIBS@
+XVFB_SYS_LIBS = @XVFB_SYS_LIBS@
+XWINMODULES_CFLAGS = @XWINMODULES_CFLAGS@
+XWINMODULES_LIBS = @XWINMODULES_LIBS@
+XWIN_LIBS = @XWIN_LIBS@
+XWIN_SERVER_NAME = @XWIN_SERVER_NAME@
+XWIN_SYS_LIBS = @XWIN_SYS_LIBS@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+__XCONFIGDIR__ = @__XCONFIGDIR__@
+__XCONFIGFILE__ = @__XCONFIGFILE__@
+abi_ansic = @abi_ansic@
+abi_extension = @abi_extension@
+abi_videodrv = @abi_videodrv@
+abi_xinput = @abi_xinput@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+driverdir = @driverdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+extdir = @extdir@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+logdir = @logdir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+moduledir = @moduledir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sdkdir = @sdkdir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+symbol_visibility = @symbol_visibility@
+sysconfdir = @sysconfdir@
+sysconfigdir = @sysconfigdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+noinst_LTLIBRARIES = libos.la liblog.la
+AM_CFLAGS = $(DIX_CFLAGS) $(SHA1_CFLAGS)
+SECURERPC_SRCS = rpcauth.c
+XDMCP_SRCS = xdmcp.c
+STRLCAT_SRCS = strlcat.c strlcpy.c
+
+# Build a convenience library liblog.la that will be added into
+# libos.la. The split is done so that log.c can be built with
+# different compiler options.
+liblog_la_SOURCES = log.c
+# Add flags needed for proper backtraces of functions marked with GCC
+# __attribute__((noreturn)). Currently those flags are needed for
+# FatalError and AbortServer in log.c.
+liblog_la_CFLAGS = $(AM_CFLAGS) $(ARM_BACKTRACE_CFLAGS)
+libos_la_SOURCES = WaitFor.c access.c auth.c backtrace.c connection.c \
+ io.c mitauth.c oscolor.c osdep.h osinit.c utils.c strcasecmp.c \
+ strcasestr.c xdmauth.c xsha1.c xstrans.c xprintf.c \
+ $(am__append_1) $(am__append_2) $(am__append_3)
+libos_la_LIBADD = @SHA1_LIBS@ $(DLOPEN_LIBS) liblog.la
+EXTRA_DIST = $(SECURERPC_SRCS) $(INTERNALMALLOC_SRCS) \
+ $(XDMCP_SRCS) $(STRLCAT_SRCS)
+
+CLEANFILES = os.c
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign os/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign os/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+liblog.la: $(liblog_la_OBJECTS) $(liblog_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(liblog_la_LINK) $(liblog_la_OBJECTS) $(liblog_la_LIBADD) $(LIBS)
+libos.la: $(libos_la_OBJECTS) $(libos_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(LINK) $(libos_la_OBJECTS) $(libos_la_LIBADD) $(LIBS)
+
+clean-noinstPROGRAMS:
+ @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+@SPECIAL_DTRACE_OBJECTS_FALSE@os.O$(EXEEXT): $(os_O_OBJECTS) $(os_O_DEPENDENCIES)
+@SPECIAL_DTRACE_OBJECTS_FALSE@ @rm -f os.O$(EXEEXT)
+@SPECIAL_DTRACE_OBJECTS_FALSE@ $(AM_V_CCLD)$(LINK) $(os_O_OBJECTS) $(os_O_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/WaitFor.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/access.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backtrace.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/connection.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/io.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblog_la-log.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mitauth.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/os.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oscolor.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osinit.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpcauth.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strcasecmp.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strcasestr.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strlcat.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strlcpy.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdmauth.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xdmcp.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xprintf.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xsha1.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xstrans.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+liblog_la-log.lo: log.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblog_la_CFLAGS) $(CFLAGS) -MT liblog_la-log.lo -MD -MP -MF $(DEPDIR)/liblog_la-log.Tpo -c -o liblog_la-log.lo `test -f 'log.c' || echo '$(srcdir)/'`log.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liblog_la-log.Tpo $(DEPDIR)/liblog_la-log.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='log.c' object='liblog_la-log.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblog_la_CFLAGS) $(CFLAGS) -c -o liblog_la-log.lo `test -f 'log.c' || echo '$(srcdir)/'`log.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-noinstPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-noinstPROGRAMS \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am
+
+
+# Generate dtrace object code for probes in libos & libdix
+@SPECIAL_DTRACE_OBJECTS_TRUE@dtrace.o: $(top_srcdir)/dix/Xserver.d $(am_libos_la_OBJECTS)
+@SPECIAL_DTRACE_OBJECTS_TRUE@ $(AM_V_GEN)$(DTRACE) -G -C -o $@ -s $(top_srcdir)/dix/Xserver.d .libs/*.o ../dix/.libs/*.o
+
+@SPECIAL_DTRACE_OBJECTS_TRUE@os.O: dtrace.o $(am_libos_la_OBJECTS)
+@SPECIAL_DTRACE_OBJECTS_TRUE@ $(AM_V_GEN)ld -r -o $@ dtrace.o .libs/*.o
+
+os.c:
+ touch $@
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/os/WaitFor.c b/os/WaitFor.c
new file mode 100644
index 0000000..867cb04
--- /dev/null
+++ b/os/WaitFor.c
@@ -0,0 +1,687 @@
+/***********************************************************
+
+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 <X11/Xwinsock.h>
+#endif
+#include <X11/Xos.h> /* for strings, fcntl, time */
+#include <errno.h>
+#include <stdio.h>
+#include <X11/X.h>
+#include "misc.h"
+
+#include "osdep.h"
+#include <X11/Xpoll.h>
+#include "dixstruct.h"
+#include "opaque.h"
+#ifdef DPMSExtension
+#include "dpmsproc.h"
+#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
+
+/* like ffs, but uses fd_mask instead of int as argument, so it works
+ when fd_mask is longer than an int, such as common 64-bit platforms */
+/* 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
+#include <X11/extensions/dpmsconst.h>
+#endif
+
+struct _OsTimerRec {
+ OsTimerPtr next;
+ CARD32 expires;
+ CARD32 delta;
+ OsTimerCallback callback;
+ pointer arg;
+};
+
+static void DoTimer(OsTimerPtr timer, CARD32 now, OsTimerPtr *prev);
+static void CheckAllTimers(void);
+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;
+ static int nready;
+ fd_set devicesReadable;
+ CARD32 now = 0;
+ Bool someReady = FALSE;
+
+ FD_ZERO(&clientsReadable);
+
+ if (nready)
+ SmartScheduleStopTimer();
+ nready = 0;
+
+ /* 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))
+ {
+ if (!SmartScheduleDisable)
+ {
+ someReady = TRUE;
+ waittime.tv_sec = 0;
+ waittime.tv_usec = 0;
+ wt = &waittime;
+ }
+ else
+ {
+ XFD_COPYSET (&ClientsWithInput, &clientsReadable);
+ break;
+ }
+ }
+ 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 > timers->delta + 250) {
+ /* time has rewound. reset the timers. */
+ CheckAllTimers();
+ }
+
+ if (timers) {
+ 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);
+ }
+
+ BlockHandler((pointer)&wt, (pointer)&LastSelectMask);
+ if (NewOutputPending)
+ FlushAllOutput();
+ /* keep this check close to select() call to minimize race */
+ if (dispatchException)
+ i = -1;
+ else if (AnyClientsWriteBlocked)
+ {
+ XFD_COPYSET(&ClientsWriteBlocked, &clientsWritable);
+ i = Select (MaxClients, &LastSelectMask, &clientsWritable, NULL, wt);
+ }
+ else
+ {
+ i = Select (MaxClients, &LastSelectMask, NULL, NULL, wt);
+ }
+ selecterr = GetErrno();
+ WakeupHandler(i, (pointer)&LastSelectMask);
+ if (i <= 0) /* An error or timeout occurred */
+ {
+ if (dispatchException)
+ return 0;
+ if (i < 0)
+ {
+ if (selecterr == EBADF) /* Some client disconnected */
+ {
+ CheckConnections ();
+ if (! XFD_ANYSET (&AllClients))
+ return 0;
+ }
+ else if (selecterr == EINVAL)
+ {
+ FatalError("WaitForSomething(): select: %s\n",
+ strerror(selecterr));
+ }
+ else if (selecterr != EINTR && selecterr != EAGAIN)
+ {
+ ErrorF("WaitForSomething(): select: %s\n",
+ strerror(selecterr));
+ }
+ }
+ else if (someReady)
+ {
+ /*
+ * If no-one else is home, bail quickly
+ */
+ XFD_COPYSET(&ClientsWithInput, &LastSelectMask);
+ XFD_COPYSET(&ClientsWithInput, &clientsReadable);
+ break;
+ }
+ if (*checkForInput[0] != *checkForInput[1])
+ return 0;
+
+ 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 (AnyClientsWriteBlocked && XFD_ANYSET (&clientsWritable))
+ {
+ NewOutputPending = TRUE;
+ XFD_ORSET(&OutputPending, &clientsWritable, &OutputPending);
+ XFD_UNSET(&ClientsWriteBlocked, &clientsWritable);
+ if (! XFD_ANYSET(&ClientsWriteBlocked))
+ AnyClientsWriteBlocked = FALSE;
+ }
+
+ XFD_ANDSET(&devicesReadable, &LastSelectMask, &EnabledDevices);
+ XFD_ANDSET(&clientsReadable, &LastSelectMask, &AllClients);
+ XFD_ANDSET(&tmp_set, &LastSelectMask, &WellKnownConnections);
+ if (XFD_ANYSET(&tmp_set))
+ QueueWorkProc(EstablishNewConnections, NULL,
+ (pointer)&LastSelectMask);
+
+ if (XFD_ANYSET (&devicesReadable) || XFD_ANYSET (&clientsReadable))
+ break;
+ /* check here for DDXes that queue events during Block/Wakeup */
+ if (*checkForInput[0] != *checkForInput[1])
+ return 0;
+ }
+ }
+
+ nready = 0;
+ if (XFD_ANYSET (&clientsReadable))
+ {
+#ifndef WIN32
+ for (i=0; i<howmany(XFD_SETSIZE, NFDBITS); i++)
+ {
+ int highest_priority = 0;
+
+ while (clientsReadable.fds_bits[i])
+ {
+ int client_priority, client_index;
+
+ curclient = mffs (clientsReadable.fds_bits[i]) - 1;
+ client_index = /* raphael: modified */
+ ConnectionTranslation[curclient + (i * (sizeof(fd_mask) * 8))];
+#else
+ int highest_priority = 0;
+ 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
+ /* We implement "strict" priorities.
+ * Only the highest priority client is returned to
+ * dix. If multiple clients at the same priority are
+ * ready, they are all returned. This means that an
+ * aggressive client could take over the server.
+ * This was not considered a big problem because
+ * aggressive clients can hose the server in so many
+ * other ways :)
+ */
+ client_priority = clients[client_index]->priority;
+ if (nready == 0 || client_priority > highest_priority)
+ {
+ /* Either we found the first client, or we found
+ * a client whose priority is greater than all others
+ * that have been found so far. Either way, we want
+ * to initialize the list of clients to contain just
+ * this client.
+ */
+ pClientsReady[0] = client_index;
+ highest_priority = client_priority;
+ nready = 1;
+ }
+ /* the following if makes sure that multiple same-priority
+ * clients get batched together
+ */
+ else if (client_priority == highest_priority)
+ {
+ pClientsReady[nready++] = client_index;
+ }
+#ifndef WIN32
+ clientsReadable.fds_bits[i] &= ~(((fd_mask)1L) << curclient);
+ }
+#else
+ FD_CLR(curclient, &clientsReadable);
+#endif
+ }
+ }
+
+ if (nready)
+ SmartScheduleStartTimer();
+
+ return nready;
+}
+
+/* If time has rewound, re-run every affected timer.
+ * Timers might drop out of the list, so we have to restart every time. */
+static void
+CheckAllTimers(void)
+{
+ OsTimerPtr timer;
+ CARD32 now;
+
+start:
+ now = GetTimeInMillis();
+
+ for (timer = timers; timer; timer = timer->next) {
+ if (timer->expires - now > timer->delta + 250) {
+ TimerForce(timer);
+ goto start;
+ }
+ }
+}
+
+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, pointer arg)
+{
+ register OsTimerPtr *prev;
+ CARD32 now = GetTimeInMillis();
+
+ if (!timer)
+ {
+ timer = 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) {
+ timer->delta = millis - now;
+ }
+ else {
+ timer->delta = millis;
+ 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);
+ }
+}
+
+#ifdef DPMSExtension
+
+#define DPMS_CHECK_MODE(mode,time)\
+ if (time > 0 && DPMSPowerLevel < mode && timeout >= time)\
+ DPMSSet(serverClient, mode);
+
+#define DPMS_CHECK_TIMEOUT(time)\
+ if (time > 0 && (time - timeout) > 0)\
+ return time - timeout;
+
+static CARD32
+NextDPMSTimeout(INT32 timeout)
+{
+ /*
+ * Return the amount of time remaining until we should set
+ * the next power level. Fallthroughs are intentional.
+ */
+ switch (DPMSPowerLevel)
+ {
+ case DPMSModeOn:
+ DPMS_CHECK_TIMEOUT(DPMSStandbyTime)
+
+ case DPMSModeStandby:
+ DPMS_CHECK_TIMEOUT(DPMSSuspendTime)
+
+ case DPMSModeSuspend:
+ DPMS_CHECK_TIMEOUT(DPMSOffTime)
+
+ default: /* DPMSModeOff */
+ return 0;
+ }
+}
+#endif /* DPMSExtension */
+
+static CARD32
+ScreenSaverTimeoutExpire(OsTimerPtr timer,CARD32 now,pointer arg)
+{
+ INT32 timeout = now - lastDeviceEventTime.milliseconds;
+ CARD32 nextTimeout = 0;
+
+#ifdef DPMSExtension
+ /*
+ * Check each mode lowest to highest, since a lower mode can
+ * have the same timeout as a higher one.
+ */
+ if (DPMSEnabled)
+ {
+ DPMS_CHECK_MODE(DPMSModeOff, DPMSOffTime)
+ DPMS_CHECK_MODE(DPMSModeSuspend, DPMSSuspendTime)
+ DPMS_CHECK_MODE(DPMSModeStandby, DPMSStandbyTime)
+
+ nextTimeout = NextDPMSTimeout(timeout);
+ }
+
+ /*
+ * Only do the screensaver checks if we're not in a DPMS
+ * power saving mode
+ */
+ if (DPMSPowerLevel != DPMSModeOn)
+ return nextTimeout;
+#endif /* DPMSExtension */
+
+ if (!ScreenSaverTime)
+ return nextTimeout;
+
+ if (timeout < ScreenSaverTime)
+ {
+ return nextTimeout > 0 ?
+ min(ScreenSaverTime - timeout, nextTimeout) :
+ ScreenSaverTime - timeout;
+ }
+
+ ResetOsBuffers(); /* not ideal, but better than nothing */
+ dixSaveScreens(serverClient, SCREEN_SAVER_ON, ScreenSaverActive);
+
+ if (ScreenSaverInterval > 0)
+ {
+ nextTimeout = nextTimeout > 0 ?
+ min(ScreenSaverInterval, nextTimeout) :
+ ScreenSaverInterval;
+ }
+
+ return nextTimeout;
+}
+
+static OsTimerPtr ScreenSaverTimer = NULL;
+
+void
+FreeScreenSaverTimer(void)
+{
+ if (ScreenSaverTimer) {
+ TimerFree(ScreenSaverTimer);
+ ScreenSaverTimer = NULL;
+ }
+}
+
+void
+SetScreenSaverTimer(void)
+{
+ CARD32 timeout = 0;
+
+#ifdef DPMSExtension
+ if (DPMSEnabled)
+ {
+ /*
+ * A higher DPMS level has a timeout that's either less
+ * than or equal to that of a lower DPMS level.
+ */
+ if (DPMSStandbyTime > 0)
+ timeout = DPMSStandbyTime;
+
+ else if (DPMSSuspendTime > 0)
+ timeout = DPMSSuspendTime;
+
+ else if (DPMSOffTime > 0)
+ timeout = DPMSOffTime;
+ }
+#endif
+
+ if (ScreenSaverTime > 0)
+ {
+ timeout = timeout > 0 ?
+ min(ScreenSaverTime, timeout) :
+ ScreenSaverTime;
+ }
+
+#ifdef SCREENSAVER
+ if (timeout && !screenSaverSuspended) {
+#else
+ if (timeout) {
+#endif
+ ScreenSaverTimer = TimerSet(ScreenSaverTimer, 0, timeout,
+ ScreenSaverTimeoutExpire, NULL);
+ }
+ else if (ScreenSaverTimer) {
+ FreeScreenSaverTimer();
+ }
+}
+
diff --git a/os/access.c b/os/access.c
new file mode 100644
index 0000000..be9c0d5
--- /dev/null
+++ b/os/access.c
@@ -0,0 +1,2095 @@
+/***********************************************************
+
+Copyright 1987, 1998 The Open Group
+
+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.
+
+******************************************************************/
+
+/*
+ * Copyright (c) 2004, 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 (including the next
+ * paragraph) 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.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifdef WIN32
+#include <X11/Xwinsock.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#define XSERV_t
+#define TRANS_SERVER
+#define TRANS_REOPEN
+#include <X11/Xtrans/Xtrans.h>
+#include <X11/Xauth.h>
+#include <X11/X.h>
+#include <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(STREAMSCONN)
+#include <netinet/in.h>
+#endif /* TCPCONN || STREAMSCONN */
+
+#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>
+#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
+
+
+#define X_INCLUDE_NETDB_H
+#include <X11/Xos_r.h>
+
+#include "dixstruct.h"
+#include "osdep.h"
+
+#include "xace.h"
+
+#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*/,
+ pointer * /*addr*/);
+
+static int CheckAddr(int /*family*/,
+ const void * /*pAddr*/,
+ unsigned /*length*/);
+
+static Bool NewHost(int /*family*/,
+ const 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)=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, pointer 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, (pointer)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(sun) && 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;
+
+ memset((char *) &ioc, 0, 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;
+ }
+ 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
+ return ret;
+}
+#else
+#define ifioctl ioctl
+#endif
+
+/*
+ * 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.
+ */
+
+#if !defined(SIOCGIFCONF)
+void
+DefineSelf (int fd)
+{
+#if !defined(TCPCONN) && !defined(STREAMSCONN) && !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, (pointer *)&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[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 && !STREAMSCONN && !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(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 *cp, *cplim;
+# ifdef USE_SIOCGLIFCONF
+ struct sockaddr_storage buf[16];
+ struct lifconf ifc;
+ register struct lifreq *ifr;
+# ifdef SIOCGLIFNUM
+ struct lifnum ifn;
+# endif
+# else /* !USE_SIOCGLIFCONF */
+ char buf[2048];
+ struct ifconf ifc;
+ register struct ifreq *ifr;
+# endif
+ void * bufptr = buf;
+#else /* HAS_GETIFADDRS */
+ 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
+#define IFC_IFC_REQ ifc.ifc_req
+#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, (pointer) &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, (pointer *)&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
+ 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, (pointer) &broad_req) != -1 &&
+ (broad_req.ifr_flags & IFF_BROADCAST) &&
+ (broad_req.ifr_flags & IFF_UP)
+ )
+ {
+ broad_req = *ifr;
+ if (ifioctl (fd, SIOCGIFBRDADDR, (pointer) &broad_req) != -1)
+ broad_addr = broad_req.ifr_addr;
+ else
+ continue;
+ }
+ else
+ continue;
+ }
+#endif /* SIOCGIFBRDADDR */
+ 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((struct sockaddr *) ifr->ifa_addr, &len,
+ (pointer *)&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
+
+ 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
+ {
+ /*
+ * 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) &&
+ ifr->ifa_broadaddr)
+ XdmcpRegisterBroadcastAddress(
+ (struct sockaddr_in *) ifr->ifa_broadaddr);
+ else
+ continue;
+ }
+#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 /* hpux && !HAS_IFREQ */
+
+#ifdef XDMCP
+void
+AugmentSelf(pointer from, int len)
+{
+ int family;
+ pointer addr;
+ register HOST *host;
+
+ family = ConvertAddr(from, &len, (pointer *)&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(STREAMSCONN) ) && \
+ (!defined(IPv6) || !defined(AF_INET6))
+ union {
+ struct sockaddr sa;
+#if defined(TCPCONN) || defined(STREAMSCONN)
+ struct sockaddr_in in;
+#endif /* TCPCONN || STREAMSCONN */
+ } saddr;
+#endif
+ int family = 0;
+ pointer addr;
+ int len;
+
+ siTypesInitialize();
+ AccessEnabled = defeatAccessControl ? FALSE : DEFAULT_ACCESS_CONTROL;
+ LocalHostEnabled = FALSE;
+ while ((host = validhosts) != 0)
+ {
+ validhosts = host->next;
+ FreeHost (host);
+ }
+
+#if defined WIN32 && defined __MINGW32__
+#define ETC_HOST_PREFIX "X"
+#else
+#define ETC_HOST_PREFIX "/etc/X"
+#endif
+#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);
+ snprintf(fname, sizeof(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) || defined(STREAMSCONN)
+ 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) || defined(STREAMSCONN)
+ {
+#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,(pointer *)&addr);
+ if ( (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, (pointer *)&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, (pointer)*list, len, FALSE);
+#else
+ (void) NewHost (family, (pointer)hp->h_addr, len, FALSE);
+#endif
+ }
+ }
+#endif /* IPv6 */
+ }
+#endif /* TCPCONN || STREAMSCONN */
+ family = FamilyWild;
+ }
+ fclose (fd);
+ }
+}
+
+/* Is client on the local host */
+Bool
+ComputeLocalClient(ClientPtr client)
+{
+ int alen, family, notused;
+ Xtransaddr *from = NULL;
+ pointer addr;
+ register HOST *host;
+ OsCommPtr oc = (OsCommPtr) client->osPrivate;
+
+ if (!oc->trans_conn)
+ return FALSE;
+
+ if (!_XSERVTransGetPeerAddr (oc->trans_conn, &notused, &alen, &from))
+ {
+ family = ConvertAddr ((struct sockaddr *) from,
+ &alen, (pointer *)&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;
+}
+
+Bool LocalClient(ClientPtr client)
+{
+ if (!client->osPrivate)
+ return FALSE;
+ return ((OsCommPtr)client->osPrivate)->local_client;
+}
+
+/*
+ * 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 who 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 int
+AuthorizedClient(ClientPtr client)
+{
+ int rc;
+
+ if (!client || defeatAccessControl)
+ return Success;
+
+ /* untrusted clients can't change host access */
+ rc = XaceHook(XACE_SERVER_ACCESS, client, DixManageAccess);
+ if (rc != Success)
+ return rc;
+
+ return LocalClient(client) ? 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 */
+ const void * pAddr)
+{
+ int rc, len;
+
+ rc = AuthorizedClient(client);
+ if (rc != Success)
+ return rc;
+ 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 FamilyDECnet:
+ 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 */,
+ pointer /* closure */),
+ pointer 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,
+ const 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 */
+ pointer pAddr)
+{
+ int rc, len;
+ register HOST *host, **prev;
+
+ rc = AuthorizedClient(client);
+ if (rc != Success)
+ return rc;
+ 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 FamilyDECnet:
+ 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 (
+ pointer *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 += pad_to_int32(host->len) + sizeof(xHostEntry);
+ }
+ if (n)
+ {
+ *data = ptr = malloc(n);
+ if (!ptr)
+ {
+ return BadAlloc;
+ }
+ for (host = validhosts; host; host = host->next)
+ {
+ len = host->len;
+ ((xHostEntry *)ptr)->family = host->family;
+ ((xHostEntry *)ptr)->length = len;
+ ptr += sizeof(xHostEntry);
+ acopy (host->addr, ptr, len);
+ ptr += pad_to_int32(len);
+ }
+ } 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,
+ const void * pAddr,
+ unsigned length)
+{
+ int len;
+
+ switch (family)
+ {
+#if defined(TCPCONN) || defined(STREAMSCONN)
+ 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;
+ pointer addr;
+ register HOST *selfhost, *host;
+
+ if (!AccessEnabled) /* just let them in */
+ return 0;
+ family = ConvertAddr (saddr, &len, (pointer *)&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 (addrEqual (family, addr, len, host))
+ return 0;
+ }
+
+ }
+ return 1;
+}
+
+static int
+ConvertAddr (
+ register struct sockaddr *saddr,
+ int *len,
+ pointer *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) || defined(STREAMSCONN)
+ case AF_INET:
+#ifdef WIN32
+ if (16777343 == *(long*)&((struct sockaddr_in *) saddr)->sin_addr)
+ return FamilyLocal;
+#endif
+ *len = sizeof (struct in_addr);
+ *addr = (pointer) &(((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 = (pointer) &(saddr6->sin6_addr.s6_addr[12]);
+ return FamilyInternet;
+ } else {
+ *len = sizeof (struct in6_addr);
+ *addr = (pointer) &(saddr6->sin6_addr);
+ return FamilyInternet6;
+ }
+ }
+#endif
+#endif
+ default:
+ return -1;
+ }
+}
+
+int
+ChangeAccessControl(
+ ClientPtr client,
+ int fEnabled)
+{
+ int rc = AuthorizedClient(client);
+ if (rc != Success)
+ return rc;
+ 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, pointer 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 = 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, pointer 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, pointer 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;
+ pointer hostaddr;
+
+ 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) &&
+ (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;
+ pointer 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, pointer 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, pointer 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/os/auth.c b/os/auth.c
new file mode 100644
index 0000000..7685751
--- /dev/null
+++ b/os/auth.c
@@ -0,0 +1,328 @@
+/*
+
+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 <X11/X.h>
+# include <X11/Xauth.h>
+# include "misc.h"
+# include "osdep.h"
+# include "dixstruct.h"
+# include <sys/types.h>
+# include <sys/stat.h>
+#ifdef WIN32
+#include <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
+};
+
+# 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)
+{
+ authorization_file = file_name;
+}
+
+static int
+LoadAuthorization (void)
+{
+ FILE *f;
+ Xauth *auth;
+ int i;
+ int count = 0;
+
+ ShouldLoadAuth = FALSE;
+ if (!authorization_file)
+ return 0;
+
+ 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)
+ {
+ ++count;
+ (*protocols[i].Add) (auth->data_length, auth->data,
+ FakeClientID(0));
+ }
+ }
+ XauDisposeAuth (auth);
+ }
+
+ Fclose (f);
+ 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,
+ const char *name,
+ unsigned int data_length,
+ const char *data,
+ ClientPtr client,
+ char **reason) /* failure message. NULL for default msg */
+{
+ int i;
+ struct stat buf;
+ static time_t lastmod = 0;
+ static Bool loaded = FALSE;
+
+ 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)
+ */
+
+ if (loadauth > 0)
+ {
+ DisableLocalHost(); /* got at least one */
+ loaded = TRUE;
+ }
+ else if (loadauth == 0 || !loaded)
+ EnableLocalHost ();
+ }
+ 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;
+}
+
+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,
+ const char *name,
+ unsigned short data_length,
+ const 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, const 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,
+ const char *name,
+ unsigned data_length,
+ const 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;
+}
+
+void
+GenerateRandomData (int len, char *buf)
+{
+ int fd;
+
+ fd = open("/dev/urandom", O_RDONLY);
+ read(fd, buf, len);
+ close(fd);
+}
+
+#endif /* XCSECURITY */
diff --git a/os/backtrace.c b/os/backtrace.c
new file mode 100644
index 0000000..7ca6dab
--- /dev/null
+++ b/os/backtrace.c
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2008 Red Hat, 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 (including the next
+ * paragraph) 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.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "os.h"
+#include "misc.h"
+
+#ifdef HAVE_BACKTRACE
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include <dlfcn.h>
+#include <execinfo.h>
+
+void xorg_backtrace(void)
+{
+ void *array[64];
+ const char *mod;
+ int size, i;
+ Dl_info info;
+ ErrorF("\nBacktrace:\n");
+ size = backtrace(array, 64);
+ for (i = 0; i < size; i++) {
+ dladdr(array[i], &info);
+ mod = (info.dli_fname && *info.dli_fname) ? info.dli_fname : "(vdso)";
+ if (info.dli_saddr)
+ ErrorF("%d: %s (%s+0x%lx) [%p]\n", i, mod,
+ info.dli_sname, (long unsigned int)((char *) array[i] - (char *) info.dli_saddr), array[i]);
+ else
+ ErrorF("%d: %s (%p+0x%lx) [%p]\n", i, mod,
+ info.dli_fbase, (long unsigned int)((char *) array[i] - (char *) info.dli_fbase), array[i]);
+ }
+}
+
+#else /* not glibc or glibc < 2.1 */
+
+# if defined(sun) && defined(__SVR4)
+# define HAVE_PSTACK
+# endif
+
+# if defined(HAVE_WALKCONTEXT) /* Solaris 9 & later */
+
+# include <ucontext.h>
+# include <signal.h>
+# include <dlfcn.h>
+# include <sys/elf.h>
+
+#ifdef _LP64
+# define ElfSym Elf64_Sym
+#else
+# define ElfSym Elf32_Sym
+#endif
+
+/* Called for each frame on the stack to print it's contents */
+static int xorg_backtrace_frame(uintptr_t pc, int signo, void *arg)
+{
+ Dl_info dlinfo;
+ ElfSym *dlsym;
+ char header[32];
+ int depth = *((int *) arg);
+
+ if (signo) {
+ char signame[SIG2STR_MAX];
+
+ if (sig2str(signo, signame) != 0) {
+ strcpy(signame, "unknown");
+ }
+
+ ErrorF("** Signal %d (%s)\n", signo, signame);
+ }
+
+ snprintf(header, sizeof(header), "%d: 0x%lx", depth, pc);
+ *((int *) arg) = depth + 1;
+
+ /* Ask system dynamic loader for info on the address */
+ if (dladdr1((void *) pc, &dlinfo, (void **) &dlsym, RTLD_DL_SYMENT)) {
+ unsigned long offset = pc - (uintptr_t) dlinfo.dli_saddr;
+ const char *symname;
+
+ if (offset < dlsym->st_size) { /* inside a function */
+ symname = dlinfo.dli_sname;
+ } else { /* found which file it was in, but not which function */
+ symname = "<section start>";
+ offset = pc - (uintptr_t)dlinfo.dli_fbase;
+ }
+ ErrorF("%s: %s:%s+0x%lx\n", header, dlinfo.dli_fname,
+ symname, offset);
+
+ } else {
+ /* Couldn't find symbol info from system dynamic loader, should
+ * probably poke elfloader here, but haven't written that code yet,
+ * so we just print the pc.
+ */
+ ErrorF("%s\n", header);
+ }
+
+ return 0;
+}
+# endif /* HAVE_WALKCONTEXT */
+
+# ifdef HAVE_PSTACK
+static int xorg_backtrace_pstack(void) {
+ pid_t kidpid;
+ int pipefd[2];
+
+ if (pipe(pipefd) != 0) {
+ return -1;
+ }
+
+ kidpid = fork1();
+
+ if (kidpid == -1) {
+ /* ERROR */
+ return -1;
+ } else if (kidpid == 0) {
+ /* CHILD */
+ char parent[16];
+
+ seteuid(0);
+ close(STDIN_FILENO);
+ close(STDOUT_FILENO);
+ dup2(pipefd[1],STDOUT_FILENO);
+ closefrom(STDERR_FILENO);
+
+ snprintf(parent, sizeof(parent), "%d", getppid());
+ execle("/usr/bin/pstack", "pstack", parent, NULL);
+ exit(1);
+ } else {
+ /* PARENT */
+ char btline[256];
+ int kidstat;
+ int bytesread;
+ int done = 0;
+
+ close(pipefd[1]);
+
+ while (!done) {
+ bytesread = read(pipefd[0], btline, sizeof(btline) - 1);
+
+ if (bytesread > 0) {
+ btline[bytesread] = 0;
+ ErrorF("%s", btline);
+ }
+ else if ((bytesread < 0) ||
+ ((errno != EINTR) && (errno != EAGAIN)))
+ done = 1;
+ }
+ close(pipefd[0]);
+ waitpid(kidpid, &kidstat, 0);
+ if (kidstat != 0)
+ return -1;
+ }
+ return 0;
+}
+# endif /* HAVE_PSTACK */
+
+
+# if defined(HAVE_PSTACK) || defined(HAVE_WALKCONTEXT)
+
+void xorg_backtrace(void) {
+
+ ErrorF("\nBacktrace:\n");
+
+# ifdef HAVE_PSTACK
+/* First try fork/exec of pstack - otherwise fall back to walkcontext
+ pstack is preferred since it can print names of non-exported functions */
+
+ if (xorg_backtrace_pstack() < 0)
+# endif
+ {
+# ifdef HAVE_WALKCONTEXT
+ ucontext_t u;
+ int depth = 1;
+
+ if (getcontext(&u) == 0)
+ walkcontext(&u, xorg_backtrace_frame, &depth);
+ else
+# endif
+ Error("Failed to get backtrace info");
+ }
+ ErrorF("\n");
+}
+
+# else
+
+/* Default fallback if we can't find any way to get a backtrace */
+void xorg_backtrace(void) { return; }
+
+# endif
+#endif
diff --git a/os/connection.c b/os/connection.c
new file mode 100644
index 0000000..5580fab
--- /dev/null
+++ b/os/connection.c
@@ -0,0 +1,1308 @@
+/***********************************************************
+
+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, AddEnabledDevice,
+ * RemoveEnabledDevice, 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 <X11/Xwinsock.h>
+#endif
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#define XSERV_t
+#define TRANS_SERVER
+#define TRANS_REOPEN
+#include <X11/Xtrans/Xtrans.h>
+#include <X11/Xtrans/Xtransint.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef WIN32
+#include <sys/socket.h>
+
+
+
+#if defined(TCPCONN) || defined(STREAMSCONN)
+# include <netinet/in.h>
+# include <arpa/inet.h>
+# ifdef apollo
+# ifndef NO_TCP_H
+# include <netinet/tcp.h>
+# endif
+# else
+# ifdef CSRG_BASED
+# include <sys/param.h>
+# endif
+# include <netinet/tcp.h>
+# endif
+# include <arpa/inet.h>
+#endif
+
+#include <sys/uio.h>
+
+#endif /* WIN32 */
+#include "misc.h" /* for typedef of pointer */
+#include "osdep.h"
+#include <X11/Xpoll.h>
+#include "opaque.h"
+#include "dixstruct.h"
+#include "xace.h"
+
+#define Pid_t pid_t
+
+
+#ifdef HAS_GETPEERUCRED
+# include <ucred.h>
+# include <zone.h>
+#endif
+
+#ifdef XSERVER_DTRACE
+# include <sys/types.h>
+typedef const char *string;
+# ifndef HAS_GETPEERUCRED
+# define zoneid_t int
+# endif
+# include "../dix/Xserver-dtrace.h"
+#endif
+
+static int lastfdesc; /* maximum file descriptor */
+
+fd_set WellKnownConnections; /* Listener mask */
+fd_set EnabledDevices; /* mask for input devices that are on */
+fd_set AllSockets; /* select on this */
+fd_set AllClients; /* available clients */
+fd_set LastSelectMask; /* 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;
+Bool NewOutputPending; /* not yet attempted to write some new output */
+Bool AnyClientsWriteBlocked; /* true if some client blocked on write */
+
+static Bool RunFromSmartParent; /* send SIGUSR1 to parent process */
+Bool RunFromSigStopParent; /* send SIGSTOP to our own process; Upstart (or
+ equivalent) will send SIGCONT back. */
+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;
+
+#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
+
+struct _ct_node {
+ struct _ct_node *next;
+ int key;
+ int value;
+};
+
+struct _ct_node *ct_head[256];
+
+void InitConnectionTranslation(void)
+{
+ memset(ct_head, 0, sizeof(ct_head));
+}
+
+int GetConnectionTranslation(int conn)
+{
+ struct _ct_node *node = ct_head[conn & 0xff];
+ while (node != NULL)
+ {
+ if (node->key == conn)
+ return node->value;
+ node = node->next;
+ }
+ return 0;
+}
+
+void SetConnectionTranslation(int conn, int client)
+{
+ struct _ct_node **node = ct_head + (conn & 0xff);
+ if (client == 0) /* 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 = malloc(sizeof(struct _ct_node));
+ (*node)->next = NULL;
+ (*node)->key = conn;
+ (*node)->value = client;
+ return;
+ }
+}
+
+void ClearConnectionTranslation(void)
+{
+ unsigned i;
+ for (i = 0; i < 256; i++)
+ {
+ struct _ct_node *node = ct_head[i];
+ while (node != NULL)
+ {
+ struct _ct_node *temp = node;
+ node = node->next;
+ free(temp);
+ }
+ }
+}
+#endif
+
+static XtransConnInfo *ListenTransConns = NULL;
+static int *ListenTransFds = NULL;
+static int ListenTransCount;
+
+static void ErrorConnMax(XtransConnInfo /* trans_conn */);
+
+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)
+ if (!ConnectionTranslation)
+ 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 ();
+#endif
+}
+
+void
+NotifyParentProcess(void)
+{
+#if !defined(WIN32)
+ if (RunFromSmartParent) {
+ if (ParentProcess > 1) {
+ kill (ParentProcess, SIGUSR1);
+ }
+ }
+ if (RunFromSigStopParent)
+ raise (SIGSTOP);
+#endif
+}
+
+/*****************
+ * CreateWellKnownSockets
+ * At initialization, create the sockets to listen on for new clients.
+ *****************/
+
+void
+CreateWellKnownSockets(void)
+{
+ int i;
+ int partial;
+ char port[20];
+
+ FD_ZERO(&AllSockets);
+ FD_ZERO(&AllClients);
+ FD_ZERO(&LastSelectMask);
+ FD_ZERO(&ClientsWithInput);
+
+#if !defined(WIN32)
+ for (i=0; i<MaxClients; i++) ConnectionTranslation[i] = 0;
+#else
+ ClearConnectionTranslation();
+#endif
+
+ FD_ZERO (&WellKnownConnections);
+
+ sprintf (port, "%d", atoi (display));
+
+ if ((_XSERVTransMakeAllCOTSServerListeners (port, &partial,
+ &ListenTransCount, &ListenTransConns) >= 0) &&
+ (ListenTransCount >= 1))
+ {
+ if (!PartialNetwork && partial)
+ {
+ FatalError ("Failed to establish all listening sockets");
+ }
+ else
+ {
+ ListenTransFds = malloc(ListenTransCount * sizeof (int));
+
+ for (i = 0; i < ListenTransCount; i++)
+ {
+ int fd = _XSERVTransGetConnectionNumber (ListenTransConns[i]);
+
+ ListenTransFds[i] = fd;
+ FD_SET (fd, &WellKnownConnections);
+
+ if (!_XSERVTransIsLocal (ListenTransConns[i]))
+ {
+ DefineSelf (fd);
+ }
+ }
+ }
+ }
+
+ if (!XFD_ANYSET (&WellKnownConnections))
+ FatalError ("Cannot establish any listening sockets - Make sure an X server isn't already running");
+#if !defined(WIN32)
+ OsSignal (SIGPIPE, SIG_IGN);
+ OsSignal (SIGHUP, AutoResetServer);
+#endif
+ OsSignal (SIGINT, GiveUp);
+ OsSignal (SIGTERM, GiveUp);
+ XFD_COPYSET (&WellKnownConnections, &AllSockets);
+ ResetHosts(display);
+
+ InitParentProcess();
+
+#ifdef XDMCP
+ XdmcpInit ();
+#endif
+}
+
+void
+ResetWellKnownSockets (void)
+{
+ int i;
+
+ ResetOsBuffers();
+
+ for (i = 0; i < ListenTransCount; i++)
+ {
+ int status = _XSERVTransResetListener (ListenTransConns[i]);
+
+ if (status != TRANS_RESET_NOOP)
+ {
+ if (status == TRANS_RESET_FAILURE)
+ {
+ /*
+ * ListenTransConns[i] freed by xtrans.
+ * Remove it from out list.
+ */
+
+ FD_CLR (ListenTransFds[i], &WellKnownConnections);
+ ListenTransFds[i] = ListenTransFds[ListenTransCount - 1];
+ ListenTransConns[i] = ListenTransConns[ListenTransCount - 1];
+ ListenTransCount -= 1;
+ i -= 1;
+ }
+ else if (status == TRANS_RESET_NEW_FD)
+ {
+ /*
+ * A new file descriptor was allocated (the old one was closed)
+ */
+
+ int newfd = _XSERVTransGetConnectionNumber (ListenTransConns[i]);
+
+ FD_CLR (ListenTransFds[i], &WellKnownConnections);
+ ListenTransFds[i] = newfd;
+ FD_SET(newfd, &WellKnownConnections);
+ }
+ }
+ }
+
+ ResetAuthorization ();
+ ResetHosts(display);
+ /*
+ * restart XDMCP
+ */
+#ifdef XDMCP
+ XdmcpReset ();
+#endif
+}
+
+void
+CloseWellKnownConnections(void)
+{
+ int i;
+
+ for (i = 0; i < ListenTransCount; i++)
+ _XSERVTransClose (ListenTransConns[i]);
+}
+
+static void
+AuthAudit (ClientPtr client, Bool letin,
+ struct sockaddr *saddr, int len,
+ unsigned int proto_n, char *auth_proto, int auth_id)
+{
+ char addr[128];
+ char *out = addr;
+ char client_uid_string[64];
+ LocalClientCredRec *lcc;
+#ifdef XSERVER_DTRACE
+ pid_t client_pid = -1;
+ zoneid_t client_zid = -1;
+#endif
+
+ if (!len)
+ strcpy(out, "local host");
+ else
+ switch (saddr->sa_family)
+ {
+ case AF_UNSPEC:
+#if defined(UNIXCONN) || defined(LOCALCONN)
+ case AF_UNIX:
+#endif
+ strcpy(out, "local host");
+ break;
+#if defined(TCPCONN) || defined(STREAMSCONN)
+ case AF_INET:
+ sprintf(out, "IP %s",
+ inet_ntoa(((struct sockaddr_in *) saddr)->sin_addr));
+ break;
+#if defined(IPv6) && defined(AF_INET6)
+ case AF_INET6: {
+ char ipaddr[INET6_ADDRSTRLEN];
+ inet_ntop(AF_INET6, &((struct sockaddr_in6 *) saddr)->sin6_addr,
+ ipaddr, sizeof(ipaddr));
+ sprintf(out, "IP %s", ipaddr);
+ }
+ break;
+#endif
+#endif
+ default:
+ strcpy(out, "unknown address");
+ }
+
+ if (GetLocalClientCreds(client, &lcc) != -1) {
+ int slen; /* 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) {
+#ifdef XSERVER_DTRACE
+ client_pid = lcc->pid;
+#endif
+ snprintf(client_uid_string + slen,
+ sizeof(client_uid_string) - slen,
+ "pid=%ld ", (long) lcc->pid);
+ slen = strlen(client_uid_string);
+ }
+
+ if (lcc->fieldsSet & LCC_ZID_SET) {
+#ifdef XSERVER_DTRACE
+ client_zid = lcc->zoneid;
+#endif
+ snprintf(client_uid_string + slen,
+ sizeof(client_uid_string) - slen,
+ "zoneid=%ld ", (long) lcc->zoneid);
+ slen = strlen(client_uid_string);
+ }
+
+ snprintf(client_uid_string + slen, sizeof(client_uid_string) - slen,
+ ")");
+ FreeLocalClientCreds(lcc);
+ }
+ else {
+ client_uid_string[0] = '\0';
+ }
+
+#ifdef XSERVER_DTRACE
+ XSERVER_CLIENT_AUTH(client->index, addr, client_pid, client_zid);
+#endif
+ if (auditTrailLevel > 1) {
+ if (proto_n)
+ AuditF("client %d %s from %s%s\n Auth name: %.*s ID: %d\n",
+ client->index, letin ? "connected" : "rejected", addr,
+ client_uid_string, (int)proto_n, auth_proto, auth_id);
+ else
+ AuditF("client %d %s from %s%s\n",
+ client->index, letin ? "connected" : "rejected", addr,
+ client_uid_string);
+
+ }
+}
+
+XID
+AuthorizationIDOfClient(ClientPtr client)
+{
+ if (client->osPrivate)
+ return ((OsCommPtr)client->osPrivate)->auth_id;
+ else
+ return None;
+}
+
+
+/*****************************************************************
+ * 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;
+
+ /* Allow any client to connect without authorization on a launchd socket,
+ because it is securely created -- this prevents a race condition on launch */
+ if(trans_conn->flags & TRANS_NOXAUTH) {
+ auth_id = (XID) 0L;
+ } else {
+ auth_id = CheckAuthorization (proto_n, auth_proto, string_n, auth_string, client, &reason);
+ }
+
+ if (auth_id == (XID) ~0L)
+ {
+ if (_XSERVTransGetPeerAddr(trans_conn, &family, &fromlen, &from) != -1)
+ {
+ if (InvalidHost ((struct sockaddr *) from, fromlen, client))
+ AuthAudit(client, FALSE, (struct sockaddr *) from,
+ fromlen, proto_n, auth_proto, auth_id);
+ else
+ {
+ auth_id = (XID) 0;
+#ifdef XSERVER_DTRACE
+ if ((auditTrailLevel > 1) || XSERVER_CLIENT_AUTH_ENABLED())
+#else
+ if (auditTrailLevel > 1)
+#endif
+ AuthAudit(client, TRUE,
+ (struct sockaddr *) from, fromlen,
+ proto_n, auth_proto, auth_id);
+ }
+
+ free(from);
+ }
+
+ if (auth_id == (XID) ~0L) {
+ if (reason)
+ return reason;
+ else
+ return "Client is not authorized to connect to Server";
+ }
+ }
+#ifdef XSERVER_DTRACE
+ else if ((auditTrailLevel > 1) || XSERVER_CLIENT_AUTH_ENABLED())
+#else
+ else if (auditTrailLevel > 1)
+#endif
+ {
+ if (_XSERVTransGetPeerAddr (trans_conn,
+ &family, &fromlen, &from) != -1)
+ {
+ AuthAudit(client, TRUE, (struct sockaddr *) from, fromlen,
+ proto_n, auth_proto, auth_id);
+
+ free(from);
+ }
+ }
+ priv->auth_id = auth_id;
+ priv->conn_time = 0;
+
+#ifdef XDMCP
+ /* indicate to Xdmcp protocol that we've opened new client */
+ XdmcpOpenDisplay(priv->fd);
+#endif /* XDMCP */
+
+ XaceHook(XACE_AUTH_AVAIL, client, auth_id);
+
+ /* 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 = malloc(sizeof(OsCommRec));
+ if (!oc)
+ return NullClient;
+ oc->trans_conn = trans_conn;
+ oc->fd = fd;
+ oc->input = (ConnectionInputPtr)NULL;
+ oc->output = (ConnectionOutputPtr)NULL;
+ oc->auth_id = None;
+ oc->conn_time = conn_time;
+ if (!(client = NextAvailableClient((pointer)oc)))
+ {
+ free(oc);
+ return NullClient;
+ }
+ oc->local_client = ComputeLocalClient(client);
+#if !defined(WIN32)
+ ConnectionTranslation[fd] = client->index;
+#else
+ SetConnectionTranslation(fd, client->index);
+#endif
+ if (GrabInProgress)
+ {
+ FD_SET(fd, &SavedAllClients);
+ FD_SET(fd, &SavedAllSockets);
+ }
+ else
+ {
+ FD_SET(fd, &AllClients);
+ FD_SET(fd, &AllSockets);
+ }
+
+#ifdef DEBUG
+ ErrorF("AllocNewConnection: client index = %d, socket fd = %d\n",
+ client->index, fd);
+#endif
+#ifdef XSERVER_DTRACE
+ XSERVER_CLIENT_CONNECT(client->index, fd);
+#endif
+
+ return client;
+}
+
+/*****************
+ * EstablishNewConnections
+ * If anyone is waiting on listened sockets, accept them.
+ * Returns a mask with indices of new clients. Updates AllClients
+ * and AllSockets.
+ *****************/
+
+/*ARGSUSED*/
+Bool
+EstablishNewConnections(ClientPtr clientUnused, pointer closure)
+{
+ fd_set readyconnections; /* set of listeners that are ready */
+ int curconn; /* fd of listener that's ready */
+ register int newconn; /* fd of new client */
+ CARD32 connect_time;
+ register int i;
+ register ClientPtr client;
+ register OsCommPtr oc;
+ fd_set tmask;
+
+ XFD_ANDSET (&tmask, (fd_set*)closure, &WellKnownConnections);
+ XFD_COPYSET(&tmask, &readyconnections);
+ if (!XFD_ANYSET(&readyconnections))
+ return TRUE;
+ connect_time = GetTimeInMillis();
+ /* 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);
+ }
+ }
+#ifndef WIN32
+ for (i = 0; i < howmany(XFD_SETSIZE, NFDBITS); i++)
+ {
+ while (readyconnections.fds_bits[i])
+#else
+ for (i = 0; i < XFD_SETCOUNT(&readyconnections); i++)
+#endif
+ {
+ XtransConnInfo trans_conn, new_trans_conn;
+ int status;
+
+#ifndef WIN32
+ curconn = mffs (readyconnections.fds_bits[i]) - 1;
+ readyconnections.fds_bits[i] &= ~((fd_mask)1 << curconn);
+ curconn += (i * (sizeof(fd_mask)*8));
+#else
+ curconn = XFD_FD(&readyconnections, i);
+#endif
+
+ if ((trans_conn = lookup_trans_conn (curconn)) == NULL)
+ continue;
+
+ if ((new_trans_conn = _XSERVTransAccept (trans_conn, &status)) == NULL)
+ continue;
+
+ newconn = _XSERVTransGetConnectionNumber (new_trans_conn);
+
+ if (newconn < lastfdesc)
+ {
+ int clientid;
+#if !defined(WIN32)
+ clientid = ConnectionTranslation[newconn];
+#else
+ clientid = GetConnectionTranslation(newconn);
+#endif
+ if(clientid && (client = clients[clientid]))
+ CloseDownClient(client);
+ }
+
+ _XSERVTransSetOption(new_trans_conn, TRANS_NONBLOCKING, 1);
+
+ if (!AllocNewConnection (new_trans_conn, newconn, connect_time))
+ {
+ ErrorConnMax(new_trans_conn);
+ _XSERVTransClose(new_trans_conn);
+ }
+
+ if(trans_conn->flags & TRANS_NOXAUTH)
+ new_trans_conn->flags = new_trans_conn->flags | TRANS_NOXAUTH;
+
+ }
+#ifndef WIN32
+ }
+#endif
+ return TRUE;
+}
+
+#define NOROOM "Maximum number of clients reached"
+
+/************
+ * ErrorConnMax
+ * Fail a connection due to lack of client or file descriptor space
+ ************/
+
+static void
+ErrorConnMax(XtransConnInfo trans_conn)
+{
+ int fd = _XSERVTransGetConnectionNumber (trans_conn);
+ xConnSetupPrefix csp;
+ char pad[3];
+ struct iovec iov[3];
+ char byteOrder = 0;
+ int whichbyte = 1;
+ struct timeval waittime;
+ fd_set mask;
+
+ /* if these seems like a lot of trouble to go to, it probably is */
+ waittime.tv_sec = BOTIMEOUT / MILLI_PER_SECOND;
+ waittime.tv_usec = (BOTIMEOUT % MILLI_PER_SECOND) *
+ (1000000 / MILLI_PER_SECOND);
+ FD_ZERO(&mask);
+ FD_SET(fd, &mask);
+ (void)Select(fd + 1, &mask, NULL, NULL, &waittime);
+ /* try to read the byte-order of the connection */
+ (void)_XSERVTransRead(trans_conn, &byteOrder, 1);
+ if ((byteOrder == 'l') || (byteOrder == 'B'))
+ {
+ csp.success = xFalse;
+ csp.lengthReason = sizeof(NOROOM) - 1;
+ csp.length = (sizeof(NOROOM) + 2) >> 2;
+ csp.majorVersion = X_PROTOCOL;
+ csp.minorVersion = X_PROTOCOL_REVISION;
+ if (((*(char *) &whichbyte) && (byteOrder == 'B')) ||
+ (!(*(char *) &whichbyte) && (byteOrder == 'l')))
+ {
+ swaps(&csp.majorVersion, whichbyte);
+ swaps(&csp.minorVersion, whichbyte);
+ swaps(&csp.length, whichbyte);
+ }
+ iov[0].iov_len = sz_xConnSetupPrefix;
+ iov[0].iov_base = (char *) &csp;
+ iov[1].iov_len = csp.lengthReason;
+ iov[1].iov_base = NOROOM;
+ iov[2].iov_len = (4 - (csp.lengthReason & 3)) & 3;
+ iov[2].iov_base = pad;
+ (void)_XSERVTransWritev(trans_conn, iov, 3);
+ }
+}
+
+/************
+ * 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);
+ }
+#ifndef WIN32
+ ConnectionTranslation[connection] = 0;
+#else
+ SetConnectionTranslation(connection, 0);
+#endif
+ FD_CLR(connection, &AllSockets);
+ FD_CLR(connection, &AllClients);
+ FD_CLR(connection, &ClientsWithInput);
+ FD_CLR(connection, &GrabImperviousClients);
+ if (GrabInProgress)
+ {
+ FD_CLR(connection, &SavedAllSockets);
+ FD_CLR(connection, &SavedAllClients);
+ FD_CLR(connection, &SavedClientsWithInput);
+ }
+ FD_CLR(connection, &ClientsWriteBlocked);
+ if (!XFD_ANYSET(&ClientsWriteBlocked))
+ AnyClientsWriteBlocked = FALSE;
+ FD_CLR(connection, &OutputPending);
+}
+
+/*****************
+ * 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 = mffs (mask) - 1;
+ curclient = curoff + (i * (sizeof(fd_mask)*8));
+ FD_ZERO(&tmask);
+ FD_SET(curclient, &tmask);
+ do {
+ r = Select (curclient + 1, &tmask, NULL, NULL, &notime);
+ } while (r < 0 && (errno == EINTR || errno == EAGAIN));
+ if (r < 0)
+ if (ConnectionTranslation[curclient] > 0)
+ CloseDownClient(clients[ConnectionTranslation[curclient]]);
+ mask &= ~((fd_mask)1 << curoff);
+ }
+ }
+#else
+ XFD_COPYSET(&AllClients, &savedAllClients);
+ for (i = 0; i < XFD_SETCOUNT(&savedAllClients); i++)
+ {
+ curclient = XFD_FD(&savedAllClients, i);
+ FD_ZERO(&tmask);
+ FD_SET(curclient, &tmask);
+ do {
+ r = Select (curclient + 1, &tmask, NULL, NULL, &notime);
+ } while (r < 0 && (errno == EINTR || errno == EAGAIN));
+ if (r < 0)
+ if (GetConnectionTranslation(curclient) > 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, NULL);
+
+ if (oc->output && oc->output->count)
+ FlushClient(client, oc, (char *)NULL, 0);
+#ifdef XDMCP
+ XdmcpCloseDisplay(oc->fd);
+#endif
+ CloseDownFileDescriptor(oc);
+ FreeOsBuffers(oc);
+ free(client->osPrivate);
+ client->osPrivate = (pointer)NULL;
+ if (auditTrailLevel > 1)
+ AuditF("client %d disconnected\n", client->index);
+}
+
+void
+AddGeneralSocket(int fd)
+{
+ FD_SET(fd, &AllSockets);
+ if (GrabInProgress)
+ FD_SET(fd, &SavedAllSockets);
+}
+
+void
+AddEnabledDevice(int fd)
+{
+ FD_SET(fd, &EnabledDevices);
+ AddGeneralSocket(fd);
+}
+
+void
+RemoveGeneralSocket(int fd)
+{
+ FD_CLR(fd, &AllSockets);
+ if (GrabInProgress)
+ FD_CLR(fd, &SavedAllSockets);
+}
+
+void
+RemoveEnabledDevice(int fd)
+{
+ FD_CLR(fd, &EnabledDevices);
+ RemoveGeneralSocket(fd);
+}
+
+/*****************
+ * 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()
+ *****************/
+
+int
+OnlyListenToOneClient(ClientPtr client)
+{
+ OsCommPtr oc = (OsCommPtr)client->osPrivate;
+ int rc, connection = oc->fd;
+
+ rc = XaceHook(XACE_SERVER_ACCESS, client, DixGrabAccess);
+ if (rc != Success)
+ return rc;
+
+ if (! GrabInProgress)
+ {
+ XFD_COPYSET(&ClientsWithInput, &SavedClientsWithInput);
+ XFD_ANDSET(&ClientsWithInput,
+ &ClientsWithInput, &GrabImperviousClients);
+ if (FD_ISSET(connection, &SavedClientsWithInput))
+ {
+ FD_CLR(connection, &SavedClientsWithInput);
+ FD_SET(connection, &ClientsWithInput);
+ }
+ XFD_UNSET(&SavedClientsWithInput, &GrabImperviousClients);
+ XFD_COPYSET(&AllSockets, &SavedAllSockets);
+ XFD_COPYSET(&AllClients, &SavedAllClients);
+ XFD_UNSET(&AllSockets, &AllClients);
+ XFD_ANDSET(&AllClients, &AllClients, &GrabImperviousClients);
+ FD_SET(connection, &AllClients);
+ XFD_ORSET(&AllSockets, &AllSockets, &AllClients);
+ GrabInProgress = client->index;
+ }
+ return rc;
+}
+
+/****************
+ * 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;
+
+ client->ignoreCount++;
+ if (client->ignoreCount > 1)
+ return;
+
+ isItTimeToYield = TRUE;
+ if (!GrabInProgress || FD_ISSET(connection, &AllClients))
+ {
+ if (FD_ISSET (connection, &ClientsWithInput))
+ FD_SET(connection, &IgnoredClientsWithInput);
+ else
+ FD_CLR(connection, &IgnoredClientsWithInput);
+ FD_CLR(connection, &ClientsWithInput);
+ FD_CLR(connection, &AllSockets);
+ FD_CLR(connection, &AllClients);
+ FD_CLR(connection, &LastSelectMask);
+ }
+ else
+ {
+ if (FD_ISSET (connection, &SavedClientsWithInput))
+ FD_SET(connection, &IgnoredClientsWithInput);
+ else
+ FD_CLR(connection, &IgnoredClientsWithInput);
+ FD_CLR(connection, &SavedClientsWithInput);
+ FD_CLR(connection, &SavedAllSockets);
+ FD_CLR(connection, &SavedAllClients);
+ }
+}
+
+/****************
+ * AttendClient
+ * Adds one client back into the input masks.
+ ****************/
+
+void
+AttendClient (ClientPtr client)
+{
+ OsCommPtr oc = (OsCommPtr)client->osPrivate;
+ int connection = oc->fd;
+
+ client->ignoreCount--;
+ if (client->ignoreCount)
+ return;
+
+ if (!GrabInProgress || GrabInProgress == client->index ||
+ FD_ISSET(connection, &GrabImperviousClients))
+ {
+ FD_SET(connection, &AllClients);
+ FD_SET(connection, &AllSockets);
+ FD_SET(connection, &LastSelectMask);
+ if (FD_ISSET (connection, &IgnoredClientsWithInput))
+ FD_SET(connection, &ClientsWithInput);
+ }
+ else
+ {
+ FD_SET(connection, &SavedAllClients);
+ FD_SET(connection, &SavedAllSockets);
+ if (FD_ISSET(connection, &IgnoredClientsWithInput))
+ FD_SET(connection, &SavedClientsWithInput);
+ }
+}
+
+/* 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);
+ }
+}
+
+#ifdef XQUARTZ
+/* Add a fd (from launchd) to our listeners */
+void ListenOnOpenFD(int fd, int noxauth) {
+ char port[256];
+ XtransConnInfo ciptr;
+ const char *display_env = getenv("DISPLAY");
+
+ if(display_env && (strncmp(display_env, "/tmp/launch", 11) == 0)) {
+ /* Make the path the launchd socket if our DISPLAY is set right */
+ strcpy(port, display_env);
+ } else {
+ /* Just some default so things don't break and die. */
+ sprintf(port, ":%d", atoi(display));
+ }
+
+ /* Make our XtransConnInfo
+ * TRANS_SOCKET_LOCAL_INDEX = 5 from Xtrans.c
+ */
+ ciptr = _XSERVTransReopenCOTSServer(5, fd, port);
+ if(ciptr == NULL) {
+ ErrorF("Got NULL while trying to Reopen launchd port.\n");
+ return;
+ }
+
+ if(noxauth)
+ ciptr->flags = ciptr->flags | TRANS_NOXAUTH;
+
+ /* Allocate space to store it */
+ ListenTransFds = (int *) realloc(ListenTransFds, (ListenTransCount + 1) * sizeof (int));
+ ListenTransConns = (XtransConnInfo *) realloc(ListenTransConns, (ListenTransCount + 1) * sizeof (XtransConnInfo));
+
+ /* Store it */
+ ListenTransConns[ListenTransCount] = ciptr;
+ ListenTransFds[ListenTransCount] = fd;
+
+ FD_SET(fd, &WellKnownConnections);
+ FD_SET(fd, &AllSockets);
+
+ /* Increment the count */
+ ListenTransCount++;
+
+ /* This *might* not be needed... /shrug */
+ ResetAuthorization();
+ ResetHosts(display);
+#ifdef XDMCP
+ XdmcpReset();
+#endif
+}
+
+#endif
diff --git a/os/io.c b/os/io.c
new file mode 100644
index 0000000..4210238
--- /dev/null
+++ b/os/io.c
@@ -0,0 +1,1147 @@
+/***********************************************************
+
+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
+
+#undef DEBUG_COMMUNICATION
+
+#ifdef WIN32
+#include <X11/Xwinsock.h>
+#endif
+#include <stdio.h>
+#define XSERV_t
+#define TRANS_SERVER
+#define TRANS_REOPEN
+#include <X11/Xtrans/Xtrans.h>
+#include <X11/Xmd.h>
+#include <errno.h>
+#if !defined(WIN32)
+#include <sys/uio.h>
+#endif
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include "os.h"
+#include "osdep.h"
+#include <X11/Xpoll.h>
+#include "opaque.h"
+#include "dixstruct.h"
+#include "misc.h"
+
+CallbackListPtr ReplyCallback;
+CallbackListPtr FlushCallback;
+
+static ConnectionInputPtr AllocateInputBuffer(void);
+static ConnectionOutputPtr AllocateOutputBuffer(void);
+
+/* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX
+ * systems are broken and return EWOULDBLOCK when they should return EAGAIN
+ */
+#ifndef WIN32
+#define ETEST(err) (err == EAGAIN || err == EWOULDBLOCK)
+#else /* WIN32 The socket errorcodes differ from the normal errors*/
+#define ETEST(err) (err == EAGAIN || err == WSAEWOULDBLOCK)
+#endif
+
+static Bool CriticalOutputPending;
+static int timesThisConnection = 0;
+static ConnectionInputPtr FreeInputs = (ConnectionInputPtr)NULL;
+static ConnectionOutputPtr FreeOutputs = (ConnectionOutputPtr)NULL;
+static OsCommPtr AvailableInput = (OsCommPtr)NULL;
+
+#define get_req_len(req,cli) ((cli)->swapped ? \
+ lswaps((req)->length) : (req)->length)
+
+#include <X11/extensions/bigreqsproto.h>
+
+#define get_big_req_len(req,cli) ((cli)->swapped ? \
+ lswapl(((xBigReq *)(req))->length) : \
+ ((xBigReq *)(req))->length)
+
+#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.
+ *****************************************************************/
+
+static void
+YieldControl(void)
+{
+ isItTimeToYield = TRUE;
+ timesThisConnection = 0;
+}
+
+static void
+YieldControlNoInput(int fd)
+{
+ YieldControl();
+ FD_CLR(fd, &ClientsWithInput);
+}
+
+static void
+YieldControlDeath(void)
+{
+ 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;
+ Bool move_header;
+
+ /* 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;
+ move_header = FALSE;
+ 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);
+ 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 = bytes_to_int32(sizeof(xBigReq)); /* needed is in CARD32s now */
+ need_header = TRUE;
+ }
+ else
+ needed = get_big_req_len(request, client);
+ }
+ 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 > maxBigRequestSize << 2)
+ {
+ /* 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(fd);
+ 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);
+ if (!needed && client->big_requests)
+ {
+ move_header = TRUE;
+ if (gotnow < sizeof(xBigReq))
+ needed = bytes_to_int32(sizeof(xBigReq));
+ else
+ needed = get_big_req_len(request, client);
+ }
+ client->req_len = needed;
+ needed <<= 2;
+ }
+ if (gotnow < needed)
+ {
+ /* Still don't have enough; punt. */
+ YieldControlNoInput(fd);
+ return 0;
+ }
+ }
+ if (needed == 0)
+ {
+ if (client->big_requests)
+ needed = sizeof(xBigReq);
+ else
+ needed = sizeof(xReq);
+ }
+
+ /* If there are bytes to ignore, ignore them now. */
+
+ if (oci->ignoreBytes > 0) {
+ assert(needed == oci->ignoreBytes || needed == oci->size);
+ /*
+ * 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))
+ && (result ||
+ (client->big_requests &&
+ (gotnow >= sizeof(xBigReq) &&
+ gotnow >= (get_big_req_len(request, client) << 2))))
+ )
+ FD_SET(fd, &ClientsWithInput);
+ else
+ {
+ if (!SmartScheduleDisable)
+ FD_CLR(fd, &ClientsWithInput);
+ else
+ YieldControlNoInput(fd);
+ }
+ }
+ else
+ {
+ if (!gotnow)
+ AvailableInput = oc;
+ if (!SmartScheduleDisable)
+ FD_CLR(fd, &ClientsWithInput);
+ else
+ YieldControlNoInput(fd);
+ }
+ if (SmartScheduleDisable)
+ if (++timesThisConnection >= MAX_TIMES_PER)
+ YieldControl();
+ 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 -= bytes_to_int32(sizeof(xBigReq) - sizeof(xReq));
+ }
+ client->requestBuffer = (pointer)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(fd);
+ 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(fd);
+ }
+ else
+ {
+ request = (xReq *)oci->bufptr;
+ needed = get_req_len(request, client);
+ 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)
+ {
+ char n;
+ swapl(&((xBigReq *)oci->bufptr)->length, n);
+ }
+ }
+ if (gotnow >= (needed << 2))
+ {
+ if (FD_ISSET(fd, &AllClients))
+ {
+ FD_SET(fd, &ClientsWithInput);
+ }
+ else
+ {
+ FD_SET(fd, &IgnoredClientsWithInput);
+ }
+ YieldControl();
+ }
+ else
+ YieldControlNoInput(fd);
+ }
+}
+
+static const 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 (FlushCallback)
+ CallCallbacks(&FlushCallback, NULL);
+
+ 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), (pointer)&replyinfo);
+ }
+ else if (who->clientState == ClientStateRunning
+ && buf[0] == X_Reply)
+ { /* start of new reply */
+ CARD32 replylen;
+ unsigned long bytesleft;
+ char n;
+
+ replylen = ((xGenericReply *)buf)->length;
+ if (who->swapped)
+ swapl(&replylen, n);
+ bytesleft = (replylen * 4) + SIZEOF(xReply) - count - padBytes;
+ replyinfo.startOfReply = TRUE;
+ replyinfo.bytesRemaining = who->replyBytesRemaining = bytesleft;
+ CallCallbacks((&ReplyCallback), (pointer)&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 + count + padBytes > oco->size)
+ {
+ FD_CLR(oc->fd, &OutputPending);
+ if(!XFD_ANYSET(&OutputPending)) {
+ CriticalOutputPending = FALSE;
+ NewOutputPending = FALSE;
+ }
+
+ if (FlushCallback)
+ CallCallbacks(&FlushCallback, NULL);
+
+ return FlushClient(who, oc, buf, count);
+ }
+
+ NewOutputPending = TRUE;
+ FD_SET(oc->fd, &OutputPending);
+ memmove((char *)oco->buf + oco->count, buf, count);
+ oco->count += 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;
+ 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);
+ AnyClientsWriteBlocked = 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;
+
+ obuf = (unsigned char *)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 (AnyClientsWriteBlocked)
+ {
+ FD_CLR(oc->fd, &ClientsWriteBlocked);
+ if (! XFD_ANYSET(&ClientsWriteBlocked))
+ AnyClientsWriteBlocked = 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 */
+}
+
+static ConnectionInputPtr
+AllocateInputBuffer(void)
+{
+ ConnectionInputPtr oci;
+
+ oci = malloc(sizeof(ConnectionInput));
+ if (!oci)
+ return NULL;
+ oci->buffer = malloc(BUFSIZE);
+ if (!oci->buffer)
+ {
+ free(oci);
+ return NULL;
+ }
+ oci->size = BUFSIZE;
+ oci->bufptr = oci->buffer;
+ oci->bufcnt = 0;
+ oci->lenLastReq = 0;
+ oci->ignoreBytes = 0;
+ return oci;
+}
+
+static ConnectionOutputPtr
+AllocateOutputBuffer(void)
+{
+ ConnectionOutputPtr oco;
+
+ oco = malloc(sizeof(ConnectionOutput));
+ if (!oco)
+ return NULL;
+ oco->buf = calloc(1, BUFSIZE);
+ if (!oco->buf)
+ {
+ free(oco);
+ return 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;
+ }
+ }
+ 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/os/log.c b/os/log.c
new file mode 100644
index 0000000..9579e58
--- /dev/null
+++ b/os/log.c
@@ -0,0 +1,598 @@
+/*
+
+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 <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 XF86BIGFONT
+#include "xf86bigfontsrv.h"
+#endif
+
+#ifdef __clang__
+#pragma clang diagnostic ignored "-Wformat-nonliteral"
+#endif
+
+#ifdef DDXOSVERRORF
+void (*OsVendorVErrorFProc)(const char *, va_list args) = NULL;
+#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;
+
+#ifdef __APPLE__
+#include <AvailabilityMacros.h>
+
+static char __crashreporter_info_buff__[4096] = {0};
+static const char *__crashreporter_info__ __attribute__((__used__)) = &__crashreporter_info_buff__[0];
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
+// This is actually a toolchain requirement, but I'm not sure the correct check,
+// but it should be fine to just only include it for Leopard and later. This line
+// just tells the linker to never strip this symbol (such as for space optimization)
+asm (".desc ___crashreporter_info__, 0x10");
+#endif
+#endif
+
+/* 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
+
+/*
+ * 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.
+ */
+
+const char *
+LogInit(const char *fname, const char *backup)
+{
+ char *logFileName = NULL;
+
+ if (fname && *fname) {
+ if (asprintf(&logFileName, fname, display) == -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, display) == -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);
+ }
+ }
+ 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
+LogClose(void)
+{
+ 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;
+ static Bool newline = TRUE;
+
+ if (newline) {
+ sprintf(tmpBuffer, "[%10.3f] ", GetTimeInMillis() / 1000.0);
+ len = strlen(tmpBuffer);
+ if (logFile)
+ fwrite(tmpBuffer, len, 1, logFile);
+ }
+
+ /*
+ * 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);
+ len = strlen(tmpBuffer);
+ }
+ newline = (tmpBuffer[len-1] == '\n');
+ 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) {
+ if (len > bufferUnused) {
+ bufferSize += 1024;
+ bufferUnused += 1024;
+ saveBuffer = realloc(saveBuffer, 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[1024];
+
+ /* 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;
+ }
+
+ /* if s is not NULL we need a space before format */
+ snprintf(tmpBuf, sizeof(tmpBuf), "%s%s%s", s ? s : "",
+ s ? " " : "",
+ format);
+ LogVWrite(verb, tmpBuf, 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);
+}
+
+void
+AbortServer(void) _X_NORETURN;
+
+void
+AbortServer(void)
+{
+#ifdef XF86BIGFONT
+ XF86BigfontCleanup();
+#endif
+ CloseWellKnownConnections();
+ OsCleanup(TRUE);
+ CloseDownDevices();
+ AbortDDX();
+ fflush(stderr);
+ if (CoreDump)
+ OsAbort();
+ exit (1);
+}
+
+#define AUDIT_PREFIX "AUDIT: %s: %ld: "
+#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';
+ len = strlen(AUDIT_PREFIX) + strlen(autime) + 10 + 1;
+ tmpBuf = malloc(len);
+ if (!tmpBuf)
+ return NULL;
+ snprintf(tmpBuf, len, AUDIT_PREFIX, autime, (unsigned long)getpid());
+ 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, pointer arg)
+{
+ char *prefix;
+
+ if (nrepeat > 0) {
+ prefix = AuditPrefix();
+ ErrorF("%slast message repeated %d times\n",
+ prefix != NULL ? prefix : "", nrepeat);
+ nrepeat = 0;
+ 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);
+ }
+ free(prefix);
+}
+
+void
+FatalError(const char *f, ...)
+{
+ va_list args;
+ static Bool beenhere = FALSE;
+
+ if (beenhere)
+ ErrorF("\nFatalError re-entered, aborting\n");
+ else
+ ErrorF("\nFatal server error:\n");
+
+ va_start(args, f);
+#ifdef __APPLE__
+ (void)vsnprintf(__crashreporter_info_buff__, sizeof(__crashreporter_info_buff__), f, args);
+#endif
+ VErrorF(f, args);
+ va_end(args);
+ ErrorF("\n");
+ if (!beenhere)
+ OsVendorFatalError();
+ if (!beenhere) {
+ beenhere = TRUE;
+ AbortServer();
+ } else
+ OsAbort();
+ /*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. */
+
+void
+Error(const char *str)
+{
+ const char *err = strerror(errno);
+
+ if (str)
+ LogWrite(-1, "%s: %s", str, err);
+ else
+ LogWrite(-1, "%s", err);
+}
+
+void
+LogPrintMarkers(void)
+{
+ /* Show what the message marker symbols mean. */
+ LogWrite(0, "Markers: ");
+ LogMessageVerb(X_PROBED, 0, "probed, ");
+ LogMessageVerb(X_CONFIG, 0, "from config file, ");
+ LogMessageVerb(X_DEFAULT, 0, "default setting,\n\t");
+ LogMessageVerb(X_CMDLINE, 0, "from command line, ");
+ LogMessageVerb(X_NOTICE, 0, "notice, ");
+ LogMessageVerb(X_INFO, 0, "informational,\n\t");
+ LogMessageVerb(X_WARNING, 0, "warning, ");
+ LogMessageVerb(X_ERROR, 0, "error, ");
+ LogMessageVerb(X_NOT_IMPLEMENTED, 0, "not implemented, ");
+ LogMessageVerb(X_UNKNOWN, 0, "unknown.\n");
+}
+
diff --git a/os/mitauth.c b/os/mitauth.c
new file mode 100644
index 0000000..4b8f6e9
--- /dev/null
+++ b/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 <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,
+ const char *data,
+ XID id)
+{
+ struct auth *new;
+
+ new = malloc(sizeof (struct auth));
+ if (!new)
+ return 0;
+ new->data = 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,
+ const char *data,
+ ClientPtr client,
+ char **reason)
+{
+ struct auth *auth;
+
+ for (auth = mit_auth; auth; auth=auth->next) {
+ if (data_length == auth->len &&
+ 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,
+ const 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,
+ const 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/os/os.c b/os/os.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/os/os.c
diff --git a/os/oscolor.c b/os/oscolor.c
new file mode 100644
index 0000000..7f6b938
--- /dev/null
+++ b/os/oscolor.c
@@ -0,0 +1,1606 @@
+/***********************************************************
+
+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 <X11/keysym.h>
+#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"
+ "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"
+ "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"
+ "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"
+ "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 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 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"
+ "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"
+ "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"
+ "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"
+ "wheat\0"
+ "wheat1\0"
+ "wheat2\0"
+ "wheat3\0"
+ "wheat4\0"
+ "white\0"
+ "white smoke\0"
+ "WhiteSmoke\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 */
+ { 127, 255, 212, 104 }, /* aquamarine */
+ { 127, 255, 212, 115 }, /* aquamarine1 */
+ { 118, 238, 198, 127 }, /* aquamarine2 */
+ { 102, 205, 170, 139 }, /* aquamarine3 */
+ { 69, 139, 116, 151 }, /* aquamarine4 */
+ { 240, 255, 255, 163 }, /* azure */
+ { 240, 255, 255, 169 }, /* azure1 */
+ { 224, 238, 238, 176 }, /* azure2 */
+ { 193, 205, 205, 183 }, /* azure3 */
+ { 131, 139, 139, 190 }, /* azure4 */
+ { 245, 245, 220, 197 }, /* beige */
+ { 255, 228, 196, 203 }, /* bisque */
+ { 255, 228, 196, 210 }, /* bisque1 */
+ { 238, 213, 183, 218 }, /* bisque2 */
+ { 205, 183, 158, 226 }, /* bisque3 */
+ { 139, 125, 107, 234 }, /* bisque4 */
+ { 0, 0, 0, 242 }, /* black */
+ { 255, 235, 205, 248 }, /* blanched almond */
+ { 255, 235, 205, 264 }, /* BlanchedAlmond */
+ { 0, 0, 255, 279 }, /* blue */
+ { 138, 43, 226, 284 }, /* blue violet */
+ { 0, 0, 255, 296 }, /* blue1 */
+ { 0, 0, 238, 302 }, /* blue2 */
+ { 0, 0, 205, 308 }, /* blue3 */
+ { 0, 0, 139, 314 }, /* blue4 */
+ { 138, 43, 226, 320 }, /* BlueViolet */
+ { 165, 42, 42, 331 }, /* brown */
+ { 255, 64, 64, 337 }, /* brown1 */
+ { 238, 59, 59, 344 }, /* brown2 */
+ { 205, 51, 51, 351 }, /* brown3 */
+ { 139, 35, 35, 358 }, /* brown4 */
+ { 222, 184, 135, 365 }, /* burlywood */
+ { 255, 211, 155, 375 }, /* burlywood1 */
+ { 238, 197, 145, 386 }, /* burlywood2 */
+ { 205, 170, 125, 397 }, /* burlywood3 */
+ { 139, 115, 85, 408 }, /* burlywood4 */
+ { 95, 158, 160, 419 }, /* cadet blue */
+ { 95, 158, 160, 430 }, /* CadetBlue */
+ { 152, 245, 255, 440 }, /* CadetBlue1 */
+ { 142, 229, 238, 451 }, /* CadetBlue2 */
+ { 122, 197, 205, 462 }, /* CadetBlue3 */
+ { 83, 134, 139, 473 }, /* CadetBlue4 */
+ { 127, 255, 0, 484 }, /* chartreuse */
+ { 127, 255, 0, 495 }, /* chartreuse1 */
+ { 118, 238, 0, 507 }, /* chartreuse2 */
+ { 102, 205, 0, 519 }, /* chartreuse3 */
+ { 69, 139, 0, 531 }, /* chartreuse4 */
+ { 210, 105, 30, 543 }, /* chocolate */
+ { 255, 127, 36, 553 }, /* chocolate1 */
+ { 238, 118, 33, 564 }, /* chocolate2 */
+ { 205, 102, 29, 575 }, /* chocolate3 */
+ { 139, 69, 19, 586 }, /* chocolate4 */
+ { 255, 127, 80, 597 }, /* coral */
+ { 255, 114, 86, 603 }, /* coral1 */
+ { 238, 106, 80, 610 }, /* coral2 */
+ { 205, 91, 69, 617 }, /* coral3 */
+ { 139, 62, 47, 624 }, /* coral4 */
+ { 100, 149, 237, 631 }, /* cornflower blue */
+ { 100, 149, 237, 647 }, /* CornflowerBlue */
+ { 255, 248, 220, 662 }, /* cornsilk */
+ { 255, 248, 220, 671 }, /* cornsilk1 */
+ { 238, 232, 205, 681 }, /* cornsilk2 */
+ { 205, 200, 177, 691 }, /* cornsilk3 */
+ { 139, 136, 120, 701 }, /* cornsilk4 */
+ { 0, 255, 255, 711 }, /* cyan */
+ { 0, 255, 255, 716 }, /* cyan1 */
+ { 0, 238, 238, 722 }, /* cyan2 */
+ { 0, 205, 205, 728 }, /* cyan3 */
+ { 0, 139, 139, 734 }, /* cyan4 */
+ { 0, 0, 139, 740 }, /* dark blue */
+ { 0, 139, 139, 750 }, /* dark cyan */
+ { 184, 134, 11, 760 }, /* dark goldenrod */
+ { 169, 169, 169, 775 }, /* dark gray */
+ { 0, 100, 0, 785 }, /* dark green */
+ { 169, 169, 169, 796 }, /* dark grey */
+ { 189, 183, 107, 806 }, /* dark khaki */
+ { 139, 0, 139, 817 }, /* dark magenta */
+ { 85, 107, 47, 830 }, /* dark olive green */
+ { 255, 140, 0, 847 }, /* dark orange */
+ { 153, 50, 204, 859 }, /* dark orchid */
+ { 139, 0, 0, 871 }, /* dark red */
+ { 233, 150, 122, 880 }, /* dark salmon */
+ { 143, 188, 143, 892 }, /* dark sea green */
+ { 72, 61, 139, 907 }, /* dark slate blue */
+ { 47, 79, 79, 923 }, /* dark slate gray */
+ { 47, 79, 79, 939 }, /* dark slate grey */
+ { 0, 206, 209, 955 }, /* dark turquoise */
+ { 148, 0, 211, 970 }, /* dark violet */
+ { 0, 0, 139, 982 }, /* DarkBlue */
+ { 0, 139, 139, 991 }, /* DarkCyan */
+ { 184, 134, 11, 1000 }, /* DarkGoldenrod */
+ { 255, 185, 15, 1014 }, /* DarkGoldenrod1 */
+ { 238, 173, 14, 1029 }, /* DarkGoldenrod2 */
+ { 205, 149, 12, 1044 }, /* DarkGoldenrod3 */
+ { 139, 101, 8, 1059 }, /* DarkGoldenrod4 */
+ { 169, 169, 169, 1074 }, /* DarkGray */
+ { 0, 100, 0, 1083 }, /* DarkGreen */
+ { 169, 169, 169, 1093 }, /* DarkGrey */
+ { 189, 183, 107, 1102 }, /* DarkKhaki */
+ { 139, 0, 139, 1112 }, /* DarkMagenta */
+ { 85, 107, 47, 1124 }, /* DarkOliveGreen */
+ { 202, 255, 112, 1139 }, /* DarkOliveGreen1 */
+ { 188, 238, 104, 1155 }, /* DarkOliveGreen2 */
+ { 162, 205, 90, 1171 }, /* DarkOliveGreen3 */
+ { 110, 139, 61, 1187 }, /* DarkOliveGreen4 */
+ { 255, 140, 0, 1203 }, /* DarkOrange */
+ { 255, 127, 0, 1214 }, /* DarkOrange1 */
+ { 238, 118, 0, 1226 }, /* DarkOrange2 */
+ { 205, 102, 0, 1238 }, /* DarkOrange3 */
+ { 139, 69, 0, 1250 }, /* DarkOrange4 */
+ { 153, 50, 204, 1262 }, /* DarkOrchid */
+ { 191, 62, 255, 1273 }, /* DarkOrchid1 */
+ { 178, 58, 238, 1285 }, /* DarkOrchid2 */
+ { 154, 50, 205, 1297 }, /* DarkOrchid3 */
+ { 104, 34, 139, 1309 }, /* DarkOrchid4 */
+ { 139, 0, 0, 1321 }, /* DarkRed */
+ { 233, 150, 122, 1329 }, /* DarkSalmon */
+ { 143, 188, 143, 1340 }, /* DarkSeaGreen */
+ { 193, 255, 193, 1353 }, /* DarkSeaGreen1 */
+ { 180, 238, 180, 1367 }, /* DarkSeaGreen2 */
+ { 155, 205, 155, 1381 }, /* DarkSeaGreen3 */
+ { 105, 139, 105, 1395 }, /* DarkSeaGreen4 */
+ { 72, 61, 139, 1409 }, /* DarkSlateBlue */
+ { 47, 79, 79, 1423 }, /* DarkSlateGray */
+ { 151, 255, 255, 1437 }, /* DarkSlateGray1 */
+ { 141, 238, 238, 1452 }, /* DarkSlateGray2 */
+ { 121, 205, 205, 1467 }, /* DarkSlateGray3 */
+ { 82, 139, 139, 1482 }, /* DarkSlateGray4 */
+ { 47, 79, 79, 1497 }, /* DarkSlateGrey */
+ { 0, 206, 209, 1511 }, /* DarkTurquoise */
+ { 148, 0, 211, 1525 }, /* DarkViolet */
+ { 255, 20, 147, 1536 }, /* deep pink */
+ { 0, 191, 255, 1546 }, /* deep sky blue */
+ { 255, 20, 147, 1560 }, /* DeepPink */
+ { 255, 20, 147, 1569 }, /* DeepPink1 */
+ { 238, 18, 137, 1579 }, /* DeepPink2 */
+ { 205, 16, 118, 1589 }, /* DeepPink3 */
+ { 139, 10, 80, 1599 }, /* DeepPink4 */
+ { 0, 191, 255, 1609 }, /* DeepSkyBlue */
+ { 0, 191, 255, 1621 }, /* DeepSkyBlue1 */
+ { 0, 178, 238, 1634 }, /* DeepSkyBlue2 */
+ { 0, 154, 205, 1647 }, /* DeepSkyBlue3 */
+ { 0, 104, 139, 1660 }, /* DeepSkyBlue4 */
+ { 105, 105, 105, 1673 }, /* dim gray */
+ { 105, 105, 105, 1682 }, /* dim grey */
+ { 105, 105, 105, 1691 }, /* DimGray */
+ { 105, 105, 105, 1699 }, /* DimGrey */
+ { 30, 144, 255, 1707 }, /* dodger blue */
+ { 30, 144, 255, 1719 }, /* DodgerBlue */
+ { 30, 144, 255, 1730 }, /* DodgerBlue1 */
+ { 28, 134, 238, 1742 }, /* DodgerBlue2 */
+ { 24, 116, 205, 1754 }, /* DodgerBlue3 */
+ { 16, 78, 139, 1766 }, /* DodgerBlue4 */
+ { 178, 34, 34, 1778 }, /* firebrick */
+ { 255, 48, 48, 1788 }, /* firebrick1 */
+ { 238, 44, 44, 1799 }, /* firebrick2 */
+ { 205, 38, 38, 1810 }, /* firebrick3 */
+ { 139, 26, 26, 1821 }, /* firebrick4 */
+ { 255, 250, 240, 1832 }, /* floral white */
+ { 255, 250, 240, 1845 }, /* FloralWhite */
+ { 34, 139, 34, 1857 }, /* forest green */
+ { 34, 139, 34, 1870 }, /* ForestGreen */
+ { 220, 220, 220, 1882 }, /* gainsboro */
+ { 248, 248, 255, 1892 }, /* ghost white */
+ { 248, 248, 255, 1904 }, /* GhostWhite */
+ { 255, 215, 0, 1915 }, /* gold */
+ { 255, 215, 0, 1920 }, /* gold1 */
+ { 238, 201, 0, 1926 }, /* gold2 */
+ { 205, 173, 0, 1932 }, /* gold3 */
+ { 139, 117, 0, 1938 }, /* gold4 */
+ { 218, 165, 32, 1944 }, /* goldenrod */
+ { 255, 193, 37, 1954 }, /* goldenrod1 */
+ { 238, 180, 34, 1965 }, /* goldenrod2 */
+ { 205, 155, 29, 1976 }, /* goldenrod3 */
+ { 139, 105, 20, 1987 }, /* goldenrod4 */
+ { 190, 190, 190, 1998 }, /* gray */
+ { 0, 0, 0, 2003 }, /* gray0 */
+ { 3, 3, 3, 2009 }, /* gray1 */
+ { 26, 26, 26, 2015 }, /* gray10 */
+ { 255, 255, 255, 2022 }, /* gray100 */
+ { 28, 28, 28, 2030 }, /* gray11 */
+ { 31, 31, 31, 2037 }, /* gray12 */
+ { 33, 33, 33, 2044 }, /* gray13 */
+ { 36, 36, 36, 2051 }, /* gray14 */
+ { 38, 38, 38, 2058 }, /* gray15 */
+ { 41, 41, 41, 2065 }, /* gray16 */
+ { 43, 43, 43, 2072 }, /* gray17 */
+ { 46, 46, 46, 2079 }, /* gray18 */
+ { 48, 48, 48, 2086 }, /* gray19 */
+ { 5, 5, 5, 2093 }, /* gray2 */
+ { 51, 51, 51, 2099 }, /* gray20 */
+ { 54, 54, 54, 2106 }, /* gray21 */
+ { 56, 56, 56, 2113 }, /* gray22 */
+ { 59, 59, 59, 2120 }, /* gray23 */
+ { 61, 61, 61, 2127 }, /* gray24 */
+ { 64, 64, 64, 2134 }, /* gray25 */
+ { 66, 66, 66, 2141 }, /* gray26 */
+ { 69, 69, 69, 2148 }, /* gray27 */
+ { 71, 71, 71, 2155 }, /* gray28 */
+ { 74, 74, 74, 2162 }, /* gray29 */
+ { 8, 8, 8, 2169 }, /* gray3 */
+ { 77, 77, 77, 2175 }, /* gray30 */
+ { 79, 79, 79, 2182 }, /* gray31 */
+ { 82, 82, 82, 2189 }, /* gray32 */
+ { 84, 84, 84, 2196 }, /* gray33 */
+ { 87, 87, 87, 2203 }, /* gray34 */
+ { 89, 89, 89, 2210 }, /* gray35 */
+ { 92, 92, 92, 2217 }, /* gray36 */
+ { 94, 94, 94, 2224 }, /* gray37 */
+ { 97, 97, 97, 2231 }, /* gray38 */
+ { 99, 99, 99, 2238 }, /* gray39 */
+ { 10, 10, 10, 2245 }, /* gray4 */
+ { 102, 102, 102, 2251 }, /* gray40 */
+ { 105, 105, 105, 2258 }, /* gray41 */
+ { 107, 107, 107, 2265 }, /* gray42 */
+ { 110, 110, 110, 2272 }, /* gray43 */
+ { 112, 112, 112, 2279 }, /* gray44 */
+ { 115, 115, 115, 2286 }, /* gray45 */
+ { 117, 117, 117, 2293 }, /* gray46 */
+ { 120, 120, 120, 2300 }, /* gray47 */
+ { 122, 122, 122, 2307 }, /* gray48 */
+ { 125, 125, 125, 2314 }, /* gray49 */
+ { 13, 13, 13, 2321 }, /* gray5 */
+ { 127, 127, 127, 2327 }, /* gray50 */
+ { 130, 130, 130, 2334 }, /* gray51 */
+ { 133, 133, 133, 2341 }, /* gray52 */
+ { 135, 135, 135, 2348 }, /* gray53 */
+ { 138, 138, 138, 2355 }, /* gray54 */
+ { 140, 140, 140, 2362 }, /* gray55 */
+ { 143, 143, 143, 2369 }, /* gray56 */
+ { 145, 145, 145, 2376 }, /* gray57 */
+ { 148, 148, 148, 2383 }, /* gray58 */
+ { 150, 150, 150, 2390 }, /* gray59 */
+ { 15, 15, 15, 2397 }, /* gray6 */
+ { 153, 153, 153, 2403 }, /* gray60 */
+ { 156, 156, 156, 2410 }, /* gray61 */
+ { 158, 158, 158, 2417 }, /* gray62 */
+ { 161, 161, 161, 2424 }, /* gray63 */
+ { 163, 163, 163, 2431 }, /* gray64 */
+ { 166, 166, 166, 2438 }, /* gray65 */
+ { 168, 168, 168, 2445 }, /* gray66 */
+ { 171, 171, 171, 2452 }, /* gray67 */
+ { 173, 173, 173, 2459 }, /* gray68 */
+ { 176, 176, 176, 2466 }, /* gray69 */
+ { 18, 18, 18, 2473 }, /* gray7 */
+ { 179, 179, 179, 2479 }, /* gray70 */
+ { 181, 181, 181, 2486 }, /* gray71 */
+ { 184, 184, 184, 2493 }, /* gray72 */
+ { 186, 186, 186, 2500 }, /* gray73 */
+ { 189, 189, 189, 2507 }, /* gray74 */
+ { 191, 191, 191, 2514 }, /* gray75 */
+ { 194, 194, 194, 2521 }, /* gray76 */
+ { 196, 196, 196, 2528 }, /* gray77 */
+ { 199, 199, 199, 2535 }, /* gray78 */
+ { 201, 201, 201, 2542 }, /* gray79 */
+ { 20, 20, 20, 2549 }, /* gray8 */
+ { 204, 204, 204, 2555 }, /* gray80 */
+ { 207, 207, 207, 2562 }, /* gray81 */
+ { 209, 209, 209, 2569 }, /* gray82 */
+ { 212, 212, 212, 2576 }, /* gray83 */
+ { 214, 214, 214, 2583 }, /* gray84 */
+ { 217, 217, 217, 2590 }, /* gray85 */
+ { 219, 219, 219, 2597 }, /* gray86 */
+ { 222, 222, 222, 2604 }, /* gray87 */
+ { 224, 224, 224, 2611 }, /* gray88 */
+ { 227, 227, 227, 2618 }, /* gray89 */
+ { 23, 23, 23, 2625 }, /* gray9 */
+ { 229, 229, 229, 2631 }, /* gray90 */
+ { 232, 232, 232, 2638 }, /* gray91 */
+ { 235, 235, 235, 2645 }, /* gray92 */
+ { 237, 237, 237, 2652 }, /* gray93 */
+ { 240, 240, 240, 2659 }, /* gray94 */
+ { 242, 242, 242, 2666 }, /* gray95 */
+ { 245, 245, 245, 2673 }, /* gray96 */
+ { 247, 247, 247, 2680 }, /* gray97 */
+ { 250, 250, 250, 2687 }, /* gray98 */
+ { 252, 252, 252, 2694 }, /* gray99 */
+ { 0, 255, 0, 2701 }, /* green */
+ { 173, 255, 47, 2707 }, /* green yellow */
+ { 0, 255, 0, 2720 }, /* green1 */
+ { 0, 238, 0, 2727 }, /* green2 */
+ { 0, 205, 0, 2734 }, /* green3 */
+ { 0, 139, 0, 2741 }, /* green4 */
+ { 173, 255, 47, 2748 }, /* GreenYellow */
+ { 190, 190, 190, 2760 }, /* grey */
+ { 0, 0, 0, 2765 }, /* grey0 */
+ { 3, 3, 3, 2771 }, /* grey1 */
+ { 26, 26, 26, 2777 }, /* grey10 */
+ { 255, 255, 255, 2784 }, /* grey100 */
+ { 28, 28, 28, 2792 }, /* grey11 */
+ { 31, 31, 31, 2799 }, /* grey12 */
+ { 33, 33, 33, 2806 }, /* grey13 */
+ { 36, 36, 36, 2813 }, /* grey14 */
+ { 38, 38, 38, 2820 }, /* grey15 */
+ { 41, 41, 41, 2827 }, /* grey16 */
+ { 43, 43, 43, 2834 }, /* grey17 */
+ { 46, 46, 46, 2841 }, /* grey18 */
+ { 48, 48, 48, 2848 }, /* grey19 */
+ { 5, 5, 5, 2855 }, /* grey2 */
+ { 51, 51, 51, 2861 }, /* grey20 */
+ { 54, 54, 54, 2868 }, /* grey21 */
+ { 56, 56, 56, 2875 }, /* grey22 */
+ { 59, 59, 59, 2882 }, /* grey23 */
+ { 61, 61, 61, 2889 }, /* grey24 */
+ { 64, 64, 64, 2896 }, /* grey25 */
+ { 66, 66, 66, 2903 }, /* grey26 */
+ { 69, 69, 69, 2910 }, /* grey27 */
+ { 71, 71, 71, 2917 }, /* grey28 */
+ { 74, 74, 74, 2924 }, /* grey29 */
+ { 8, 8, 8, 2931 }, /* grey3 */
+ { 77, 77, 77, 2937 }, /* grey30 */
+ { 79, 79, 79, 2944 }, /* grey31 */
+ { 82, 82, 82, 2951 }, /* grey32 */
+ { 84, 84, 84, 2958 }, /* grey33 */
+ { 87, 87, 87, 2965 }, /* grey34 */
+ { 89, 89, 89, 2972 }, /* grey35 */
+ { 92, 92, 92, 2979 }, /* grey36 */
+ { 94, 94, 94, 2986 }, /* grey37 */
+ { 97, 97, 97, 2993 }, /* grey38 */
+ { 99, 99, 99, 3000 }, /* grey39 */
+ { 10, 10, 10, 3007 }, /* grey4 */
+ { 102, 102, 102, 3013 }, /* grey40 */
+ { 105, 105, 105, 3020 }, /* grey41 */
+ { 107, 107, 107, 3027 }, /* grey42 */
+ { 110, 110, 110, 3034 }, /* grey43 */
+ { 112, 112, 112, 3041 }, /* grey44 */
+ { 115, 115, 115, 3048 }, /* grey45 */
+ { 117, 117, 117, 3055 }, /* grey46 */
+ { 120, 120, 120, 3062 }, /* grey47 */
+ { 122, 122, 122, 3069 }, /* grey48 */
+ { 125, 125, 125, 3076 }, /* grey49 */
+ { 13, 13, 13, 3083 }, /* grey5 */
+ { 127, 127, 127, 3089 }, /* grey50 */
+ { 130, 130, 130, 3096 }, /* grey51 */
+ { 133, 133, 133, 3103 }, /* grey52 */
+ { 135, 135, 135, 3110 }, /* grey53 */
+ { 138, 138, 138, 3117 }, /* grey54 */
+ { 140, 140, 140, 3124 }, /* grey55 */
+ { 143, 143, 143, 3131 }, /* grey56 */
+ { 145, 145, 145, 3138 }, /* grey57 */
+ { 148, 148, 148, 3145 }, /* grey58 */
+ { 150, 150, 150, 3152 }, /* grey59 */
+ { 15, 15, 15, 3159 }, /* grey6 */
+ { 153, 153, 153, 3165 }, /* grey60 */
+ { 156, 156, 156, 3172 }, /* grey61 */
+ { 158, 158, 158, 3179 }, /* grey62 */
+ { 161, 161, 161, 3186 }, /* grey63 */
+ { 163, 163, 163, 3193 }, /* grey64 */
+ { 166, 166, 166, 3200 }, /* grey65 */
+ { 168, 168, 168, 3207 }, /* grey66 */
+ { 171, 171, 171, 3214 }, /* grey67 */
+ { 173, 173, 173, 3221 }, /* grey68 */
+ { 176, 176, 176, 3228 }, /* grey69 */
+ { 18, 18, 18, 3235 }, /* grey7 */
+ { 179, 179, 179, 3241 }, /* grey70 */
+ { 181, 181, 181, 3248 }, /* grey71 */
+ { 184, 184, 184, 3255 }, /* grey72 */
+ { 186, 186, 186, 3262 }, /* grey73 */
+ { 189, 189, 189, 3269 }, /* grey74 */
+ { 191, 191, 191, 3276 }, /* grey75 */
+ { 194, 194, 194, 3283 }, /* grey76 */
+ { 196, 196, 196, 3290 }, /* grey77 */
+ { 199, 199, 199, 3297 }, /* grey78 */
+ { 201, 201, 201, 3304 }, /* grey79 */
+ { 20, 20, 20, 3311 }, /* grey8 */
+ { 204, 204, 204, 3317 }, /* grey80 */
+ { 207, 207, 207, 3324 }, /* grey81 */
+ { 209, 209, 209, 3331 }, /* grey82 */
+ { 212, 212, 212, 3338 }, /* grey83 */
+ { 214, 214, 214, 3345 }, /* grey84 */
+ { 217, 217, 217, 3352 }, /* grey85 */
+ { 219, 219, 219, 3359 }, /* grey86 */
+ { 222, 222, 222, 3366 }, /* grey87 */
+ { 224, 224, 224, 3373 }, /* grey88 */
+ { 227, 227, 227, 3380 }, /* grey89 */
+ { 23, 23, 23, 3387 }, /* grey9 */
+ { 229, 229, 229, 3393 }, /* grey90 */
+ { 232, 232, 232, 3400 }, /* grey91 */
+ { 235, 235, 235, 3407 }, /* grey92 */
+ { 237, 237, 237, 3414 }, /* grey93 */
+ { 240, 240, 240, 3421 }, /* grey94 */
+ { 242, 242, 242, 3428 }, /* grey95 */
+ { 245, 245, 245, 3435 }, /* grey96 */
+ { 247, 247, 247, 3442 }, /* grey97 */
+ { 250, 250, 250, 3449 }, /* grey98 */
+ { 252, 252, 252, 3456 }, /* grey99 */
+ { 240, 255, 240, 3463 }, /* honeydew */
+ { 240, 255, 240, 3472 }, /* honeydew1 */
+ { 224, 238, 224, 3482 }, /* honeydew2 */
+ { 193, 205, 193, 3492 }, /* honeydew3 */
+ { 131, 139, 131, 3502 }, /* honeydew4 */
+ { 255, 105, 180, 3512 }, /* hot pink */
+ { 255, 105, 180, 3521 }, /* HotPink */
+ { 255, 110, 180, 3529 }, /* HotPink1 */
+ { 238, 106, 167, 3538 }, /* HotPink2 */
+ { 205, 96, 144, 3547 }, /* HotPink3 */
+ { 139, 58, 98, 3556 }, /* HotPink4 */
+ { 205, 92, 92, 3565 }, /* indian red */
+ { 205, 92, 92, 3576 }, /* IndianRed */
+ { 255, 106, 106, 3586 }, /* IndianRed1 */
+ { 238, 99, 99, 3597 }, /* IndianRed2 */
+ { 205, 85, 85, 3608 }, /* IndianRed3 */
+ { 139, 58, 58, 3619 }, /* IndianRed4 */
+ { 255, 255, 240, 3630 }, /* ivory */
+ { 255, 255, 240, 3636 }, /* ivory1 */
+ { 238, 238, 224, 3643 }, /* ivory2 */
+ { 205, 205, 193, 3650 }, /* ivory3 */
+ { 139, 139, 131, 3657 }, /* ivory4 */
+ { 240, 230, 140, 3664 }, /* khaki */
+ { 255, 246, 143, 3670 }, /* khaki1 */
+ { 238, 230, 133, 3677 }, /* khaki2 */
+ { 205, 198, 115, 3684 }, /* khaki3 */
+ { 139, 134, 78, 3691 }, /* khaki4 */
+ { 230, 230, 250, 3698 }, /* lavender */
+ { 255, 240, 245, 3707 }, /* lavender blush */
+ { 255, 240, 245, 3722 }, /* LavenderBlush */
+ { 255, 240, 245, 3736 }, /* LavenderBlush1 */
+ { 238, 224, 229, 3751 }, /* LavenderBlush2 */
+ { 205, 193, 197, 3766 }, /* LavenderBlush3 */
+ { 139, 131, 134, 3781 }, /* LavenderBlush4 */
+ { 124, 252, 0, 3796 }, /* lawn green */
+ { 124, 252, 0, 3807 }, /* LawnGreen */
+ { 255, 250, 205, 3817 }, /* lemon chiffon */
+ { 255, 250, 205, 3831 }, /* LemonChiffon */
+ { 255, 250, 205, 3844 }, /* LemonChiffon1 */
+ { 238, 233, 191, 3858 }, /* LemonChiffon2 */
+ { 205, 201, 165, 3872 }, /* LemonChiffon3 */
+ { 139, 137, 112, 3886 }, /* LemonChiffon4 */
+ { 173, 216, 230, 3900 }, /* light blue */
+ { 240, 128, 128, 3911 }, /* light coral */
+ { 224, 255, 255, 3923 }, /* light cyan */
+ { 238, 221, 130, 3934 }, /* light goldenrod */
+ { 250, 250, 210, 3950 }, /* light goldenrod yellow */
+ { 211, 211, 211, 3973 }, /* light gray */
+ { 144, 238, 144, 3984 }, /* light green */
+ { 211, 211, 211, 3996 }, /* light grey */
+ { 255, 182, 193, 4007 }, /* light pink */
+ { 255, 160, 122, 4018 }, /* light salmon */
+ { 32, 178, 170, 4031 }, /* light sea green */
+ { 135, 206, 250, 4047 }, /* light sky blue */
+ { 132, 112, 255, 4062 }, /* light slate blue */
+ { 119, 136, 153, 4079 }, /* light slate gray */
+ { 119, 136, 153, 4096 }, /* light slate grey */
+ { 176, 196, 222, 4113 }, /* light steel blue */
+ { 255, 255, 224, 4130 }, /* light yellow */
+ { 173, 216, 230, 4143 }, /* LightBlue */
+ { 191, 239, 255, 4153 }, /* LightBlue1 */
+ { 178, 223, 238, 4164 }, /* LightBlue2 */
+ { 154, 192, 205, 4175 }, /* LightBlue3 */
+ { 104, 131, 139, 4186 }, /* LightBlue4 */
+ { 240, 128, 128, 4197 }, /* LightCoral */
+ { 224, 255, 255, 4208 }, /* LightCyan */
+ { 224, 255, 255, 4218 }, /* LightCyan1 */
+ { 209, 238, 238, 4229 }, /* LightCyan2 */
+ { 180, 205, 205, 4240 }, /* LightCyan3 */
+ { 122, 139, 139, 4251 }, /* LightCyan4 */
+ { 238, 221, 130, 4262 }, /* LightGoldenrod */
+ { 255, 236, 139, 4277 }, /* LightGoldenrod1 */
+ { 238, 220, 130, 4293 }, /* LightGoldenrod2 */
+ { 205, 190, 112, 4309 }, /* LightGoldenrod3 */
+ { 139, 129, 76, 4325 }, /* LightGoldenrod4 */
+ { 250, 250, 210, 4341 }, /* LightGoldenrodYellow */
+ { 211, 211, 211, 4362 }, /* LightGray */
+ { 144, 238, 144, 4372 }, /* LightGreen */
+ { 211, 211, 211, 4383 }, /* LightGrey */
+ { 255, 182, 193, 4393 }, /* LightPink */
+ { 255, 174, 185, 4403 }, /* LightPink1 */
+ { 238, 162, 173, 4414 }, /* LightPink2 */
+ { 205, 140, 149, 4425 }, /* LightPink3 */
+ { 139, 95, 101, 4436 }, /* LightPink4 */
+ { 255, 160, 122, 4447 }, /* LightSalmon */
+ { 255, 160, 122, 4459 }, /* LightSalmon1 */
+ { 238, 149, 114, 4472 }, /* LightSalmon2 */
+ { 205, 129, 98, 4485 }, /* LightSalmon3 */
+ { 139, 87, 66, 4498 }, /* LightSalmon4 */
+ { 32, 178, 170, 4511 }, /* LightSeaGreen */
+ { 135, 206, 250, 4525 }, /* LightSkyBlue */
+ { 176, 226, 255, 4538 }, /* LightSkyBlue1 */
+ { 164, 211, 238, 4552 }, /* LightSkyBlue2 */
+ { 141, 182, 205, 4566 }, /* LightSkyBlue3 */
+ { 96, 123, 139, 4580 }, /* LightSkyBlue4 */
+ { 132, 112, 255, 4594 }, /* LightSlateBlue */
+ { 119, 136, 153, 4609 }, /* LightSlateGray */
+ { 119, 136, 153, 4624 }, /* LightSlateGrey */
+ { 176, 196, 222, 4639 }, /* LightSteelBlue */
+ { 202, 225, 255, 4654 }, /* LightSteelBlue1 */
+ { 188, 210, 238, 4670 }, /* LightSteelBlue2 */
+ { 162, 181, 205, 4686 }, /* LightSteelBlue3 */
+ { 110, 123, 139, 4702 }, /* LightSteelBlue4 */
+ { 255, 255, 224, 4718 }, /* LightYellow */
+ { 255, 255, 224, 4730 }, /* LightYellow1 */
+ { 238, 238, 209, 4743 }, /* LightYellow2 */
+ { 205, 205, 180, 4756 }, /* LightYellow3 */
+ { 139, 139, 122, 4769 }, /* LightYellow4 */
+ { 50, 205, 50, 4782 }, /* lime green */
+ { 50, 205, 50, 4793 }, /* LimeGreen */
+ { 250, 240, 230, 4803 }, /* linen */
+ { 255, 0, 255, 4809 }, /* magenta */
+ { 255, 0, 255, 4817 }, /* magenta1 */
+ { 238, 0, 238, 4826 }, /* magenta2 */
+ { 205, 0, 205, 4835 }, /* magenta3 */
+ { 139, 0, 139, 4844 }, /* magenta4 */
+ { 176, 48, 96, 4853 }, /* maroon */
+ { 255, 52, 179, 4860 }, /* maroon1 */
+ { 238, 48, 167, 4868 }, /* maroon2 */
+ { 205, 41, 144, 4876 }, /* maroon3 */
+ { 139, 28, 98, 4884 }, /* maroon4 */
+ { 102, 205, 170, 4892 }, /* medium aquamarine */
+ { 0, 0, 205, 4910 }, /* medium blue */
+ { 186, 85, 211, 4922 }, /* medium orchid */
+ { 147, 112, 219, 4936 }, /* medium purple */
+ { 60, 179, 113, 4950 }, /* medium sea green */
+ { 123, 104, 238, 4967 }, /* medium slate blue */
+ { 0, 250, 154, 4985 }, /* medium spring green */
+ { 72, 209, 204, 5005 }, /* medium turquoise */
+ { 199, 21, 133, 5022 }, /* medium violet red */
+ { 102, 205, 170, 5040 }, /* MediumAquamarine */
+ { 0, 0, 205, 5057 }, /* MediumBlue */
+ { 186, 85, 211, 5068 }, /* MediumOrchid */
+ { 224, 102, 255, 5081 }, /* MediumOrchid1 */
+ { 209, 95, 238, 5095 }, /* MediumOrchid2 */
+ { 180, 82, 205, 5109 }, /* MediumOrchid3 */
+ { 122, 55, 139, 5123 }, /* MediumOrchid4 */
+ { 147, 112, 219, 5137 }, /* MediumPurple */
+ { 171, 130, 255, 5150 }, /* MediumPurple1 */
+ { 159, 121, 238, 5164 }, /* MediumPurple2 */
+ { 137, 104, 205, 5178 }, /* MediumPurple3 */
+ { 93, 71, 139, 5192 }, /* MediumPurple4 */
+ { 60, 179, 113, 5206 }, /* MediumSeaGreen */
+ { 123, 104, 238, 5221 }, /* MediumSlateBlue */
+ { 0, 250, 154, 5237 }, /* MediumSpringGreen */
+ { 72, 209, 204, 5255 }, /* MediumTurquoise */
+ { 199, 21, 133, 5271 }, /* MediumVioletRed */
+ { 25, 25, 112, 5287 }, /* midnight blue */
+ { 25, 25, 112, 5301 }, /* MidnightBlue */
+ { 245, 255, 250, 5314 }, /* mint cream */
+ { 245, 255, 250, 5325 }, /* MintCream */
+ { 255, 228, 225, 5335 }, /* misty rose */
+ { 255, 228, 225, 5346 }, /* MistyRose */
+ { 255, 228, 225, 5356 }, /* MistyRose1 */
+ { 238, 213, 210, 5367 }, /* MistyRose2 */
+ { 205, 183, 181, 5378 }, /* MistyRose3 */
+ { 139, 125, 123, 5389 }, /* MistyRose4 */
+ { 255, 228, 181, 5400 }, /* moccasin */
+ { 255, 222, 173, 5409 }, /* navajo white */
+ { 255, 222, 173, 5422 }, /* NavajoWhite */
+ { 255, 222, 173, 5434 }, /* NavajoWhite1 */
+ { 238, 207, 161, 5447 }, /* NavajoWhite2 */
+ { 205, 179, 139, 5460 }, /* NavajoWhite3 */
+ { 139, 121, 94, 5473 }, /* NavajoWhite4 */
+ { 0, 0, 128, 5486 }, /* navy */
+ { 0, 0, 128, 5491 }, /* navy blue */
+ { 0, 0, 128, 5501 }, /* NavyBlue */
+ { 253, 245, 230, 5510 }, /* old lace */
+ { 253, 245, 230, 5519 }, /* OldLace */
+ { 107, 142, 35, 5527 }, /* olive drab */
+ { 107, 142, 35, 5538 }, /* OliveDrab */
+ { 192, 255, 62, 5548 }, /* OliveDrab1 */
+ { 179, 238, 58, 5559 }, /* OliveDrab2 */
+ { 154, 205, 50, 5570 }, /* OliveDrab3 */
+ { 105, 139, 34, 5581 }, /* OliveDrab4 */
+ { 255, 165, 0, 5592 }, /* orange */
+ { 255, 69, 0, 5599 }, /* orange red */
+ { 255, 165, 0, 5610 }, /* orange1 */
+ { 238, 154, 0, 5618 }, /* orange2 */
+ { 205, 133, 0, 5626 }, /* orange3 */
+ { 139, 90, 0, 5634 }, /* orange4 */
+ { 255, 69, 0, 5642 }, /* OrangeRed */
+ { 255, 69, 0, 5652 }, /* OrangeRed1 */
+ { 238, 64, 0, 5663 }, /* OrangeRed2 */
+ { 205, 55, 0, 5674 }, /* OrangeRed3 */
+ { 139, 37, 0, 5685 }, /* OrangeRed4 */
+ { 218, 112, 214, 5696 }, /* orchid */
+ { 255, 131, 250, 5703 }, /* orchid1 */
+ { 238, 122, 233, 5711 }, /* orchid2 */
+ { 205, 105, 201, 5719 }, /* orchid3 */
+ { 139, 71, 137, 5727 }, /* orchid4 */
+ { 238, 232, 170, 5735 }, /* pale goldenrod */
+ { 152, 251, 152, 5750 }, /* pale green */
+ { 175, 238, 238, 5761 }, /* pale turquoise */
+ { 219, 112, 147, 5776 }, /* pale violet red */
+ { 238, 232, 170, 5792 }, /* PaleGoldenrod */
+ { 152, 251, 152, 5806 }, /* PaleGreen */
+ { 154, 255, 154, 5816 }, /* PaleGreen1 */
+ { 144, 238, 144, 5827 }, /* PaleGreen2 */
+ { 124, 205, 124, 5838 }, /* PaleGreen3 */
+ { 84, 139, 84, 5849 }, /* PaleGreen4 */
+ { 175, 238, 238, 5860 }, /* PaleTurquoise */
+ { 187, 255, 255, 5874 }, /* PaleTurquoise1 */
+ { 174, 238, 238, 5889 }, /* PaleTurquoise2 */
+ { 150, 205, 205, 5904 }, /* PaleTurquoise3 */
+ { 102, 139, 139, 5919 }, /* PaleTurquoise4 */
+ { 219, 112, 147, 5934 }, /* PaleVioletRed */
+ { 255, 130, 171, 5948 }, /* PaleVioletRed1 */
+ { 238, 121, 159, 5963 }, /* PaleVioletRed2 */
+ { 205, 104, 137, 5978 }, /* PaleVioletRed3 */
+ { 139, 71, 93, 5993 }, /* PaleVioletRed4 */
+ { 255, 239, 213, 6008 }, /* papaya whip */
+ { 255, 239, 213, 6020 }, /* PapayaWhip */
+ { 255, 218, 185, 6031 }, /* peach puff */
+ { 255, 218, 185, 6042 }, /* PeachPuff */
+ { 255, 218, 185, 6052 }, /* PeachPuff1 */
+ { 238, 203, 173, 6063 }, /* PeachPuff2 */
+ { 205, 175, 149, 6074 }, /* PeachPuff3 */
+ { 139, 119, 101, 6085 }, /* PeachPuff4 */
+ { 205, 133, 63, 6096 }, /* peru */
+ { 255, 192, 203, 6101 }, /* pink */
+ { 255, 181, 197, 6106 }, /* pink1 */
+ { 238, 169, 184, 6112 }, /* pink2 */
+ { 205, 145, 158, 6118 }, /* pink3 */
+ { 139, 99, 108, 6124 }, /* pink4 */
+ { 221, 160, 221, 6130 }, /* plum */
+ { 255, 187, 255, 6135 }, /* plum1 */
+ { 238, 174, 238, 6141 }, /* plum2 */
+ { 205, 150, 205, 6147 }, /* plum3 */
+ { 139, 102, 139, 6153 }, /* plum4 */
+ { 176, 224, 230, 6159 }, /* powder blue */
+ { 176, 224, 230, 6171 }, /* PowderBlue */
+ { 160, 32, 240, 6182 }, /* purple */
+ { 155, 48, 255, 6189 }, /* purple1 */
+ { 145, 44, 238, 6197 }, /* purple2 */
+ { 125, 38, 205, 6205 }, /* purple3 */
+ { 85, 26, 139, 6213 }, /* purple4 */
+ { 255, 0, 0, 6221 }, /* red */
+ { 255, 0, 0, 6225 }, /* red1 */
+ { 238, 0, 0, 6230 }, /* red2 */
+ { 205, 0, 0, 6235 }, /* red3 */
+ { 139, 0, 0, 6240 }, /* red4 */
+ { 188, 143, 143, 6245 }, /* rosy brown */
+ { 188, 143, 143, 6256 }, /* RosyBrown */
+ { 255, 193, 193, 6266 }, /* RosyBrown1 */
+ { 238, 180, 180, 6277 }, /* RosyBrown2 */
+ { 205, 155, 155, 6288 }, /* RosyBrown3 */
+ { 139, 105, 105, 6299 }, /* RosyBrown4 */
+ { 65, 105, 225, 6310 }, /* royal blue */
+ { 65, 105, 225, 6321 }, /* RoyalBlue */
+ { 72, 118, 255, 6331 }, /* RoyalBlue1 */
+ { 67, 110, 238, 6342 }, /* RoyalBlue2 */
+ { 58, 95, 205, 6353 }, /* RoyalBlue3 */
+ { 39, 64, 139, 6364 }, /* RoyalBlue4 */
+ { 139, 69, 19, 6375 }, /* saddle brown */
+ { 139, 69, 19, 6388 }, /* SaddleBrown */
+ { 250, 128, 114, 6400 }, /* salmon */
+ { 255, 140, 105, 6407 }, /* salmon1 */
+ { 238, 130, 98, 6415 }, /* salmon2 */
+ { 205, 112, 84, 6423 }, /* salmon3 */
+ { 139, 76, 57, 6431 }, /* salmon4 */
+ { 244, 164, 96, 6439 }, /* sandy brown */
+ { 244, 164, 96, 6451 }, /* SandyBrown */
+ { 46, 139, 87, 6462 }, /* sea green */
+ { 46, 139, 87, 6472 }, /* SeaGreen */
+ { 84, 255, 159, 6481 }, /* SeaGreen1 */
+ { 78, 238, 148, 6491 }, /* SeaGreen2 */
+ { 67, 205, 128, 6501 }, /* SeaGreen3 */
+ { 46, 139, 87, 6511 }, /* SeaGreen4 */
+ { 255, 245, 238, 6521 }, /* seashell */
+ { 255, 245, 238, 6530 }, /* seashell1 */
+ { 238, 229, 222, 6540 }, /* seashell2 */
+ { 205, 197, 191, 6550 }, /* seashell3 */
+ { 139, 134, 130, 6560 }, /* seashell4 */
+ { 160, 82, 45, 6570 }, /* sienna */
+ { 255, 130, 71, 6577 }, /* sienna1 */
+ { 238, 121, 66, 6585 }, /* sienna2 */
+ { 205, 104, 57, 6593 }, /* sienna3 */
+ { 139, 71, 38, 6601 }, /* sienna4 */
+ { 135, 206, 235, 6609 }, /* sky blue */
+ { 135, 206, 235, 6618 }, /* SkyBlue */
+ { 135, 206, 255, 6626 }, /* SkyBlue1 */
+ { 126, 192, 238, 6635 }, /* SkyBlue2 */
+ { 108, 166, 205, 6644 }, /* SkyBlue3 */
+ { 74, 112, 139, 6653 }, /* SkyBlue4 */
+ { 106, 90, 205, 6662 }, /* slate blue */
+ { 112, 128, 144, 6673 }, /* slate gray */
+ { 112, 128, 144, 6684 }, /* slate grey */
+ { 106, 90, 205, 6695 }, /* SlateBlue */
+ { 131, 111, 255, 6705 }, /* SlateBlue1 */
+ { 122, 103, 238, 6716 }, /* SlateBlue2 */
+ { 105, 89, 205, 6727 }, /* SlateBlue3 */
+ { 71, 60, 139, 6738 }, /* SlateBlue4 */
+ { 112, 128, 144, 6749 }, /* SlateGray */
+ { 198, 226, 255, 6759 }, /* SlateGray1 */
+ { 185, 211, 238, 6770 }, /* SlateGray2 */
+ { 159, 182, 205, 6781 }, /* SlateGray3 */
+ { 108, 123, 139, 6792 }, /* SlateGray4 */
+ { 112, 128, 144, 6803 }, /* SlateGrey */
+ { 255, 250, 250, 6813 }, /* snow */
+ { 255, 250, 250, 6818 }, /* snow1 */
+ { 238, 233, 233, 6824 }, /* snow2 */
+ { 205, 201, 201, 6830 }, /* snow3 */
+ { 139, 137, 137, 6836 }, /* snow4 */
+ { 0, 255, 127, 6842 }, /* spring green */
+ { 0, 255, 127, 6855 }, /* SpringGreen */
+ { 0, 255, 127, 6867 }, /* SpringGreen1 */
+ { 0, 238, 118, 6880 }, /* SpringGreen2 */
+ { 0, 205, 102, 6893 }, /* SpringGreen3 */
+ { 0, 139, 69, 6906 }, /* SpringGreen4 */
+ { 70, 130, 180, 6919 }, /* steel blue */
+ { 70, 130, 180, 6930 }, /* SteelBlue */
+ { 99, 184, 255, 6940 }, /* SteelBlue1 */
+ { 92, 172, 238, 6951 }, /* SteelBlue2 */
+ { 79, 148, 205, 6962 }, /* SteelBlue3 */
+ { 54, 100, 139, 6973 }, /* SteelBlue4 */
+ { 210, 180, 140, 6984 }, /* tan */
+ { 255, 165, 79, 6988 }, /* tan1 */
+ { 238, 154, 73, 6993 }, /* tan2 */
+ { 205, 133, 63, 6998 }, /* tan3 */
+ { 139, 90, 43, 7003 }, /* tan4 */
+ { 216, 191, 216, 7008 }, /* thistle */
+ { 255, 225, 255, 7016 }, /* thistle1 */
+ { 238, 210, 238, 7025 }, /* thistle2 */
+ { 205, 181, 205, 7034 }, /* thistle3 */
+ { 139, 123, 139, 7043 }, /* thistle4 */
+ { 255, 99, 71, 7052 }, /* tomato */
+ { 255, 99, 71, 7059 }, /* tomato1 */
+ { 238, 92, 66, 7067 }, /* tomato2 */
+ { 205, 79, 57, 7075 }, /* tomato3 */
+ { 139, 54, 38, 7083 }, /* tomato4 */
+ { 64, 224, 208, 7091 }, /* turquoise */
+ { 0, 245, 255, 7101 }, /* turquoise1 */
+ { 0, 229, 238, 7112 }, /* turquoise2 */
+ { 0, 197, 205, 7123 }, /* turquoise3 */
+ { 0, 134, 139, 7134 }, /* turquoise4 */
+ { 238, 130, 238, 7145 }, /* violet */
+ { 208, 32, 144, 7152 }, /* violet red */
+ { 208, 32, 144, 7163 }, /* VioletRed */
+ { 255, 62, 150, 7173 }, /* VioletRed1 */
+ { 238, 58, 140, 7184 }, /* VioletRed2 */
+ { 205, 50, 120, 7195 }, /* VioletRed3 */
+ { 139, 34, 82, 7206 }, /* VioletRed4 */
+ { 245, 222, 179, 7217 }, /* wheat */
+ { 255, 231, 186, 7223 }, /* wheat1 */
+ { 238, 216, 174, 7230 }, /* wheat2 */
+ { 205, 186, 150, 7237 }, /* wheat3 */
+ { 139, 126, 102, 7244 }, /* wheat4 */
+ { 255, 255, 255, 7251 }, /* white */
+ { 245, 245, 245, 7257 }, /* white smoke */
+ { 245, 245, 245, 7269 }, /* WhiteSmoke */
+ { 255, 255, 0, 7280 }, /* yellow */
+ { 154, 205, 50, 7287 }, /* yellow green */
+ { 255, 255, 0, 7300 }, /* yellow1 */
+ { 238, 238, 0, 7308 }, /* yellow2 */
+ { 205, 205, 0, 7316 }, /* yellow3 */
+ { 139, 139, 0, 7324 }, /* yellow4 */
+ { 154, 205, 50, 7332 }, /* 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/os/osdep.h b/os/osdep.h
new file mode 100644
index 0000000..087e36d
--- /dev/null
+++ b/os/osdep.h
@@ -0,0 +1,288 @@
+/***********************************************************
+
+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 BOTIMEOUT 200 /* in milliseconds */
+#define BUFSIZE 4096
+#define BUFWATERMARK 8192
+
+#if defined(XDMCP) || defined(HASXDMAUTH)
+#include <X11/Xdmcp.h>
+#endif
+
+#ifdef _POSIX_SOURCE
+#include <limits.h>
+#else
+#define _POSIX_SOURCE
+#include <limits.h>
+#undef _POSIX_SOURCE
+#endif
+
+#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 <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)
+
+#ifndef HAS_GETDTABLESIZE
+#if !defined(SVR4) && !defined(SYSV)
+#define HAS_GETDTABLESIZE
+#endif
+#endif
+
+#include <stddef.h>
+
+#if defined(XDMCP) || defined(HASXDMAUTH)
+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, const char *name,
+ unsigned data_length, char *data);
+#endif
+
+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, const char *data, XID id
+typedef int (*AuthAddCFunc) (AuthAddCArgs);
+
+#define AuthCheckArgs unsigned short data_length, const 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, const char *data, XID id, unsigned *data_length_return, char **data_return
+typedef XID (*AuthGenCFunc) (AuthGenCArgs);
+
+#define AuthRemCArgs unsigned short data_length, const 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 */
+ Bool local_client;
+} OsCommRec, *OsCommPtr;
+
+extern int FlushClient(
+ ClientPtr /*who*/,
+ OsCommPtr /*oc*/,
+ const void * /*extraBuf*/,
+ int /*extraCount*/
+);
+
+extern void FreeOsBuffers(
+ OsCommPtr /*oc*/
+);
+
+#include "dix.h"
+
+extern fd_set AllSockets;
+extern fd_set AllClients;
+extern fd_set LastSelectMask;
+extern fd_set WellKnownConnections;
+extern fd_set EnabledDevices;
+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(void);
+#endif
+
+extern Bool NewOutputPending;
+extern Bool AnyClientsWriteBlocked;
+
+extern WorkQueuePtr workQueue;
+
+/* in WaitFor.c */
+#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
+
+#ifdef XDMCP
+/* in xdmcp.c */
+extern void XdmcpUseMsg (void);
+extern int XdmcpOptions(int argc, char **argv, int i);
+extern void XdmcpRegisterConnection (
+ int type,
+ const char *address,
+ int addrlen);
+extern void XdmcpRegisterAuthorizations (void);
+extern void XdmcpRegisterAuthorization (const char *name, int namelen);
+extern void XdmcpInit (void);
+extern void XdmcpReset (void);
+extern void XdmcpOpenDisplay(int sock);
+extern void XdmcpCloseDisplay(int sock);
+extern void XdmcpRegisterAuthentication (
+ const char *name,
+ int namelen,
+ const char *data,
+ int datalen,
+ ValidatorFunc Validator,
+ GeneratorFunc Generator,
+ AddAuthorFunc AddAuth);
+
+struct sockaddr_in;
+extern void XdmcpRegisterBroadcastAddress (const struct sockaddr_in *addr);
+#endif
+
+#ifdef HASXDMAUTH
+extern void XdmAuthenticationInit (const char *cookie, int cookie_length);
+#endif
+
+#endif /* _OSDEP_H_ */
diff --git a/os/osinit.c b/os/osinit.c
new file mode 100644
index 0000000..018e404
--- /dev/null
+++ b/os/osinit.c
@@ -0,0 +1,315 @@
+/***********************************************************
+
+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 <X11/X.h>
+#include "os.h"
+#include "osdep.h"
+#include <X11/Xos.h>
+#include <signal.h>
+#include <errno.h>
+#ifdef HAVE_DLFCN_H
+# include <dlfcn.h>
+#endif
+#ifdef HAVE_BACKTRACE
+#include <execinfo.h>
+#endif
+
+
+#include "dixstruct.h"
+
+#ifndef PATH_MAX
+#ifdef MAXPATHLEN
+#define PATH_MAX MAXPATHLEN
+#else
+#define PATH_MAX 1024
+#endif
+#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
+
+static OsSigWrapperPtr OsSigWrapper = NULL;
+
+OsSigWrapperPtr
+OsRegisterSigWrapper(OsSigWrapperPtr newSigWrapper)
+{
+ OsSigWrapperPtr oldSigWrapper = OsSigWrapper;
+
+ OsSigWrapper = newSigWrapper;
+
+ return oldSigWrapper;
+}
+
+/*
+ * OsSigHandler --
+ * Catch unexpected signals and exit or continue cleanly.
+ */
+static void
+#ifdef SA_SIGINFO
+OsSigHandler(int signo, siginfo_t *sip, void *unused)
+#else
+OsSigHandler(int signo)
+#endif
+{
+#ifdef RTLD_DI_SETSIGNAL
+ const char *dlerr = dlerror();
+
+ if (dlerr) {
+ LogMessage(X_ERROR, "Dynamic loader error: %s\n", dlerr);
+ }
+#endif /* RTLD_DI_SETSIGNAL */
+
+ if (OsSigWrapper != NULL) {
+ if (OsSigWrapper(signo) == 0) {
+ /* ddx handled signal and wants us to continue */
+ return;
+ }
+ }
+
+ /* log, cleanup, and abort */
+ xorg_backtrace();
+
+#ifdef SA_SIGINFO
+ if (sip->si_code == SI_USER) {
+ ErrorF("Recieved signal %d sent by process %ld, uid %ld\n",
+ signo, (long) sip->si_pid, (long) sip->si_uid);
+ } else {
+ switch (signo) {
+ case SIGSEGV:
+ case SIGBUS:
+ case SIGILL:
+ case SIGFPE:
+ ErrorF("%s at address %p\n", strsignal(signo), sip->si_addr);
+ }
+ }
+#endif
+
+ FatalError("Caught signal %d (%s). Server aborting\n",
+ signo, strsignal(signo));
+}
+
+void
+OsInit(void)
+{
+ static Bool been_here = FALSE;
+ static char* devnull = "/dev/null";
+ char fname[PATH_MAX];
+
+ if (!been_here) {
+ struct sigaction act, oact;
+ int i;
+ int siglist[] = { SIGSEGV, SIGQUIT, SIGILL, SIGFPE, SIGBUS,
+ SIGSYS,
+ SIGXCPU,
+ SIGXFSZ,
+#ifdef SIGEMT
+ SIGEMT,
+#endif
+ 0 /* must be last */ };
+ sigemptyset(&act.sa_mask);
+#ifdef SA_SIGINFO
+ act.sa_sigaction = OsSigHandler;
+ act.sa_flags = SA_SIGINFO;
+#else
+ act.sa_handler = OsSigHandler;
+ act.sa_flags = 0;
+#endif
+ for (i = 0; siglist[i] != 0; i++) {
+ if (sigaction(siglist[i], &act, &oact)) {
+ ErrorF("failed to install signal handler for signal %d: %s\n",
+ siglist[i], strerror(errno));
+ }
+ }
+#ifdef HAVE_BACKTRACE
+ /*
+ * initialize the backtracer, since the ctor calls dlopen(), which
+ * calls malloc(), which isn't signal-safe.
+ */
+ do {
+ void *array;
+ backtrace(&array, 1);
+ } while (0);
+#endif
+
+#ifdef RTLD_DI_SETSIGNAL
+ /* Tell runtime linker to send a signal we can catch instead of SIGKILL
+ * for failures to load libraries/modules at runtime so we can clean up
+ * after ourselves.
+ */
+ int failure_signal = SIGQUIT;
+ dlinfo(RTLD_SELF, RTLD_DI_SETSIGNAL, &failure_signal);
+#endif
+
+#if !defined(__CYGWIN__)
+ 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
+ }
+
+ if (getpgrp () == 0)
+ setpgid (0, 0);
+
+#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;
+ (void)setrlimit(RLIMIT_NOFILE, &rlim);
+ }
+ }
+#endif
+ LockServer();
+ been_here = TRUE;
+ }
+ TimerInit();
+ OsVendorInit();
+ /*
+ * 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 ();
+}
+
+void
+OsCleanup(Bool terminating)
+{
+ if (terminating)
+ {
+ UnlockServer();
+ }
+}
diff --git a/os/rpcauth.c b/os/rpcauth.c
new file mode 100644
index 0000000..ad6ebf9
--- /dev/null
+++ b/os/rpcauth.c
@@ -0,0 +1,193 @@
+/*
+
+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 <X11/X.h>
+#include <X11/Xauth.h>
+#include "misc.h"
+#include "os.h"
+#include "osdep.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
+
+static enum auth_stat why;
+
+static char *
+authdes_ezdecode(const 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 = malloc(len);
+ 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 = 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,
+ pointer closure
+)
+{
+ return (len == strlen ((char *) closure) &&
+ strncmp ((char *) addr, (char *) closure, len) == 0);
+}
+
+static char rpc_error[MAXNETNAMELEN+50];
+
+_X_HIDDEN XID
+SecureRPCCheck (unsigned short data_length, const 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;
+}
+
+_X_HIDDEN void
+SecureRPCInit (void)
+{
+ if (rpc_id == ~0L)
+ AddAuthorization (9, "SUN-DES-1", 0, (char *) 0);
+}
+
+_X_HIDDEN int
+SecureRPCAdd (unsigned short data_length, const char *data, XID id)
+{
+ if (data_length)
+ AddHost ((pointer) 0, FamilyNetname, data_length, data);
+ rpc_id = id;
+ return 1;
+}
+
+_X_HIDDEN int
+SecureRPCReset (void)
+{
+ rpc_id = (XID) ~0L;
+ return 1;
+}
+
+_X_HIDDEN XID
+SecureRPCToID (unsigned short data_length, char *data)
+{
+ return rpc_id;
+}
+
+_X_HIDDEN int
+SecureRPCFromID (XID id, unsigned short *data_lenp, char **datap)
+{
+ return 0;
+}
+
+_X_HIDDEN int
+SecureRPCRemove (unsigned short data_length, const char *data)
+{
+ return 0;
+}
+#endif /* SECURE_RPC */
diff --git a/os/strcasecmp.c b/os/strcasecmp.c
new file mode 100644
index 0000000..ad6da6a
--- /dev/null
+++ b/os/strcasecmp.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 1987, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <ctype.h>
+#include "dix.h"
+
+#ifdef NEED_STRCASECMP
+int
+xstrcasecmp(const char *str1, const char *str2)
+{
+ const u_char *us1 = (const u_char *)str1, *us2 = (const u_char *)str2;
+
+ while (tolower(*us1) == tolower(*us2)) {
+ if (*us1++ == '\0')
+ return 0;
+ us2++;
+ }
+
+ return (tolower(*us1) - tolower(*us2));
+}
+#endif
+
+#ifdef NEED_STRNCASECMP
+int
+xstrncasecmp(const char *s1, const char *s2, size_t n)
+{
+ if (n != 0) {
+ const u_char *us1 = (const u_char *)s1, *us2 = (const u_char *)s2;
+
+ do {
+ if (tolower(*us1) != tolower(*us2++))
+ return (tolower(*us1) - tolower(*--us2));
+ if (*us1++ == '\0')
+ break;
+ } while (--n != 0);
+ }
+
+ return 0;
+}
+#endif
diff --git a/os/strcasestr.c b/os/strcasestr.c
new file mode 100644
index 0000000..f89b2f2
--- /dev/null
+++ b/os/strcasestr.c
@@ -0,0 +1,64 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <ctype.h>
+#include <string.h>
+#include "dix.h"
+
+/*
+ * Find the first occurrence of find in s, ignore case.
+ */
+#ifdef NEED_STRCASESTR
+char *
+xstrcasestr(const char *s, const char *find)
+{
+ char c, sc;
+ size_t len;
+
+ if ((c = *find++) != 0) {
+ c = tolower((unsigned char)c);
+ len = strlen(find);
+ do {
+ do {
+ if ((sc = *s++) == 0)
+ return NULL;
+ } while ((char)tolower((unsigned char)sc) != c);
+ } while (strncasecmp(s, find, len) != 0);
+ s--;
+ }
+ return ((char *)s);
+}
+#endif
diff --git a/os/strlcat.c b/os/strlcat.c
new file mode 100644
index 0000000..7d53b0a
--- /dev/null
+++ b/os/strlcat.c
@@ -0,0 +1,59 @@
+/*
+ * 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_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <sys/types.h>
+#include <string.h>
+#include "os.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/os/strlcpy.c b/os/strlcpy.c
new file mode 100644
index 0000000..2e55b2e
--- /dev/null
+++ b/os/strlcpy.c
@@ -0,0 +1,54 @@
+/*
+ * 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_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <sys/types.h>
+#include <string.h>
+#include "os.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/os/utils.c b/os/utils.c
new file mode 100644
index 0000000..fc72787
--- /dev/null
+++ b/os/utils.c
@@ -0,0 +1,1825 @@
+/*
+
+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>
+/*
+ Sigh... We really need a prototype for this to know it is stdcall,
+ but #include-ing <windows.h> here is not a good idea...
+*/
+__stdcall unsigned long GetTickCount(void);
+#endif
+
+#if defined(WIN32) && !defined(__CYGWIN__)
+#include <X11/Xwinsock.h>
+#endif
+#include <X11/Xos.h>
+#include <stdio.h>
+#include <time.h>
+#if !defined(WIN32) || !defined(__MINGW32__)
+#include <sys/time.h>
+#include <sys/resource.h>
+#endif
+#include "misc.h"
+#include <X11/X.h>
+#define XSERV_t
+#define TRANS_SERVER
+#define TRANS_REOPEN
+#include <X11/Xtrans/Xtrans.h>
+#include "input.h"
+#include "dixfont.h"
+#include "osdep.h"
+#include "extension.h"
+#ifdef X_POSIX_C_SOURCE
+#define _POSIX_C_SOURCE X_POSIX_C_SOURCE
+#include <signal.h>
+#undef _POSIX_C_SOURCE
+#else
+#if 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 <sys/stat.h>
+#include <ctype.h> /* for isspace */
+#include <stdarg.h>
+
+#include <stdlib.h> /* for malloc() */
+
+#if defined(TCPCONN) || defined(STREAMSCONN)
+# ifndef WIN32
+# include <netdb.h>
+# endif
+#endif
+
+#include "opaque.h"
+
+#include "dixstruct.h"
+
+#include "xkbsrv.h"
+
+#include "picture.h"
+
+Bool noTestExtensions;
+#ifdef COMPOSITE
+Bool noCompositeExtension = FALSE;
+#endif
+
+#ifdef DAMAGE
+Bool noDamageExtension = FALSE;
+#endif
+#ifdef DBE
+Bool noDbeExtension = FALSE;
+#endif
+#ifdef DPMSExtension
+Bool noDPMSExtension = FALSE;
+#endif
+#ifdef GLXEXT
+Bool noGlxExtension = FALSE;
+Bool noGlxVisualInit = FALSE;
+#endif
+#ifdef SCREENSAVER
+Bool noScreenSaverExtension = FALSE;
+#endif
+#ifdef MITSHM
+Bool noMITShmExtension = FALSE;
+#endif
+#ifdef RANDR
+Bool noRRExtension = FALSE;
+#endif
+Bool noRenderExtension = FALSE;
+#ifdef XCSECURITY
+Bool noSecurityExtension = FALSE;
+#endif
+#ifdef RES
+Bool noResExtension = FALSE;
+#endif
+#ifdef XF86BIGFONT
+Bool noXFree86BigfontExtension = FALSE;
+#endif
+#ifdef XFreeXDGA
+Bool noXFree86DGAExtension = FALSE;
+#endif
+#ifdef XF86DRI
+Bool noXFree86DRIExtension = FALSE;
+#endif
+#ifdef XF86VIDMODE
+Bool noXFree86VidModeExtension = FALSE;
+#endif
+#ifdef XFIXES
+Bool noXFixesExtension = FALSE;
+#endif
+#ifdef PANORAMIX
+/* Xinerama is disabled by default unless enabled via +xinerama */
+Bool noPanoramiXExtension = TRUE;
+#endif
+#ifdef XSELINUX
+Bool noSELinuxExtension = FALSE;
+int selinuxEnforcingState = SELINUX_MODE_DEFAULT;
+#endif
+#ifdef XV
+Bool noXvExtension = FALSE;
+#endif
+#ifdef DRI2
+Bool noDRI2Extension = FALSE;
+#endif
+
+Bool noGEExtension = FALSE;
+
+#define X_INCLUDE_NETDB_H
+#include <X11/Xos_r.h>
+
+#include <errno.h>
+
+Bool CoreDump;
+
+#ifdef PANORAMIX
+Bool PanoramiXExtensionDisabledHack = FALSE;
+#endif
+
+int auditTrailLevel = 1;
+
+#if defined(SVR4) || defined(__linux__) || defined(CSRG_BASED)
+#define HAS_SAVED_IDS_AND_SETEUID
+#endif
+
+OsSigHandlerPtr
+OsSignal(int sig, OsSigHandlerPtr handler)
+{
+ 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;
+}
+
+/*
+ * 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) 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());
+ (void) write(lfd, pid_str, 11);
+ (void) chmod(tmp, 0444);
+ (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);
+ 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) return;
+
+ if (!StillLocking){
+
+ (void) unlink(LockFile);
+ }
+}
+
+/* Force connections to close on SIGHUP from init */
+
+void
+AutoResetServer (int sig)
+{
+ int olderrno = errno;
+
+ dispatchException |= DE_RESET;
+ isItTimeToYield = TRUE;
+ errno = olderrno;
+}
+
+/* Force connections to close and then exit on SIGTERM, SIGINT */
+
+void
+GiveUp(int sig)
+{
+ int olderrno = errno;
+
+ dispatchException |= DE_TERMINATE;
+ isItTimeToYield = TRUE;
+ errno = olderrno;
+}
+
+#if (defined WIN32 && defined __MINGW32__) || defined(__CYGWIN__)
+CARD32
+GetTimeInMillis (void)
+{
+ return GetTickCount ();
+}
+#else
+CARD32
+GetTimeInMillis(void)
+{
+ struct timeval tv;
+
+#ifdef MONOTONIC_CLOCK
+ struct timespec tp;
+ static clockid_t clockid;
+ if (!clockid) {
+#ifdef CLOCK_MONOTONIC_COARSE
+ if (clock_getres(CLOCK_MONOTONIC_COARSE, &tp) == 0 &&
+ (tp.tv_nsec / 1000) <= 1000 &&
+ clock_gettime(CLOCK_MONOTONIC_COARSE, &tp) == 0)
+ clockid = CLOCK_MONOTONIC_COARSE;
+ else
+#endif
+ if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
+ clockid = CLOCK_MONOTONIC;
+ else
+ clockid = ~0L;
+ }
+ if (clockid != ~0L && clock_gettime(clockid, &tp) == 0)
+ return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L);
+#endif
+
+ X_GETTIMEOFDAY(&tv);
+ return(tv.tv_sec * 1000) + (tv.tv_usec / 1000);
+}
+#endif
+
+void
+AdjustWaitForDelay (pointer 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 # default pointer acceleration (factor)\n");
+ ErrorF("-ac disable access control restrictions\n");
+ ErrorF("-audit int set audit trail level\n");
+ ErrorF("-auth file select authorization file\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");
+ ErrorF("-nocursor disable the cursor\n");
+ ErrorF("-core generate core dump on fatal error\n");
+ ErrorF("-dpi int screen resolution in dots per inch\n");
+#ifdef DPMSExtension
+ 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
+ ErrorF("-nolock disable the locking mechanism\n");
+ ErrorF("-nolisten string don't listen on protocol\n");
+ ErrorF("-noreset don't reset after last client exists\n");
+ ErrorF("-background [none] create root window with no background\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");
+ ErrorF("-render [default|mono|gray|color] set render color alloc policy\n");
+ ErrorF("-retro start with classic stipple and cursor\n");
+ ErrorF("-s # screen-saver timeout (minutes)\n");
+ ErrorF("-t # default pointer threshold (pixels/t)\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("-wr create root window with white background\n");
+ ErrorF("-maxbigreqsize set maximal bigrequest size \n");
+#ifdef PANORAMIX
+ ErrorF("+xinerama Enable XINERAMA extension\n");
+ ErrorF("-xinerama Disable XINERAMA extension\n");
+#endif
+ ErrorF("-dumbSched Disable smart scheduling, enable old behavior\n");
+ ErrorF("-schedInterval int Set scheduler interval in msec\n");
+ ErrorF("-sigstop Enable SIGSTOP based startup\n");
+ ErrorF("+extension name Enable extension\n");
+ ErrorF("-extension name Disable extension\n");
+#ifdef XDMCP
+ XdmcpUseMsg();
+#endif
+ XkbUseMsg();
+ 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 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];
+ 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;
+ }
+ 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], "-br") == 0) ; /* default */
+ 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)
+ {
+#if !defined(WIN32) || !defined(__MINGW32__)
+ struct rlimit core_limit;
+ getrlimit (RLIMIT_CORE, &core_limit);
+ core_limit.rlim_cur = core_limit.rlim_max;
+ setrlimit (RLIMIT_CORE, &core_limit);
+#endif
+ CoreDump = TRUE;
+ }
+ else if ( strcmp( argv[i], "-nocursor") == 0)
+ {
+ EnableCursor = FALSE;
+ }
+ else if ( strcmp( argv[i], "-dpi") == 0)
+ {
+ if(++i < argc)
+ monitorResolution = atoi(argv[i]);
+ else
+ UseMsg();
+ }
+#ifdef DPMSExtension
+ else if ( strcmp( argv[i], "dpms") == 0)
+ /* ignored for compatibility */ ;
+ else if ( strcmp( argv[i], "-dpms") == 0)
+ DPMSDisabledSwitch = TRUE;
+#endif
+ else if ( strcmp( argv[i], "-deferglyphs") == 0)
+ {
+ if(++i >= argc || !ParseGlyphCachingMode(argv[i]))
+ 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);
+ }
+ else if ( (skip=XkbProcessArguments(argc,argv,i))!=0 ) {
+ if (skip>0)
+ i+= skip-1;
+ else UseMsg();
+ }
+#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
+ 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;
+ }
+ else if ( strcmp( argv[i], "-nolisten") == 0)
+ {
+ if(++i < argc) {
+ 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], "-pogo") == 0)
+ {
+ dispatchException = DE_TERMINATE;
+ }
+ 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], "-retro") == 0)
+ party_like_its_1989 = TRUE;
+ 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], "-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], "-wr") == 0)
+ whiteRoot = TRUE;
+ else if ( strcmp( argv[i], "-background") == 0) {
+ if(++i < argc) {
+ if (!strcmp ( argv[i], "none"))
+ bgNoneRoot = TRUE;
+ else
+ UseMsg();
+ }
+ }
+ 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
+ else if ( strcmp( argv[i], "-I") == 0)
+ {
+ /* ignore all remaining arguments */
+ break;
+ }
+ else if (strncmp (argv[i], "tty", 3) == 0)
+ {
+ /* init supplies us with this useless information */
+ }
+#ifdef XDMCP
+ else if ((skip = XdmcpOptions(argc, argv, i)) != i)
+ {
+ i = skip - 1;
+ }
+#endif
+ else if ( strcmp( argv[i], "-dumbSched") == 0)
+ {
+ SmartScheduleDisable = TRUE;
+ }
+ 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();
+ }
+ else if ( strcmp( argv[i], "-render" ) == 0)
+ {
+ if (++i < argc)
+ {
+ int policy = PictureParseCmapPolicy (argv[i]);
+
+ if (policy != PictureCmapPolicyInvalid)
+ PictureCmapPolicy = policy;
+ else
+ UseMsg ();
+ }
+ else
+ UseMsg ();
+ }
+ else if ( strcmp( argv[i], "-sigstop") == 0)
+ {
+ RunFromSigStopParent = TRUE;
+ }
+ 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]);
+ }
+ }
+}
+
+/* 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, pointer client)
+{
+#define AUTHORIZATION_NAME "hp-hostname-1"
+#if defined(TCPCONN) || defined(STREAMSCONN)
+ 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)
+ memset(&hints, 0, 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 */
+}
+
+void *
+Xalloc(unsigned long amount)
+{
+ /*
+ * Xalloc used to return NULL when large amount of memory is requested. In
+ * order to catch the buggy callers this warning has been added, slated to
+ * removal by anyone who touches this code (or just looks at it) in 2011.
+ *
+ * -- Mikhail Gusarov
+ */
+ if ((long)amount <= 0)
+ ErrorF("Warning: Xalloc: "
+ "requesting unpleasantly large amount of memory: %lu bytes.\n",
+ amount);
+
+ return malloc(amount);
+}
+
+void *
+XNFalloc(unsigned long amount)
+{
+ void *ptr = malloc(amount);
+ if (!ptr)
+ FatalError("Out of memory");
+ return ptr;
+}
+
+void *
+Xcalloc(unsigned long amount)
+{
+ return calloc(1, amount);
+}
+
+void *
+XNFcalloc(unsigned long amount)
+{
+ void *ret = calloc(1, amount);
+ if (!ret)
+ FatalError("XNFcalloc: Out of memory");
+ return ret;
+}
+
+void *
+Xrealloc(void *ptr, unsigned long amount)
+{
+ /*
+ * Xrealloc used to return NULL when large amount of memory is requested. In
+ * order to catch the buggy callers this warning has been added, slated to
+ * removal by anyone who touches this code (or just looks at it) in 2011.
+ *
+ * -- Mikhail Gusarov
+ */
+ if ((long)amount <= 0)
+ ErrorF("Warning: Xrealloc: "
+ "requesting unpleasantly large amount of memory: %lu bytes.\n",
+ amount);
+
+ return realloc(ptr, amount);
+}
+
+void *
+XNFrealloc(void *ptr, unsigned long amount)
+{
+ void *ret = realloc(ptr, amount);
+ if (!ret)
+ FatalError("XNFrealloc: Out of memory");
+ return ret;
+}
+
+void
+Xfree(void *ptr)
+{
+ free(ptr);
+}
+
+
+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)
+{
+ struct itimerval timer;
+
+ if (SmartScheduleDisable)
+ return;
+ 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);
+}
+
+void
+SmartScheduleStartTimer (void)
+{
+ struct itimerval timer;
+
+ if (SmartScheduleDisable)
+ return;
+ 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);
+}
+
+static void
+SmartScheduleTimer (int sig)
+{
+ SmartScheduleTime += SmartScheduleInterval;
+}
+
+void
+SmartScheduleInit (void)
+{
+ struct sigaction act;
+
+ if (SmartScheduleDisable)
+ return;
+
+ memset((char *) &act, 0, sizeof(struct sigaction));
+
+ /* Set up the timer signal function */
+ act.sa_handler = SmartScheduleTimer;
+ sigemptyset (&act.sa_mask);
+ sigaddset (&act.sa_mask, SIGALRM);
+ if (sigaction (SIGALRM, &act, 0) < 0)
+ {
+ perror ("sigaction for smart scheduler");
+ SmartScheduleDisable = TRUE;
+ }
+}
+
+#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);
+ sigaddset (&set, SIGALRM);
+ sigaddset (&set, SIGVTALRM);
+#ifdef SIGWINCH
+ sigaddset (&set, SIGWINCH);
+#endif
+#ifdef SIGIO
+ sigaddset (&set, SIGIO);
+#endif
+ sigaddset (&set, SIGTSTP);
+ sigaddset (&set, SIGTTIN);
+ sigaddset (&set, SIGTTOU);
+ sigaddset (&set, SIGCHLD);
+ sigprocmask (SIG_BLOCK, &set, &PreviousSignalMask);
+ }
+#endif
+}
+
+void
+OsReleaseSignals (void)
+{
+#ifdef SIG_BLOCK
+ if (--BlockedSignalCount == 0)
+ {
+ sigprocmask (SIG_SETMASK, &PreviousSignalMask, 0);
+ }
+#endif
+}
+
+/*
+ * Pending signals may interfere with core dumping. Provide a
+ * mechanism to block signals when aborting.
+ */
+
+void
+OsAbort (void)
+{
+#ifndef __APPLE__
+ OsBlockSignals();
+#endif
+ abort();
+}
+
+#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;
+ void (*csig)(int);
+ int status;
+
+ if (!command)
+ return 1;
+
+ csig = signal(SIGCHLD, SIG_DFL);
+ if (csig == SIG_ERR) {
+ perror("signal");
+ return -1;
+ }
+ DebugF("System: `%s'\n", command);
+
+ switch (pid = fork()) {
+ case -1: /* error */
+ p = -1;
+ case 0: /* child */
+ 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);
+
+ }
+
+ if (signal(SIGCHLD, csig) == SIG_ERR) {
+ perror("signal");
+ return -1;
+ }
+
+ return p == -1 ? -1 : status;
+}
+
+static struct pid {
+ struct pid *next;
+ FILE *fp;
+ int pid;
+} *pidlist;
+
+OsSigHandlerPtr old_alarm = NULL; /* XXX horrible awful hack */
+
+pointer
+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 = malloc(sizeof(struct pid))) == NULL)
+ return NULL;
+
+ if (pipe(pdes) < 0) {
+ free(cur);
+ return NULL;
+ }
+
+ /* Ignore the smart scheduler while this is going on */
+ old_alarm = OsSignal(SIGALRM, SIG_IGN);
+ if (old_alarm == SIG_ERR) {
+ close(pdes[0]);
+ close(pdes[1]);
+ free(cur);
+ perror("signal");
+ return NULL;
+ }
+
+ switch (pid = fork()) {
+ case -1: /* error */
+ close(pdes[0]);
+ close(pdes[1]);
+ free(cur);
+ if (OsSignal(SIGALRM, old_alarm) == SIG_ERR)
+ perror("signal");
+ 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/sh", "sh", "-c", command, (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;
+
+ DebugF("Popen: `%s', fp = %p\n", command, iop);
+
+ return iop;
+}
+
+/* fopen that drops privileges */
+pointer
+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 = 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;
+
+ DebugF("Fopen(%s), fp = %p\n", file, iop);
+
+ 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(pointer iop)
+{
+ struct pid *cur, *last;
+ int pstat;
+ int pid;
+
+ DebugF("Pclose: fp = %p\n", iop);
+ 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 ();
+
+ if (old_alarm && OsSignal(SIGALRM, old_alarm) == SIG_ERR) {
+ perror("signal");
+ return -1;
+ }
+
+ return pid == -1 ? -1 : pstat;
+}
+
+int
+Fclose(pointer 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
+
+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)) {
+ 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
+ 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);
+ break;
+ case ArgTooLong:
+ ErrorF("Command line argument number %d is too long\n", i);
+ break;
+ case UnprintableArg:
+ ErrorF("Command line argument number %d contains unprintable"
+ " characters\n", i);
+ break;
+ case EnvTooLong:
+ ErrorF("Environment variable `%s' is too long\n", e);
+ 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");
+ 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
+}
+
+/*
+ * Tokenize a string into a NULL terminated array of strings. Always returns
+ * an allocated array unless an error occurs.
+ */
+char**
+xstrtokenize(const char *str, const char *separators)
+{
+ char **list, **nlist;
+ char *tok, *tmp;
+ unsigned num = 0, n;
+
+ if (!str)
+ return NULL;
+ list = calloc(1, sizeof(*list));
+ if (!list)
+ return NULL;
+ tmp = strdup(str);
+ if (!tmp)
+ goto error;
+ for (tok = strtok(tmp, separators); tok; tok = strtok(NULL, separators)) {
+ nlist = realloc(list, (num + 2) * sizeof(*list));
+ if (!nlist)
+ goto error;
+ list = nlist;
+ list[num] = strdup(tok);
+ if (!list[num])
+ goto error;
+ list[++num] = NULL;
+ }
+ free(tmp);
+ return list;
+
+error:
+ free(tmp);
+ for (n = 0; n < num; n++)
+ free(list[n]);
+ free(list);
+ return NULL;
+}
diff --git a/os/xdmauth.c b/os/xdmauth.c
new file mode 100644
index 0000000..b8cbada
--- /dev/null
+++ b/os/xdmauth.c
@@ -0,0 +1,499 @@
+/*
+
+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 <X11/X.h>
+#define XSERV_t
+#define TRANS_SERVER
+#define TRANS_REOPEN
+#include <X11/Xtrans/Xtrans.h>
+#include "os.h"
+#include "osdep.h"
+#include "dixstruct.h"
+
+#ifdef HASXDMAUTH
+
+static Bool authFromXDMCP;
+
+#ifdef XDMCP
+#include <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, const 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 (const 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 (const char *cookie, int cookie_len)
+{
+ memset(privateKey.data, 0, 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 (const XdmClientAuthPtr a, const 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 (const 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 = 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) || defined(STREAMSCONN)
+ 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, const 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 = 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, const 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 = 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 = 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);
+ free(plain);
+ return auth->id;
+ }
+ }
+ free(cookie);
+ free(plain);
+ 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, const char *data)
+{
+ XdmAuthorizationPtr auth;
+ XdmAuthKeyPtr key_bits, rho_bits;
+
+ 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))
+ {
+ xdmAuth = auth->next;
+ free(auth);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+#endif
diff --git a/os/xdmcp.c b/os/xdmcp.c
new file mode 100644
index 0000000..877b11c
--- /dev/null
+++ b/os/xdmcp.c
@@ -0,0 +1,1661 @@
+/*
+ * 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 <X11/Xwinsock.h>
+#endif
+
+#include <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 <X11/X.h>
+#include <X11/Xmd.h>
+#include "misc.h"
+#include <X11/Xpoll.h>
+#include "osdep.h"
+#include "input.h"
+#include "dixstruct.h"
+#include "opaque.h"
+#include "site.h"
+
+#ifdef STREAMSCONN
+#include <tiuser.h>
+#include <netconfig.h>
+#include <netdir.h>
+#endif
+
+#ifdef XDMCP
+#undef REQUEST
+
+#ifdef XDMCP_NO_IPV6
+#undef IPv6
+#endif
+
+#include <X11/Xdmcp.h>
+
+#define X_INCLUDE_NETDB_H
+#include <X11/Xos_r.h>
+
+static char *defaultDisplayClass = COMPILEDDISPLAYCLASS;
+
+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 CARD32 defaultKeepaliveDormancy = XDM_DEF_DORMANCY;
+static CARD32 keepaliveDormancy = XDM_DEF_DORMANCY;
+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(
+ const struct sockaddr *from,
+ int fromlen,
+ ARRAY8Ptr AuthenticationName,
+ ARRAY8Ptr hostname,
+ ARRAY8Ptr status);
+
+static void XdmcpSelectHost(
+ const 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(
+ const char * /*type*/,
+ ARRAY8Ptr /*status*/);
+
+static void XdmcpWarning(const 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);
+
+static void timeout(void);
+
+static void restart(void);
+
+static void XdmcpBlockHandler(
+ pointer /*data*/,
+ struct timeval ** /*wt*/,
+ pointer /*LastSelectMask*/);
+
+static void XdmcpWakeupHandler(
+ pointer /*data*/,
+ int /*i*/,
+ pointer /*LastSelectMask*/);
+
+/*
+ * Register the Manufacturer display ID
+ */
+
+static ARRAY8 ManufacturerDisplayID;
+
+static void
+XdmcpRegisterManufacturerDisplayID (const 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];
+}
+
+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 (const struct sockaddr_in *addr)
+{
+ struct sockaddr_in *bcast;
+ if (NumBroadcastAddresses >= MAX_BROADCAST)
+ return;
+ bcast = &BroadcastAddresses[NumBroadcastAddresses++];
+ memset(bcast, 0, 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 (
+ const char *name,
+ int namelen,
+ const 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 = 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.
+ */
+
+static ARRAY8 noAuthenticationName = {(CARD16) 0, (CARD8Ptr) 0};
+static ARRAY8 noAuthenticationData = {(CARD16) 0, (CARD8Ptr) 0};
+static ARRAY8Ptr AuthenticationName = &noAuthenticationName;
+static ARRAY8Ptr AuthenticationData = &noAuthenticationData;
+static AuthenticationFuncsPtr AuthenticationFuncs;
+
+static void
+XdmcpSetAuthentication (const 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,
+ const 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;
+ }
+ }
+ if (ConnectionAddresses.length + 1 == 256)
+ return;
+ newAddress = 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 (const char *name, int namelen)
+{
+ ARRAY8 authName;
+ int i;
+
+ authName.data = 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
+ */
+
+static ARRAY8 DisplayClass;
+
+static void
+XdmcpRegisterDisplayClass (const 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];
+}
+
+/*
+ * initialize XDMCP; create the socket, compute the display
+ * number, set up the state machine
+ */
+
+void
+XdmcpInit(void)
+{
+ 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,
+ (pointer) 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,
+ (pointer) 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;
+ 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(
+ pointer data, /* unused */
+ struct timeval **wt,
+ pointer 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(
+ pointer data, /* unused */
+ int i,
+ pointer pReadmask)
+{
+ fd_set* LastSelectMask = (fd_set*)pReadmask;
+ fd_set devicesReadable;
+
+ 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
+ XFD_ANDSET(&devicesReadable, LastSelectMask, &EnabledDevices);
+ if (XFD_ANYSET(&devicesReadable))
+ {
+ if (state == XDM_AWAIT_USER_INPUT)
+ restart();
+ else if (state == XDM_RUN_SESSION)
+ keepaliveDormancy = defaultKeepaliveDormancy;
+ }
+ if (XFD_ANYSET(&AllClients) && state == XDM_RUN_SESSION)
+ timeOutTime = GetTimeInMillis() + keepaliveDormancy * 1000;
+ }
+ 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(
+ const 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(
+ const 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
+ */
+
+static 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.
+ */
+
+static void
+XdmcpDeadSession (const 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();
+}
+
+static void
+restart(void)
+{
+ state = XDM_INIT_STATE;
+ timeOutRtx = 0;
+ send_packet();
+}
+
+static int
+XdmcpCheckAuthentication (ARRAY8Ptr Name, ARRAY8Ptr Data, int packet_type)
+{
+ return (XdmcpARRAY8Equal (Name, AuthenticationName) &&
+ (AuthenticationName->length == 0 ||
+ (*AuthenticationFuncs->Validator) (AuthenticationData, Data, packet_type)));
+}
+
+static 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)
+{
+#ifdef STREAMSCONN
+ struct netconfig *nconf;
+
+ if ((xdmcpSocket = t_open("/dev/udp", O_RDWR, 0)) < 0) {
+ XdmcpWarning("t_open() of /dev/udp failed");
+ return;
+ }
+
+ if( t_bind(xdmcpSocket,NULL,NULL) < 0 ) {
+ XdmcpWarning("UDP socket creation failed");
+ t_error("t_bind(xdmcpSocket) failed" );
+ t_close(xdmcpSocket);
+ return;
+ }
+
+ /*
+ * This part of the code looks contrived. It will actually fit in nicely
+ * when the CLTS part of Xtrans is implemented.
+ */
+
+ if( (nconf=getnetconfigent("udp")) == NULL ) {
+ XdmcpWarning("UDP socket creation failed: getnetconfigent()");
+ t_unbind(xdmcpSocket);
+ t_close(xdmcpSocket);
+ return;
+ }
+
+ if( netdir_options(nconf, ND_SET_BROADCAST, xdmcpSocket, NULL) ) {
+ XdmcpWarning("UDP set broadcast option failed: netdir_options()");
+ freenetconfigent(nconf);
+ t_unbind(xdmcpSocket);
+ t_close(xdmcpSocket);
+ return;
+ }
+
+ freenetconfigent(nconf);
+#else
+ 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);
+ }
+ }
+#endif /* STREAMSCONN */
+}
+
+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)
+ {
+ /* backoff dormancy period */
+ state = XDM_RUN_SESSION;
+ if ((GetTimeInMillis() - lastDeviceEventTime.milliseconds) >
+ keepaliveDormancy * 1000)
+ {
+ keepaliveDormancy <<= 1;
+ if (keepaliveDormancy > XDM_MAX_DORMANCY)
+ keepaliveDormancy = XDM_MAX_DORMANCY;
+ }
+ timeOutTime = GetTimeInMillis() + keepaliveDormancy * 1000;
+ }
+ else
+ {
+ XdmcpDeadSession ("Alive response indicates session dead");
+ }
+ }
+}
+
+static void
+XdmcpFatal (
+ const char *type,
+ ARRAY8Ptr status)
+{
+ FatalError ("XDMCP fatal error: %s %*.*s\n", type,
+ status->length, status->length, status->data);
+}
+
+static void
+XdmcpWarning(const char *str)
+{
+ ErrorF("XDMCP warning: %s\n", str);
+}
+
+static void
+get_addr_by_name(
+ const char *argtype,
+ const 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;
+
+ memset(&hints, 0, 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
+ );
+#if defined(IPv6) && defined(AF_INET6)
+ if (aifirst != NULL)
+ freeaddrinfo(aifirst);
+#endif
+ xdm_from = argv[i];
+}
+
+
+#if defined(IPv6) && defined(AF_INET6)
+static int
+get_mcast_options(int argc, char **argv, int i)
+{
+ 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);
+ }
+ memset(&hints, 0, 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/os/xprintf.c b/os/xprintf.c
new file mode 100644
index 0000000..254b737
--- /dev/null
+++ b/os/xprintf.c
@@ -0,0 +1,226 @@
+/**
+ * @file
+ *
+ * @section DESCRIPTION
+ *
+ * These functions provide a portable implementation of the common (but not
+ * yet universal) asprintf & vasprintf routines to allocate a buffer big
+ * enough to sprintf the arguments to. The XNF variants terminate the server
+ * if the allocation fails.
+ */
+/*
+ * 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.
+ */
+/*
+ * Copyright (c) 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 (including the next
+ * paragraph) 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.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/Xos.h>
+#include "os.h"
+#include <stdarg.h>
+#include <stdio.h>
+
+#ifdef asprintf
+# undef asprintf
+#endif
+#ifdef vasprintf
+# undef vasprintf
+#endif
+
+#ifndef va_copy
+# ifdef __va_copy
+# define va_copy __va_copy
+# else
+# error "no working va_copy was found"
+# endif
+#endif
+
+/**
+ * Varargs sprintf that allocates a string buffer the right size for
+ * the pattern & data provided and prints the requested data to it.
+ *
+ * @param ret Pointer to which the newly allocated buffer is written
+ * (contents undefined on error)
+ * @param format printf style format string
+ * @param va variable argument list
+ * @return size of allocated buffer, or -1 on error.
+ */
+int
+Xvasprintf(char **ret, const char * _X_RESTRICT_KYWD format, va_list va)
+{
+#ifdef HAVE_VASPRINTF
+ return vasprintf(ret, format, va);
+#else
+ int size;
+ va_list va2;
+
+ va_copy(va2, va);
+ size = vsnprintf(NULL, 0, format, va2);
+ va_end(va2);
+
+ *ret = malloc(size + 1);
+ if (*ret == NULL)
+ return -1;
+
+ vsnprintf(*ret, size + 1, format, va);
+ (*ret)[size] = 0;
+ return size;
+#endif
+}
+
+#ifndef HAVE_VASPRINTF
+# define vasprintf Xvasprintf
+#endif
+
+/**
+ * sprintf that allocates a string buffer the right size for
+ * the pattern & data provided and prints the requested data to it.
+ *
+ * @param ret Pointer to which the newly allocated buffer is written
+ * (contents undefined on error)
+ * @param format printf style format string
+ * @param ... arguments for specified format
+ * @return size of allocated buffer, or -1 on error.
+ */
+int
+Xasprintf(char ** ret, const char * _X_RESTRICT_KYWD format, ...)
+{
+ int size;
+ va_list va;
+ va_start(va, format);
+ size = vasprintf(ret, format, va);
+ va_end(va);
+ return size;
+}
+
+/**
+ * Varargs sprintf that allocates a string buffer the right size for
+ * the pattern & data provided and prints the requested data to it.
+ * On failure, issues a FatalError message and aborts the server.
+ *
+ * @param ret Pointer to which the newly allocated buffer is written
+ * (contents undefined on error)
+ * @param format printf style format string
+ * @param va variable argument list
+ * @return size of allocated buffer
+ */
+int
+XNFvasprintf(char **ret, const char * _X_RESTRICT_KYWD format, va_list va)
+{
+ int size = vasprintf(ret, format, va);
+ if ((size == -1) || (*ret == NULL)) {
+ Error("XNFvasprintf");
+ FatalError("XNFvasprintf failed");
+ }
+ return size;
+}
+
+/**
+ * sprintf that allocates a string buffer the right size for
+ * the pattern & data provided and prints the requested data to it.
+ * On failure, issues a FatalError message and aborts the server.
+ *
+ * @param ret Pointer to which the newly allocated buffer is written
+ * (contents undefined on error)
+ * @param format printf style format string
+ * @param ... arguments for specified format
+ * @return size of allocated buffer
+ */
+int
+XNFasprintf(char ** ret, const char * _X_RESTRICT_KYWD format, ...)
+{
+ int size;
+ va_list va;
+ va_start(va, format);
+ size = XNFvasprintf(ret, format, va);
+ va_end(va);
+ return size;
+}
+
+/* Old api, now deprecated, may be removed in the future */
+char *
+Xvprintf(const char *format, va_list va)
+{
+ char *ret;
+
+ if (vasprintf(&ret, format, va) == -1)
+ ret = NULL;
+
+ return ret;
+}
+
+char *Xprintf(const char *format, ...)
+{
+ char *ret;
+ va_list va;
+ va_start(va, format);
+ if (vasprintf(&ret, format, va) == -1)
+ ret = NULL;
+ va_end(va);
+ return ret;
+}
+
+char *
+XNFvprintf(const char *format, va_list va)
+{
+ char *ret;
+
+ XNFvasprintf(&ret, format, va);
+
+ return ret;
+}
+
+char *XNFprintf(const char *format, ...)
+{
+ char *ret;
+ va_list va;
+ va_start(va, format);
+ XNFvasprintf(&ret, format, va);
+ va_end(va);
+ return ret;
+}
diff --git a/os/xsha1.c b/os/xsha1.c
new file mode 100644
index 0000000..5ea71da
--- /dev/null
+++ b/os/xsha1.c
@@ -0,0 +1,168 @@
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "os.h"
+#include "xsha1.h"
+
+#if defined(HAVE_SHA1_IN_LIBMD) /* Use libmd for SHA1 */ \
+ || defined(HAVE_SHA1_IN_LIBC) /* Use libc for SHA1 */
+
+# include <sha1.h>
+
+void *x_sha1_init(void)
+{
+ SHA1_CTX *ctx = malloc(sizeof(*ctx));
+ if (!ctx)
+ return NULL;
+ SHA1Init(ctx);
+ return ctx;
+}
+
+int x_sha1_update(void *ctx, void *data, int size)
+{
+ SHA1_CTX *sha1_ctx = ctx;
+ SHA1Update(sha1_ctx, data, size);
+ return 1;
+}
+
+int x_sha1_final(void *ctx, unsigned char result[20])
+{
+ SHA1_CTX *sha1_ctx = ctx;
+ SHA1Final(result, sha1_ctx);
+ free(sha1_ctx);
+ return 1;
+}
+
+#elif defined(HAVE_SHA1_IN_COMMONCRYPTO) /* Use CommonCrypto for SHA1 */
+
+#include <CommonCrypto/CommonDigest.h>
+
+void *x_sha1_init(void)
+{
+ CC_SHA1_CTX *ctx = malloc(sizeof(*ctx));
+ if (!ctx)
+ return NULL;
+ CC_SHA1_Init(ctx);
+ return ctx;
+}
+
+int x_sha1_update(void *ctx, void *data, int size)
+{
+ CC_SHA1_CTX *sha1_ctx = ctx;
+ CC_SHA1_Update(sha1_ctx, data, size);
+ return 1;
+}
+
+int x_sha1_final(void *ctx, unsigned char result[20])
+{
+ CC_SHA1_CTX *sha1_ctx = ctx;
+ CC_SHA1_Final(result, sha1_ctx);
+ free(sha1_ctx);
+ return 1;
+}
+
+#elif defined(HAVE_SHA1_IN_LIBGCRYPT) /* Use libgcrypt for SHA1 */
+
+# include <gcrypt.h>
+
+void *x_sha1_init(void)
+{
+ static int init;
+ gcry_md_hd_t h;
+ gcry_error_t err;
+
+ if (!init) {
+ if (!gcry_check_version(NULL))
+ return NULL;
+ gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
+ gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
+ init = 1;
+ }
+
+ err = gcry_md_open(&h, GCRY_MD_SHA1, 0);
+ if (err)
+ return NULL;
+ return h;
+}
+
+int x_sha1_update(void *ctx, void *data, int size)
+{
+ gcry_md_hd_t h = ctx;
+ gcry_md_write(h, data, size);
+ return 1;
+}
+
+int x_sha1_final(void *ctx, unsigned char result[20])
+{
+ gcry_md_hd_t h = ctx;
+ memcpy(result, gcry_md_read(h, GCRY_MD_SHA1), 20);
+ gcry_md_close(h);
+ return 1;
+}
+
+#elif defined(HAVE_SHA1_IN_LIBSHA1) /* Use libsha1 */
+
+# include <libsha1.h>
+
+void *x_sha1_init(void)
+{
+ sha1_ctx *ctx = malloc(sizeof(*ctx));
+ if(!ctx)
+ return NULL;
+ sha1_begin(ctx);
+ return ctx;
+}
+
+int x_sha1_update(void *ctx, void *data, int size)
+{
+ sha1_hash(data, size, ctx);
+ return 1;
+}
+
+int x_sha1_final(void *ctx, unsigned char result[20])
+{
+ sha1_end(result, ctx);
+ free(ctx);
+ return 1;
+}
+
+#else /* Use OpenSSL's libcrypto */
+
+# include <stddef.h> /* buggy openssl/sha.h wants size_t */
+# include <openssl/sha.h>
+
+void *x_sha1_init(void)
+{
+ int ret;
+ SHA_CTX *ctx = malloc(sizeof(*ctx));
+ if (!ctx)
+ return NULL;
+ ret = SHA1_Init(ctx);
+ if (!ret) {
+ free(ctx);
+ return NULL;
+ }
+ return ctx;
+}
+
+int x_sha1_update(void *ctx, void *data, int size)
+{
+ int ret;
+ SHA_CTX *sha_ctx = ctx;
+ ret = SHA1_Update(sha_ctx, data, size);
+ if (!ret)
+ free(sha_ctx);
+ return ret;
+}
+
+int x_sha1_final(void *ctx, unsigned char result[20])
+{
+ int ret;
+ SHA_CTX *sha_ctx = ctx;
+ ret = SHA1_Final(result, sha_ctx);
+ free(sha_ctx);
+ return ret;
+}
+
+#endif
diff --git a/os/xstrans.c b/os/xstrans.c
new file mode 100644
index 0000000..44ff976
--- /dev/null
+++ b/os/xstrans.c
@@ -0,0 +1,13 @@
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/Xfuncproto.h>
+
+/* ErrorF is used by xtrans */
+extern _X_EXPORT void ErrorF(const char *f, ...) _X_ATTRIBUTE_PRINTF(1,2);
+
+#define TRANS_REOPEN
+#define TRANS_SERVER
+#define XSERV_t
+#include <X11/Xtrans/transport.c>
contact: Jan Huwald // Impressum