From 3562e78743202e43aec8727005182a2558117eca Mon Sep 17 00:00:00 2001 From: marha Date: Sun, 28 Jun 2009 22:07:26 +0000 Subject: Checked in the following released items: xkeyboard-config-1.4.tar.gz ttf-bitstream-vera-1.10.tar.gz font-alias-1.0.1.tar.gz font-sun-misc-1.0.0.tar.gz font-sun-misc-1.0.0.tar.gz font-sony-misc-1.0.0.tar.gz font-schumacher-misc-1.0.0.tar.gz font-mutt-misc-1.0.0.tar.gz font-misc-misc-1.0.0.tar.gz font-misc-meltho-1.0.0.tar.gz font-micro-misc-1.0.0.tar.gz font-jis-misc-1.0.0.tar.gz font-isas-misc-1.0.0.tar.gz font-dec-misc-1.0.0.tar.gz font-daewoo-misc-1.0.0.tar.gz font-cursor-misc-1.0.0.tar.gz font-arabic-misc-1.0.0.tar.gz font-winitzki-cyrillic-1.0.0.tar.gz font-misc-cyrillic-1.0.0.tar.gz font-cronyx-cyrillic-1.0.0.tar.gz font-screen-cyrillic-1.0.1.tar.gz font-xfree86-type1-1.0.1.tar.gz font-adobe-utopia-type1-1.0.1.tar.gz font-ibm-type1-1.0.0.tar.gz font-bitstream-type1-1.0.0.tar.gz font-bitstream-speedo-1.0.0.tar.gz font-bh-ttf-1.0.0.tar.gz font-bh-type1-1.0.0.tar.gz font-bitstream-100dpi-1.0.0.tar.gz font-bh-lucidatypewriter-100dpi-1.0.0.tar.gz font-bh-100dpi-1.0.0.tar.gz font-adobe-utopia-100dpi-1.0.1.tar.gz font-adobe-100dpi-1.0.0.tar.gz font-util-1.0.1.tar.gz font-bitstream-75dpi-1.0.0.tar.gz font-bh-lucidatypewriter-75dpi-1.0.0.tar.gz font-adobe-utopia-75dpi-1.0.1.tar.gz font-bh-75dpi-1.0.0.tar.gz bdftopcf-1.0.1.tar.gz font-adobe-75dpi-1.0.0.tar.gz mkfontscale-1.0.6.tar.gz openssl-0.9.8k.tar.gz bigreqsproto-1.0.2.tar.gz xtrans-1.2.2.tar.gz resourceproto-1.0.2.tar.gz inputproto-1.4.4.tar.gz compositeproto-0.4.tar.gz damageproto-1.1.0.tar.gz zlib-1.2.3.tar.gz xkbcomp-1.0.5.tar.gz freetype-2.3.9.tar.gz pthreads-w32-2-8-0-release.tar.gz pixman-0.12.0.tar.gz kbproto-1.0.3.tar.gz evieext-1.0.2.tar.gz fixesproto-4.0.tar.gz recordproto-1.13.2.tar.gz randrproto-1.2.2.tar.gz scrnsaverproto-1.1.0.tar.gz renderproto-0.9.3.tar.gz xcmiscproto-1.1.2.tar.gz fontsproto-2.0.2.tar.gz xextproto-7.0.3.tar.gz xproto-7.0.14.tar.gz libXdmcp-1.0.2.tar.gz libxkbfile-1.0.5.tar.gz libfontenc-1.0.4.tar.gz libXfont-1.3.4.tar.gz libX11-1.1.5.tar.gz libXau-1.0.4.tar.gz libxcb-1.1.tar.gz xorg-server-1.5.3.tar.gz --- xorg-server/os/Makefile.am | 57 + xorg-server/os/Makefile.in | 716 +++++++++++++ xorg-server/os/WaitFor.c | 696 +++++++++++++ xorg-server/os/access.c | 2430 +++++++++++++++++++++++++++++++++++++++++++ xorg-server/os/auth.c | 370 +++++++ xorg-server/os/backtrace.c | 201 ++++ xorg-server/os/connection.c | 1302 +++++++++++++++++++++++ xorg-server/os/io.c | 1139 ++++++++++++++++++++ xorg-server/os/log.c | 632 +++++++++++ xorg-server/os/mitauth.c | 197 ++++ xorg-server/os/os.c | 0 xorg-server/os/oscolor.c | 139 +++ xorg-server/os/oscolor.h | 1508 +++++++++++++++++++++++++++ xorg-server/os/osdep.h | 289 +++++ xorg-server/os/osinit.c | 233 +++++ xorg-server/os/rpcauth.c | 202 ++++ xorg-server/os/strlcat.c | 58 ++ xorg-server/os/strlcpy.c | 53 + xorg-server/os/utils.c | 2244 +++++++++++++++++++++++++++++++++++++++ xorg-server/os/xdmauth.c | 497 +++++++++ xorg-server/os/xdmcp.c | 1670 +++++++++++++++++++++++++++++ xorg-server/os/xprintf.c | 104 ++ xorg-server/os/xstrans.c | 8 + 23 files changed, 14745 insertions(+) create mode 100644 xorg-server/os/Makefile.am create mode 100644 xorg-server/os/Makefile.in create mode 100644 xorg-server/os/WaitFor.c create mode 100644 xorg-server/os/access.c create mode 100644 xorg-server/os/auth.c create mode 100644 xorg-server/os/backtrace.c create mode 100644 xorg-server/os/connection.c create mode 100644 xorg-server/os/io.c create mode 100644 xorg-server/os/log.c create mode 100644 xorg-server/os/mitauth.c create mode 100644 xorg-server/os/os.c create mode 100644 xorg-server/os/oscolor.c create mode 100644 xorg-server/os/oscolor.h create mode 100644 xorg-server/os/osdep.h create mode 100644 xorg-server/os/osinit.c create mode 100644 xorg-server/os/rpcauth.c create mode 100644 xorg-server/os/strlcat.c create mode 100644 xorg-server/os/strlcpy.c create mode 100644 xorg-server/os/utils.c create mode 100644 xorg-server/os/xdmauth.c create mode 100644 xorg-server/os/xdmcp.c create mode 100644 xorg-server/os/xprintf.c create mode 100644 xorg-server/os/xstrans.c (limited to 'xorg-server/os') diff --git a/xorg-server/os/Makefile.am b/xorg-server/os/Makefile.am new file mode 100644 index 000000000..d6d748577 --- /dev/null +++ b/xorg-server/os/Makefile.am @@ -0,0 +1,57 @@ +noinst_LTLIBRARIES = libos.la + +AM_CFLAGS = $(DIX_CFLAGS) + +SECURERPC_SRCS = rpcauth.c +XDMCP_SRCS = xdmcp.c +STRLCAT_SRCS = strlcat.c strlcpy.c +XORG_SRCS = log.c + +libos_la_SOURCES = \ + WaitFor.c \ + access.c \ + auth.c \ + backtrace.c \ + connection.c \ + io.c \ + mitauth.c \ + oscolor.c \ + oscolor.h \ + osdep.h \ + osinit.c \ + utils.c \ + xdmauth.c \ + xstrans.c \ + xprintf.c \ + $(XORG_SRCS) + +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 XSERVER_DTRACE +# Generate dtrace object code for probes in libos & libdix +dtrace.o: $(top_srcdir)/dix/Xserver.d $(am_libos_la_OBJECTS) + $(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) + ld -r -o $@ dtrace.o .libs/*.o +endif + +os.c: + touch $@ + +CLEANFILES = os.c diff --git a/xorg-server/os/Makefile.in b/xorg-server/os/Makefile.in new file mode 100644 index 000000000..bc2eefdc7 --- /dev/null +++ b/xorg-server/os/Makefile.in @@ -0,0 +1,716 @@ +# Makefile.in generated by automake 1.10.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 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@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@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) +@XSERVER_DTRACE_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)/acinclude.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/xgl-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 +CONFIG_CLEAN_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libos_la_LIBADD = +am__libos_la_SOURCES_DIST = WaitFor.c access.c auth.c backtrace.c \ + connection.c io.c mitauth.c oscolor.c oscolor.h osdep.h \ + osinit.c utils.c xdmauth.c xstrans.c xprintf.c log.c rpcauth.c \ + xdmcp.c strlcat.c strlcpy.c +am__objects_1 = log.lo +am__objects_2 = rpcauth.lo +@SECURE_RPC_TRUE@am__objects_3 = $(am__objects_2) +am__objects_4 = xdmcp.lo +@XDMCP_TRUE@am__objects_5 = $(am__objects_4) +am__objects_6 = strlcat.lo strlcpy.lo +@NEED_STRLCAT_TRUE@am__objects_7 = $(am__objects_6) +am_libos_la_OBJECTS = WaitFor.lo access.lo auth.lo backtrace.lo \ + connection.lo io.lo mitauth.lo oscolor.lo osinit.lo utils.lo \ + xdmauth.lo xstrans.lo xprintf.lo $(am__objects_1) \ + $(am__objects_3) $(am__objects_5) $(am__objects_7) +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 +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libos_la_SOURCES) os.c +DIST_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@ +APPDEFAULTDIR = @APPDEFAULTDIR@ +APPLE_APPLICATIONS_DIR = @APPLE_APPLICATIONS_DIR@ +APP_MAN_DIR = @APP_MAN_DIR@ +APP_MAN_SUFFIX = @APP_MAN_SUFFIX@ +AR = @AR@ +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@ +COMPILEDDEFAULTFONTPATH = @COMPILEDDEFAULTFONTPATH@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DARWIN_LIBS = @DARWIN_LIBS@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_LIBS = @DBUS_LIBS@ +DEFAULT_LIBRARY_PATH = @DEFAULT_LIBRARY_PATH@ +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@ +DLLTOOL = @DLLTOOL@ +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@ +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_DRIVER_PATH = @DRI_DRIVER_PATH@ +DSYMUTIL = @DSYMUTIL@ +DTRACE = @DTRACE@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +FILE_MAN_DIR = @FILE_MAN_DIR@ +FILE_MAN_SUFFIX = @FILE_MAN_SUFFIX@ +FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ +FREETYPE_LIBS = @FREETYPE_LIBS@ +GLX_ARCH_DEFINES = @GLX_ARCH_DEFINES@ +GLX_DEFINES = @GLX_DEFINES@ +GL_CFLAGS = @GL_CFLAGS@ +GL_LIBS = @GL_LIBS@ +GREP = @GREP@ +HAL_CFLAGS = @HAL_CFLAGS@ +HAL_LIBS = @HAL_LIBS@ +INSTALL = @INSTALL@ +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 = @LAUNCHD@ +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@ +LIBTOOL = @LIBTOOL@ +LIB_MAN_DIR = @LIB_MAN_DIR@ +LIB_MAN_SUFFIX = @LIB_MAN_SUFFIX@ +LINUXDOC = @LINUXDOC@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MAKE_HTML = @MAKE_HTML@ +MAKE_PDF = @MAKE_PDF@ +MAKE_PS = @MAKE_PS@ +MAKE_TEXT = @MAKE_TEXT@ +MESA_SOURCE = @MESA_SOURCE@ +MISC_MAN_DIR = @MISC_MAN_DIR@ +MISC_MAN_SUFFIX = @MISC_MAN_SUFFIX@ +MKDIR_P = @MKDIR_P@ +MKFONTDIR = @MKFONTDIR@ +MKFONTSCALE = @MKFONTSCALE@ +NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCCLD = @OBJCCLD@ +OBJCDEPMODE = @OBJCDEPMODE@ +OBJCFLAGS = @OBJCFLAGS@ +OBJCLINK = @OBJCLINK@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +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@ +PKG_CONFIG = @PKG_CONFIG@ +PROJECTROOT = @PROJECTROOT@ +PS2PDF = @PS2PDF@ +RANLIB = @RANLIB@ +RAWCPP = @RAWCPP@ +RAWCPPFLAGS = @RAWCPPFLAGS@ +SED = @SED@ +SERVER_MISC_CONFIG_PATH = @SERVER_MISC_CONFIG_PATH@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOLARIS_ASM_CFLAGS = @SOLARIS_ASM_CFLAGS@ +SOLARIS_INOUT_ARCH = @SOLARIS_INOUT_ARCH@ +STRIP = @STRIP@ +TSLIB_CFLAGS = @TSLIB_CFLAGS@ +TSLIB_LIBS = @TSLIB_LIBS@ +UTILS_SYS_LIBS = @UTILS_SYS_LIBS@ +VENDOR_MAN_VERSION = @VENDOR_MAN_VERSION@ +VENDOR_NAME = @VENDOR_NAME@ +VENDOR_NAME_SHORT = @VENDOR_NAME_SHORT@ +VENDOR_RELEASE = @VENDOR_RELEASE@ +VERSION = @VERSION@ +X11APP_ARCHS = @X11APP_ARCHS@ +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@ +XEGLMODULES_CFLAGS = @XEGLMODULES_CFLAGS@ +XEGL_LIBS = @XEGL_LIBS@ +XEGL_SYS_LIBS = @XEGL_SYS_LIBS@ +XEPHYR_CFLAGS = @XEPHYR_CFLAGS@ +XEPHYR_DRI_LIBS = @XEPHYR_DRI_LIBS@ +XEPHYR_INCS = @XEPHYR_INCS@ +XEPHYR_LIBS = @XEPHYR_LIBS@ +XF86CONFIGFILE = @XF86CONFIGFILE@ +XF86MISC_CFLAGS = @XF86MISC_CFLAGS@ +XF86MISC_LIBS = @XF86MISC_LIBS@ +XF86VIDMODE_CFLAGS = @XF86VIDMODE_CFLAGS@ +XF86VIDMODE_LIBS = @XF86VIDMODE_LIBS@ +XGLMODULES_CFLAGS = @XGLMODULES_CFLAGS@ +XGLMODULES_LIBS = @XGLMODULES_LIBS@ +XGLXMODULES_CFLAGS = @XGLXMODULES_CFLAGS@ +XGLXMODULES_LIBS = @XGLXMODULES_LIBS@ +XGLX_LIBS = @XGLX_LIBS@ +XGLX_SYS_LIBS = @XGLX_SYS_LIBS@ +XGL_LIBS = @XGL_LIBS@ +XGL_MODULE_PATH = @XGL_MODULE_PATH@ +XGL_SYS_LIBS = @XGL_SYS_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@ +XNESTMODULES_CFLAGS = @XNESTMODULES_CFLAGS@ +XNESTMODULES_LIBS = @XNESTMODULES_LIBS@ +XNEST_LIBS = @XNEST_LIBS@ +XNEST_SYS_LIBS = @XNEST_SYS_LIBS@ +XORGCFG_DEP_CFLAGS = @XORGCFG_DEP_CFLAGS@ +XORGCFG_DEP_LIBS = @XORGCFG_DEP_LIBS@ +XORGCONFIG_DEP_CFLAGS = @XORGCONFIG_DEP_CFLAGS@ +XORGCONFIG_DEP_LIBS = @XORGCONFIG_DEP_LIBS@ +XORG_CFLAGS = @XORG_CFLAGS@ +XORG_INCS = @XORG_INCS@ +XORG_LIBS = @XORG_LIBS@ +XORG_MODULES_CFLAGS = @XORG_MODULES_CFLAGS@ +XORG_MODULES_LIBS = @XORG_MODULES_LIBS@ +XORG_OS = @XORG_OS@ +XORG_OS_SUBDIR = @XORG_OS_SUBDIR@ +XORG_SYS_LIBS = @XORG_SYS_LIBS@ +XPRINTMODULES_CFLAGS = @XPRINTMODULES_CFLAGS@ +XPRINTMODULES_LIBS = @XPRINTMODULES_LIBS@ +XPRINTPROTO_CFLAGS = @XPRINTPROTO_CFLAGS@ +XPRINTPROTO_LIBS = @XPRINTPROTO_LIBS@ +XPRINT_CFLAGS = @XPRINT_CFLAGS@ +XPRINT_LIBS = @XPRINT_LIBS@ +XPRINT_SYS_LIBS = @XPRINT_SYS_LIBS@ +XRESEXAMPLES_DEP_CFLAGS = @XRESEXAMPLES_DEP_CFLAGS@ +XRESEXAMPLES_DEP_LIBS = @XRESEXAMPLES_DEP_LIBS@ +XSDL_INCS = @XSDL_INCS@ +XSDL_LIBS = @XSDL_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@ +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@ +__XCONFIGFILE__ = @__XCONFIGFILE__@ +abi_ansic = @abi_ansic@ +abi_extension = @abi_extension@ +abi_font = @abi_font@ +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_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +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@ +ft_config = @ft_config@ +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@ +launchagentsdir = @launchagentsdir@ +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@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +xglmoduledir = @xglmoduledir@ +xpconfigdir = @xpconfigdir@ +noinst_LTLIBRARIES = libos.la +AM_CFLAGS = $(DIX_CFLAGS) +SECURERPC_SRCS = rpcauth.c +XDMCP_SRCS = xdmcp.c +STRLCAT_SRCS = strlcat.c strlcpy.c +XORG_SRCS = log.c +libos_la_SOURCES = WaitFor.c access.c auth.c backtrace.c connection.c \ + io.c mitauth.c oscolor.c oscolor.h osdep.h osinit.c utils.c \ + xdmauth.c xstrans.c xprintf.c $(XORG_SRCS) $(am__append_1) \ + $(am__append_2) $(am__append_3) +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 \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign os/Makefile'; \ + 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 + +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 +libos.la: $(libos_la_OBJECTS) $(libos_la_DEPENDENCIES) + $(LINK) $(libos_la_OBJECTS) $(libos_la_LIBADD) $(LIBS) + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; for p in $$list; do \ + f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f $$p $$f"; \ + rm -f $$p $$f ; \ + done +@XSERVER_DTRACE_FALSE@os.O$(EXEEXT): $(os_O_OBJECTS) $(os_O_DEPENDENCIES) +@XSERVER_DTRACE_FALSE@ @rm -f os.O$(EXEEXT) +@XSERVER_DTRACE_FALSE@ $(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)/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)/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)/xstrans.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@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@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@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@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@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 $@ $< + +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; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + 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; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + 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)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && 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 $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$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) + +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 + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +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 + +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 +@XSERVER_DTRACE_TRUE@dtrace.o: $(top_srcdir)/dix/Xserver.d $(am_libos_la_OBJECTS) +@XSERVER_DTRACE_TRUE@ $(DTRACE) -G -C -o $@ -s $(top_srcdir)/dix/Xserver.d .libs/*.o ../dix/.libs/*.o + +@XSERVER_DTRACE_TRUE@os.O: dtrace.o $(am_libos_la_OBJECTS) +@XSERVER_DTRACE_TRUE@ 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/xorg-server/os/WaitFor.c b/xorg-server/os/WaitFor.c new file mode 100644 index 000000000..da12976ca --- /dev/null +++ b/xorg-server/os/WaitFor.c @@ -0,0 +1,696 @@ +/*********************************************************** + +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 +#endif + +#ifdef WIN32 +#include +#endif +#include /* for strings, fcntl, time */ +#include +#include +#include +#include "misc.h" + +#include "osdep.h" +#include +#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 + +/* modifications by raphael */ +int +mffs(fd_mask mask) +{ + int i; + + if (!mask) return 0; + i = 1; + while (!(mask & 1)) + { + i++; + mask >>= 1; + } + return i; +} + +#ifdef DPMSExtension +#define DPMS_SERVER +#include +#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; + int nready; + fd_set devicesReadable; + CARD32 now = 0; +#ifdef SMART_SCHEDULE + Bool someReady = FALSE; +#endif + + FD_ZERO(&clientsReadable); + + /* 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)) + { +#ifdef SMART_SCHEDULE + if (!SmartScheduleDisable) + { + someReady = TRUE; + waittime.tv_sec = 0; + waittime.tv_usec = 0; + wt = &waittime; + } + else +#endif + { + XFD_COPYSET (&ClientsWithInput, &clientsReadable); + break; + } + } +#ifdef SMART_SCHEDULE + if (someReady) + { + XFD_COPYSET(&AllSockets, &LastSelectMask); + XFD_UNSET(&LastSelectMask, &ClientsWithInput); + } + else + { +#endif + 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); +#ifdef SMART_SCHEDULE + } + SmartScheduleStopTimer (); + +#endif + 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); +#ifdef SMART_SCHEDULE + SmartScheduleStartTimer (); +#endif + 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)); + } + } +#ifdef SMART_SCHEDULE + else if (someReady) + { + /* + * If no-one else is home, bail quickly + */ + XFD_COPYSET(&ClientsWithInput, &LastSelectMask); + XFD_COPYSET(&ClientsWithInput, &clientsReadable); + break; + } +#endif + 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; + } + } +#ifdef SMART_SCHEDULE + if (someReady) + XFD_ORSET(&LastSelectMask, &ClientsWithInput, &LastSelectMask); +#endif + 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; ipriority; + 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) +#endif + { + pClientsReady[nready++] = client_index; + } +#ifndef WIN32 + clientsReadable.fds_bits[i] &= ~(((fd_mask)1L) << curclient); + } +#else + FD_CLR(curclient, &clientsReadable); +#endif + } + } + 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); +} + +_X_EXPORT OsTimerPtr +TimerSet(OsTimerPtr timer, int flags, CARD32 millis, + OsTimerCallback func, pointer arg) +{ + register OsTimerPtr *prev; + CARD32 now = GetTimeInMillis(); + + if (!timer) + { + timer = (OsTimerPtr)xalloc(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; +} + + +_X_EXPORT void +TimerCancel(OsTimerPtr timer) +{ + OsTimerPtr *prev; + + if (!timer) + return; + for (prev = &timers; *prev; prev = &(*prev)->next) + { + if (*prev == timer) + { + *prev = timer->next; + break; + } + } +} + +_X_EXPORT void +TimerFree(OsTimerPtr timer) +{ + if (!timer) + return; + TimerCancel(timer); + xfree(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; + xfree(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/xorg-server/os/access.c b/xorg-server/os/access.c new file mode 100644 index 000000000..e91dd37e4 --- /dev/null +++ b/xorg-server/os/access.c @@ -0,0 +1,2430 @@ +/*********************************************************** + +Copyright 1987, 1998 The Open Group +Copyright 2004 Sun Microsystems, Inc. + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, and/or sell copies of the Software, and to permit persons +to whom the Software is furnished to do so, provided that the above +copyright notice(s) and this permission notice appear in all copies of +the Software and that both the above copyright notice(s) and this +permission notice appear in supporting documentation. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL +INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING +FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION +WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +Except as contained in this notice, the name of a copyright holder +shall not be used in advertising or otherwise to promote the sale, use +or other dealings in this Software without prior written authorization +of the copyright holder. + +X Window System is a trademark of The Open Group. + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#ifdef WIN32 +#include +#endif + +#include +#include +#define XSERV_t +#define TRANS_SERVER +#define TRANS_REOPEN +#include +#include +#include +#include +#include "misc.h" +#include "site.h" +#include +#include +#ifndef WIN32 +#ifndef Lynx +#include +#else +#include +#endif +#include +#include + +#if defined(TCPCONN) || defined(STREAMSCONN) || defined(ISC) || defined(__SCO__) +#include +#endif /* TCPCONN || STREAMSCONN || ISC || __SCO__ */ +#ifdef DNETCONN +#include +#include +#endif + +#ifdef HAS_GETPEERUCRED +# include +# ifdef sun +# include +# endif +#endif + +#if defined(DGUX) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + + +#if defined(hpux) || defined(QNX4) +# include +# ifdef HAS_IFREQ +# include +# endif +#else +#if defined(SVR4) || (defined(SYSV) && defined(__i386__)) || defined(__GNU__) +# include +#endif +#if defined(SYSV) && defined(__i386__) +# include +# ifdef ISC +# include +# include +# endif /* ISC */ +#endif +#ifdef __GNU__ +#undef SIOCGIFCONF +#include +#else /*!__GNU__*/ +# include +#endif /*__GNU__ */ +#endif /* hpux */ + +#ifdef SVR4 +#include +#include +#endif + +#include + +#ifdef CSRG_BASED +#include +#if (BSD >= 199103) +#define VARIABLE_IFREQ +#endif +#endif + +#ifdef BSD44SOCKETS +#ifndef VARIABLE_IFREQ +#define VARIABLE_IFREQ +#endif +#endif + +#ifdef HAS_GETIFADDRS +#include +#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 +#ifndef Lynx +#include +#else +#include +#endif +#ifndef PATH_MAX +#ifdef MAXPATHLEN +#define PATH_MAX MAXPATHLEN +#else +#define PATH_MAX 1024 +#endif +#endif +#endif + +#ifdef __SCO__ +/* The system defined value is wrong. MAXPATHLEN is set in sco5.cf. */ +#undef PATH_MAX +#endif + +#define X_INCLUDE_NETDB_H +#include + +#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*/, + pointer /*pAddr*/, + unsigned /*length*/); + +static Bool NewHost(int /*family*/, + pointer /*addr*/, + int /*len*/, + int /* addingLocalHosts */); + +/* XFree86 bug #156: To keep track of which hosts were explicitly requested in + /etc/X.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.hosts. They are + checked in DisableLocalHost(), which is called to disable the default + local host entries when stronger authentication is turned on. */ + +typedef struct _host { + short family; + short len; + unsigned char *addr; + struct _host *next; + int requested; +} HOST; + +#define MakeHost(h,l) (h)=(HOST *) xalloc(sizeof *(h)+(l));\ + if (h) { \ + (h)->addr=(unsigned char *) ((h) + 1);\ + (h)->requested = FALSE; \ + } +#define FreeHost(h) xfree(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(DGUX) && !defined(SCO325) && !defined(sun) && !defined(NCR)) || defined(ISC)) && !defined(__sgi) && defined(SIOCGIFCONF) && !defined(USE_SIOCGLIFCONF) + +/* Deal with different SIOCGIFCONF ioctl semantics on these OSs */ + +static int +ifioctl (int fd, int cmd, char *arg) +{ + struct strioctl ioc; + int ret; + + bzero((char *) &ioc, sizeof(ioc)); + ioc.ic_cmd = cmd; + ioc.ic_timout = 0; + if (cmd == SIOCGIFCONF) + { + ioc.ic_len = ((struct ifconf *) arg)->ifc_len; + ioc.ic_dp = ((struct ifconf *) arg)->ifc_buf; +#ifdef ISC + /* SIOCGIFCONF is somewhat brain damaged on ISC. The argument + * buffer must contain the ifconf structure as header. Ifc_req + * is also not a pointer but a one element array of ifreq + * structures. On return this array is extended by enough + * ifreq fields to hold all interfaces. The return buffer length + * is placed in the buffer header. + */ + ((struct ifconf *) ioc.ic_dp)->ifc_len = + ioc.ic_len - sizeof(struct ifconf); +#endif + } + else + { + ioc.ic_len = sizeof(struct ifreq); + ioc.ic_dp = arg; + } + ret = ioctl(fd, I_STR, (char *) &ioc); + if (ret >= 0 && cmd == SIOCGIFCONF) +#ifdef SVR4 + ((struct ifconf *) arg)->ifc_len = ioc.ic_len; +#endif +#ifdef ISC + { + ((struct ifconf *) arg)->ifc_len = + ((struct ifconf *)ioc.ic_dp)->ifc_len; + ((struct ifconf *) arg)->ifc_buf = + (caddr_t)((struct ifconf *)ioc.ic_dp)->ifc_req; + } +#endif + return(ret); +} +#else /* Case DGUX, sun, SCO325 NCR and others */ +#define ifioctl ioctl +#endif /* ((SVR4 && !DGUX !sun !SCO325 !NCR) || ISC) && SIOCGIFCONF */ + +/* + * DefineSelf (fd): + * + * Define this host for access control. Find all the hosts the OS knows about + * for this fd and add them to the selfhosts list. + */ + +#ifdef WINTCP /* NCR Wollongong based TCP */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +void +DefineSelf (int fd) +{ + /* + * The Wolongong drivers used by NCR SVR4/MP-RAS don't understand the + * socket IO calls that most other drivers seem to like. Because of + * this, this routine must be special cased for NCR. Eventually, + * this will be cleared up. + */ + + struct ipb ifnet; + struct in_ifaddr ifaddr; + struct strioctl str; + unsigned char *addr; + register HOST *host; + int family, len; + + if ((fd = open ("/dev/ip", O_RDWR, 0 )) < 0) + Error ("Getting interface configuration (1)"); + + /* Indicate that we want to start at the begining */ + ifnet.ib_next = (struct ipb *) 1; + + while (ifnet.ib_next) + { + str.ic_cmd = IPIOC_GETIPB; + str.ic_timout = 0; + str.ic_len = sizeof (struct ipb); + str.ic_dp = (char *) &ifnet; + + if (ioctl (fd, (int) I_STR, (char *) &str) < 0) + { + close (fd); + Error ("Getting interface configuration (2)"); + } + + ifaddr.ia_next = (struct in_ifaddr *) ifnet.if_addrlist; + str.ic_cmd = IPIOC_GETINADDR; + str.ic_timout = 0; + str.ic_len = sizeof (struct in_ifaddr); + str.ic_dp = (char *) &ifaddr; + + if (ioctl (fd, (int) I_STR, (char *) &str) < 0) + { + close (fd); + Error ("Getting interface configuration (3)"); + } + + len = sizeof(struct sockaddr_in); + family = ConvertAddr (IA_SIN(&ifaddr), &len, (pointer *)&addr); + if (family == -1 || family == FamilyLocal) + continue; + for (host = selfhosts; + host && !addrEqual (family, addr, len, host); + host = host->next) + ; + if (host) + continue; + MakeHost(host,len) + if (host) + { + host->family = family; + host->len = len; + acopy(addr, host->addr, len); + host->next = selfhosts; + selfhosts = host; + } +#ifdef XDMCP + { + struct sockaddr broad_addr; + + /* + * If this isn't an Internet Address, don't register it. + */ + if (family != FamilyInternet) + continue; + + /* + * Ignore 'localhost' entries as they're not useful + * on the other end of the wire. + */ + if (len == 4 && + addr[0] == 127 && addr[1] == 0 && + addr[2] == 0 && addr[3] == 1) + continue; + + /* + * Ignore '0.0.0.0' entries as they are + * returned by some OSes for unconfigured NICs but they are + * not useful on the other end of the wire. + */ + if (len == 4 && + addr[0] == 0 && addr[1] == 0 && + addr[2] == 0 && addr[3] == 0) + continue; + + XdmcpRegisterConnection (family, (char *)addr, len); + + +#define IA_BROADADDR(ia) ((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_broadaddr)) + + XdmcpRegisterBroadcastAddress ( + (struct sockaddr_in *) IA_BROADADDR(&ifaddr)); + +#undef IA_BROADADDR + } +#endif /* XDMCP */ + } + + close(fd); + + /* + * add something of FamilyLocalHost + */ + for (host = selfhosts; + host && !addrEqual(FamilyLocalHost, "", 0, host); + host = host->next); + if (!host) + { + MakeHost(host, 0); + if (host) + { + host->family = FamilyLocalHost; + host->len = 0; + acopy("", host->addr, 0); + host->next = selfhosts; + selfhosts = host; + } + } +} + +#else /* WINTCP */ + +#if !defined(SIOCGIFCONF) || (defined (hpux) && ! defined (HAS_IFREQ)) || defined(QNX4) +void +DefineSelf (int fd) +{ +#if !defined(TCPCONN) && !defined(STREAMSCONN) && !defined(UNIXCONN) && !defined(MNX_TCPCONN) + 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 QNX4 +#ifndef WIN32 + uname(&name); +#else + gethostname(name.nodename, sizeof(name.nodename)); +#endif +#else + /* QNX4's uname returns node number in name.nodename, not the hostname + have to overwrite it */ + char hname[1024]; + gethostname(hname, 1024); + name.nodename = hname; +#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[1] == 0 && + addr[2] == 0 && addr[3] == 1) || + (addr[0] == 0 && addr[1] == 0 && + addr[2] == 0 && addr[3] == 0))) + ) + { + XdmcpRegisterConnection (family, (char *)addr, len); + broad_addr = *inetaddr; + ((struct sockaddr_in *) &broad_addr)->sin_addr.s_addr = + htonl (INADDR_BROADCAST); + XdmcpRegisterBroadcastAddress ((struct sockaddr_in *) + &broad_addr); + } +#if defined(IPv6) && defined(AF_INET6) + else if (family == FamilyInternet6 && + !(IN6_IS_ADDR_LOOPBACK((struct in6_addr *)addr))) + { + XdmcpRegisterConnection (family, (char *)addr, len); + } +#endif + +#endif /* XDMCP */ + } + } + } + /* + * now add a host of family FamilyLocalHost... + */ +DefineLocalHost: + for (host = selfhosts; + host && !addrEqual(FamilyLocalHost, "", 0, host); + host = host->next); + if (!host) + { + MakeHost(host, 0); + if (host) + { + host->family = FamilyLocalHost; + host->len = 0; + acopy("", host->addr, 0); + host->next = selfhosts; + selfhosts = host; + } + } +#endif /* !TCPCONN && !STREAMSCONN && !UNIXCONN && !MNX_TCPCONN */ +} + +#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 +#ifdef QNX4 +#define ifr_size(p) (p->ifr_addr.sa_len + IFNAMSIZ) +#define ifraddr_size(a) (a.sa_len) +#else +#define ifr_size(p) (sizeof (ifr_type)) +#define ifraddr_size(a) (sizeof (a)) +#endif +#endif + +#if defined(DEF_SELF_DEBUG) || (defined(IPv6) && defined(AF_INET6)) +#include +#endif + +#if defined(IPv6) && defined(AF_INET6) +static void +in6_fillscopeid(struct sockaddr_in6 *sin6) +{ +#if defined(__KAME__) + if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { + sin6->sin6_scope_id = + ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]); + sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = 0; + } +#endif +} +#endif + +void +DefineSelf (int fd) +{ +#ifndef HAS_GETIFADDRS + char buf[2048], *cp, *cplim; + void * bufptr = buf; +#ifdef USE_SIOCGLIFCONF + struct lifconf ifc; + register struct lifreq *ifr; +#ifdef SIOCGLIFNUM + struct lifnum ifn; +#endif +#else + struct ifconf ifc; + register struct ifreq *ifr; +#endif +#else + struct ifaddrs * ifap, *ifr; +#endif + int len; + unsigned char * addr; + int family; + register HOST *host; + +#ifdef DNETCONN + struct dn_naddr *dnaddr = getnodeadd(); + /* + * AF_DECnet may not be listed in the interface list. Instead use + * the supported library call to find out the local address (if any). + */ + if (dnaddr) + { + addr = (unsigned char *) dnaddr; + len = dnaddr->a_len + sizeof(dnaddr->a_len); + family = FamilyDECnet; + for (host = selfhosts; + host && !addrEqual (family, addr, len, host); + host = host->next) + ; + if (!host) + { + MakeHost(host,len) + if (host) + { + host->family = family; + host->len = len; + acopy(addr, host->addr, len); + host->next = selfhosts; + selfhosts = host; + } + } + } +#endif /* DNETCONN */ +#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 = xalloc(len); + } +#endif + + ifc.lifc_family = AF_UNSPEC; + ifc.lifc_flags = 0; + ifc.lifc_len = len; + ifc.lifc_buf = bufptr; + +#define IFC_IOCTL_REQ SIOCGLIFCONF +#define IFC_IFC_REQ ifc.lifc_req +#define IFC_IFC_LEN ifc.lifc_len +#define IFR_IFR_ADDR ifr->lifr_addr +#define IFR_IFR_NAME ifr->lifr_name + +#else /* Use SIOCGIFCONF */ + ifc.ifc_len = len; + ifc.ifc_buf = bufptr; + +#define IFC_IOCTL_REQ SIOCGIFCONF +#ifdef ISC +#define IFC_IFC_REQ (struct ifreq *) ifc.ifc_buf +#else +#define IFC_IFC_REQ ifc.ifc_req +#endif /* ISC */ +#define IFC_IFC_LEN ifc.ifc_len +#define IFR_IFR_ADDR ifr->ifr_addr +#define IFR_IFR_NAME ifr->ifr_name +#endif + + if (ifioctl (fd, IFC_IOCTL_REQ, (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); +#ifdef DNETCONN + /* + * DECnet was handled up above. + */ + if (family == AF_DECnet) + continue; +#endif /* DNETCONN */ + if (family == -1 || family == FamilyLocal) + continue; +#if defined(IPv6) && defined(AF_INET6) + if (family == FamilyInternet6) + in6_fillscopeid((struct sockaddr_in6 *)&IFR_IFR_ADDR); +#endif +#ifdef DEF_SELF_DEBUG + if (family == FamilyInternet) + ErrorF("Xserver: DefineSelf(): ifname = %s, addr = %d.%d.%d.%d\n", + IFR_IFR_NAME, addr[0], addr[1], addr[2], addr[3]); +#if defined(IPv6) && defined(AF_INET6) + else if (family == FamilyInternet6) { + char cp[INET6_ADDRSTRLEN] = ""; + inet_ntop(AF_INET6, addr, cp, sizeof(cp)); + ErrorF("Xserver: DefineSelf(): ifname = %s, addr = %s\n", + IFR_IFR_NAME, cp); + } +#endif +#endif /* DEF_SELF_DEBUG */ + for (host = selfhosts; + host && !addrEqual (family, addr, len, host); + host = host->next) + ; + if (host) + continue; + MakeHost(host,len) + if (host) + { + host->family = family; + host->len = len; + acopy(addr, host->addr, len); + host->next = selfhosts; + selfhosts = host; + } +#ifdef XDMCP + { +#ifdef USE_SIOCGLIFCONF + struct sockaddr_storage broad_addr; +#else + struct sockaddr broad_addr; +#endif + + /* + * If this isn't an Internet Address, don't register it. + */ + if (family != FamilyInternet +#if defined(IPv6) && defined(AF_INET6) + && family != FamilyInternet6 +#endif + ) + continue; + + /* + * ignore 'localhost' entries as they're not useful + * on the other end of the wire + */ + if (family == FamilyInternet && + addr[0] == 127 && addr[1] == 0 && + addr[2] == 0 && addr[3] == 1) + continue; +#if defined(IPv6) && defined(AF_INET6) + else if (family == FamilyInternet6 && + IN6_IS_ADDR_LOOPBACK((struct in6_addr *)addr)) + continue; +#endif + + /* + * Ignore '0.0.0.0' entries as they are + * returned by some OSes for unconfigured NICs but they are + * not useful on the other end of the wire. + */ + if (len == 4 && + addr[0] == 0 && addr[1] == 0 && + addr[2] == 0 && addr[3] == 0) + continue; + + XdmcpRegisterConnection (family, (char *)addr, len); + +#if defined(IPv6) && defined(AF_INET6) + /* IPv6 doesn't support broadcasting, so we drop out here */ + if (family == FamilyInternet6) + continue; +#endif + + broad_addr = IFR_IFR_ADDR; + + ((struct sockaddr_in *) &broad_addr)->sin_addr.s_addr = + htonl (INADDR_BROADCAST); +#if defined(USE_SIOCGLIFCONF) && defined(SIOCGLIFBRDADDR) + { + struct lifreq broad_req; + + broad_req = *ifr; + if (ioctl (fd, SIOCGLIFFLAGS, (char *) &broad_req) != -1 && + (broad_req.lifr_flags & IFF_BROADCAST) && + (broad_req.lifr_flags & IFF_UP) + ) + { + broad_req = *ifr; + if (ioctl (fd, SIOCGLIFBRDADDR, &broad_req) != -1) + broad_addr = broad_req.lifr_broadaddr; + else + continue; + } + else + continue; + } + +#elif defined(SIOCGIFBRDADDR) + { + struct ifreq broad_req; + + broad_req = *ifr; + if (ifioctl (fd, SIOCGIFFLAGS, (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 */ +#ifdef DEF_SELF_DEBUG + ErrorF("Xserver: DefineSelf(): ifname = %s, baddr = %s\n", + IFR_IFR_NAME, + inet_ntoa(((struct sockaddr_in *) &broad_addr)->sin_addr)); +#endif /* DEF_SELF_DEBUG */ + XdmcpRegisterBroadcastAddress ((struct sockaddr_in *) &broad_addr); + } +#endif /* XDMCP */ + } + if (bufptr != buf) + free(bufptr); +#else /* HAS_GETIFADDRS */ + if (getifaddrs(&ifap) < 0) { + ErrorF("Warning: getifaddrs returns %s\n", strerror(errno)); + return; + } + for (ifr = ifap; ifr != NULL; ifr = ifr->ifa_next) { + if (!ifr->ifa_addr) + continue; +#ifdef DNETCONN + if (ifr->ifa_addr.sa_family == AF_DECnet) + continue; +#endif /* DNETCONN */ + len = sizeof(*(ifr->ifa_addr)); + family = ConvertAddr(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 + +#ifdef DEF_SELF_DEBUG + if (family == FamilyInternet) + ErrorF("Xserver: DefineSelf(): ifname = %s, addr = %d.%d.%d.%d\n", + ifr->ifa_name, addr[0], addr[1], addr[2], addr[3]); +#if defined(IPv6) && defined(AF_INET6) + else if (family == FamilyInternet6) { + char cp[INET6_ADDRSTRLEN]; + + inet_ntop(AF_INET6, addr, cp, sizeof(cp)); + ErrorF("Xserver: DefineSelf(): ifname = %s addr = %s\n", + ifr->ifa_name, cp); + } +#endif +#endif /* DEF_SELF_DEBUG */ + for (host = selfhosts; + host != NULL && !addrEqual(family, addr, len, host); + host = host->next) + ; + if (host != NULL) + continue; + MakeHost(host, len); + if (host != NULL) { + host->family = family; + host->len = len; + acopy(addr, host->addr, len); + host->next = selfhosts; + selfhosts = host; + } +#ifdef XDMCP + { + struct sockaddr broad_addr; + /* + * If this isn't an Internet Address, don't register it. + */ + if (family != FamilyInternet +#if defined(IPv6) && defined(AF_INET6) + && family != FamilyInternet6 +#endif + ) + continue; + + /* + * ignore 'localhost' entries as they're not useful + * on the other end of the wire + */ + if (ifr->ifa_flags & IFF_LOOPBACK) + continue; + + if (family == FamilyInternet && + addr[0] == 127 && addr[1] == 0 && + addr[2] == 0 && addr[3] == 1) + continue; + + /* + * Ignore '0.0.0.0' entries as they are + * returned by some OSes for unconfigured NICs but they are + * not useful on the other end of the wire. + */ + if (len == 4 && + addr[0] == 0 && addr[1] == 0 && + addr[2] == 0 && addr[3] == 0) + continue; +#if defined(IPv6) && defined(AF_INET6) + else if (family == FamilyInternet6 && + IN6_IS_ADDR_LOOPBACK((struct in6_addr *)addr)) + continue; +#endif + XdmcpRegisterConnection(family, (char *)addr, len); +#if defined(IPv6) && defined(AF_INET6) + if (family == FamilyInternet6) + /* IPv6 doesn't support broadcasting, so we drop out here */ + continue; +#endif + if ((ifr->ifa_flags & IFF_BROADCAST) && + (ifr->ifa_flags & IFF_UP)) + broad_addr = *ifr->ifa_broadaddr; + else + continue; +#ifdef DEF_SELF_DEBUG + ErrorF("Xserver: DefineSelf(): ifname = %s, baddr = %s\n", + ifr->ifa_name, + inet_ntoa(((struct sockaddr_in *) &broad_addr)->sin_addr)); +#endif /* DEF_SELF_DEBUG */ + XdmcpRegisterBroadcastAddress((struct sockaddr_in *) + &broad_addr); + } +#endif /* XDMCP */ + + } /* for */ + freeifaddrs(ifap); +#endif /* HAS_GETIFADDRS */ + + /* + * add something of FamilyLocalHost + */ + for (host = selfhosts; + host && !addrEqual(FamilyLocalHost, "", 0, host); + host = host->next); + if (!host) + { + MakeHost(host, 0); + if (host) + { + host->family = FamilyLocalHost; + host->len = 0; + acopy("", host->addr, 0); + host->next = selfhosts; + selfhosts = host; + } + } +} +#endif /* hpux && !HAS_IFREQ */ +#endif /* WINTCP */ + +#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(MNX_TCPCONN)) && \ + (!defined(IPv6) || !defined(AF_INET6))) || defined(DNETCONN) + union { + struct sockaddr sa; +#if defined(TCPCONN) || defined(STREAMSCONN) || defined(MNX_TCPCONN) + struct sockaddr_in in; +#endif /* TCPCONN || STREAMSCONN */ +#ifdef DNETCONN + struct sockaddr_dn dn; +#endif + } saddr; +#endif +#ifdef DNETCONN + struct nodeent *np; + struct dn_naddr dnaddr, *dnaddrp, *dnet_addr(); +#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); + sprintf(fname, ETC_HOST_PREFIX "%s" ETC_HOST_SUFFIX, display); + + if ((fd = fopen (fname, "r")) != 0) + { + while (fgets (ohostname, sizeof (ohostname), fd)) + { + family = FamilyWild; + if (*ohostname == '#') + continue; + if ((ptr = strchr(ohostname, '\n')) != 0) + *ptr = 0; + hostlen = strlen(ohostname) + 1; + for (i = 0; i < hostlen; i++) + lhostname[i] = tolower(ohostname[i]); + hostname = ohostname; + if (!strncmp("local:", lhostname, 6)) + { + family = FamilyLocalHost; + NewHost(family, "", 0, FALSE); + LocalHostRequested = TRUE; /* Fix for XFree86 bug #156 */ + } +#if defined(TCPCONN) || defined(STREAMSCONN) || defined(MNX_TCPCONN) + else if (!strncmp("inet:", lhostname, 5)) + { + family = FamilyInternet; + hostname = ohostname + 5; + } +#if defined(IPv6) && defined(AF_INET6) + else if (!strncmp("inet6:", lhostname, 6)) + { + family = FamilyInternet6; + hostname = ohostname + 6; + } +#endif +#endif +#ifdef DNETCONN + else if (!strncmp("dnet:", lhostname, 5)) + { + family = FamilyDECnet; + hostname = ohostname + 5; + } +#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 DNETCONN + if ((family == FamilyDECnet) || ((family == FamilyWild) && + (ptr = strchr(hostname, ':')) && (*(ptr + 1) == ':') && + !(*ptr = '\0'))) /* bash trailing colons if necessary */ + { + /* node name (DECnet names end in "::") */ + dnaddrp = dnet_addr(hostname); + if (!dnaddrp && (np = getnodebyname (hostname))) + { + /* node was specified by name */ + saddr.sa.sa_family = np->n_addrtype; + len = sizeof(saddr.sa); + if (ConvertAddr (&saddr.sa, &len, (pointer *)&addr) == FamilyDECnet) + { + bzero ((char *) &dnaddr, sizeof (dnaddr)); + dnaddr.a_len = np->n_length; + acopy (np->n_addr, dnaddr.a_addr, np->n_length); + dnaddrp = &dnaddr; + } + } + if (dnaddrp) + (void) NewHost(FamilyDECnet, (pointer)dnaddrp, + (int)(dnaddrp->a_len + sizeof(dnaddrp->a_len)), FALSE); + } + else +#endif /* DNETCONN */ +#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) || defined(MNX_TCPCONN) + { +#if defined(IPv6) && defined(AF_INET6) + if ( (family == FamilyInternet) || (family == FamilyInternet6) || + (family == FamilyWild) ) + { + struct addrinfo *addresses; + struct addrinfo *a; + int f; + + if (getaddrinfo(hostname, NULL, NULL, &addresses) == 0) { + for (a = addresses ; a != NULL ; a = a->ai_next) { + len = a->ai_addrlen; + f = ConvertAddr(a->ai_addr,&len,(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 */ +_X_EXPORT Bool LocalClient(ClientPtr client) +{ + int alen, family, notused; + Xtransaddr *from = NULL; + pointer addr; + register HOST *host; + + if (!_XSERVTransGetPeerAddr (((OsCommPtr)client->osPrivate)->trans_conn, + ¬used, &alen, &from)) + { + family = ConvertAddr ((struct sockaddr *) from, + &alen, (pointer *)&addr); + if (family == -1) + { + xfree ((char *) from); + return FALSE; + } + if (family == FamilyLocal) + { + xfree ((char *) from); + return TRUE; + } + for (host = selfhosts; host; host = host->next) + { + if (addrEqual (family, addr, alen, host)) + return TRUE; + } + xfree ((char *) from); + } + return FALSE; +} + +/* + * Return the uid and gid of a connected local client + * + * Used by XShm to test access rights to shared memory segments + */ +int +LocalClientCred(ClientPtr client, int *pUid, int *pGid) +{ + LocalClientCredRec *lcc; + int ret = GetLocalClientCreds(client, &lcc); + + if (ret == 0) { +#ifdef HAVE_GETZONEID /* only local if in the same zone */ + if ((lcc->fieldsSet & LCC_ZID_SET) && (lcc->zoneid != getzoneid())) { + FreeLocalClientCreds(lcc); + return -1; + } +#endif + if ((lcc->fieldsSet & LCC_UID_SET) && (pUid != NULL)) + *pUid = lcc->euid; + if ((lcc->fieldsSet & LCC_GID_SET) && (pGid != NULL)) + *pGid = lcc->egid; + FreeLocalClientCreds(lcc); + } + return ret; +} + +/* + * Return the uid and all gids of a connected local client + * Allocates a LocalClientCredRec - caller must call FreeLocalClientCreds + * + * Used by localuser & localgroup ServerInterpreted access control forms below + * Used by AuthAudit to log 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 = Xcalloc(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 = Xcalloc((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) { + Xfree(lcc->pSuppGids); + } + Xfree(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 */ + pointer 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, + pointer 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 += (((host->len + 3) >> 2) << 2) + sizeof(xHostEntry); + } + if (n) + { + *data = ptr = (pointer) xalloc (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 += ((len + 3) >> 2) << 2; + } + } else { + *data = NULL; + } + *pnHosts = nHosts; + *pLen = n; + return(Success); +} + +/* Check for valid address family and length, and return address length. */ + +/*ARGSUSED*/ +static int +CheckAddr ( + int family, + pointer pAddr, + unsigned length) +{ + int len; + + switch (family) + { +#if defined(TCPCONN) || defined(STREAMSCONN) || defined(MNX_TCPCONN) + case FamilyInternet: + if (length == sizeof (struct in_addr)) + len = length; + else + len = -1; + break; +#if defined(IPv6) && defined(AF_INET6) + case FamilyInternet6: + if (length == sizeof (struct in6_addr)) + len = length; + else + len = -1; + break; +#endif +#endif +#ifdef DNETCONN + case FamilyDECnet: + { + struct dn_naddr *dnaddr = (struct dn_naddr *) pAddr; + + if ((length < sizeof(dnaddr->a_len)) || + (length < dnaddr->a_len + sizeof(dnaddr->a_len))) + len = -1; + else + len = dnaddr->a_len + sizeof(dnaddr->a_len); + if (len > sizeof(struct dn_naddr)) + len = -1; + } + break; +#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) || defined(MNX_TCPCONN) + 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 +#ifdef DNETCONN + case AF_DECnet: + { + struct sockaddr_dn *sdn = (struct sockaddr_dn *) saddr; + *len = sdn->sdn_nodeaddrl + sizeof(sdn->sdn_nodeaddrl); + *addr = (pointer) &(sdn->sdn_add); + } + return FamilyDECnet; +#endif +#ifdef CHAOSCONN + case AF_CHAOS: + { + not implemented + } + return FamilyChaos; +#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 + * + * 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 = (struct siType *) xalloc(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 +#include + +#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 = xalloc(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; + } + } + } + + xfree(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/xorg-server/os/auth.c b/xorg-server/os/auth.c new file mode 100644 index 000000000..dab4f60bd --- /dev/null +++ b/xorg-server/os/auth.c @@ -0,0 +1,370 @@ +/* + +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 +#endif + +# include +# include +# include "misc.h" +# include "osdep.h" +# include "dixstruct.h" +# include +# include +#ifdef WIN32 +#include +#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, + char *name, + unsigned int data_length, + char *data, + ClientPtr client, + char **reason) /* failure message. NULL for default msg */ +{ + int i; + struct stat buf; + static time_t lastmod = 0; + 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, + char *name, + unsigned short data_length, + char *data) +{ + int i; + + for (i = 0; i < NUM_AUTHORIZATION; i++) { + if (protocols[i].name_length == name_length && + memcmp (protocols[i].name, name, (int) name_length) == 0 && + protocols[i].Remove) + { + return (*protocols[i].Remove) (data_length, data); + } + } + return 0; +} + +int +AddAuthorization (unsigned name_length, char *name, unsigned data_length, char *data) +{ + int i; + + for (i = 0; i < NUM_AUTHORIZATION; i++) { + if (protocols[i].name_length == name_length && + memcmp (protocols[i].name, name, (int) name_length) == 0 && + protocols[i].Add) + { + return (*protocols[i].Add) (data_length, data, FakeClientID(0)); + } + } + return 0; +} + +#ifdef XCSECURITY + +XID +GenerateAuthorization( + unsigned name_length, + char *name, + unsigned data_length, + char *data, + unsigned *data_length_return, + char **data_return) +{ + int i; + + for (i = 0; i < NUM_AUTHORIZATION; i++) { + if (protocols[i].name_length == name_length && + memcmp (protocols[i].name, name, (int) name_length) == 0 && + protocols[i].Generate) + { + return (*protocols[i].Generate) (data_length, data, + FakeClientID(0), data_length_return, data_return); + } + } + return -1; +} + +#ifdef HAVE_URANDOM + +void +GenerateRandomData (int len, char *buf) +{ + int fd; + + fd = open("/dev/urandom", O_RDONLY); + read(fd, buf, len); + close(fd); +} + +#else /* !HAVE_URANDOM */ + +/* A random number generator that is more unpredictable + than that shipped with some systems. + This code is taken from the C standard. */ + +static unsigned long int next = 1; + +static int +xdm_rand(void) +{ + next = next * 1103515245 + 12345; + return (unsigned int)(next/65536) % 32768; +} + +static void +xdm_srand(unsigned int seed) +{ + next = seed; +} + +void +GenerateRandomData (int len, char *buf) +{ + static int seed; + int value; + int i; + + seed += GetTimeInMillis(); + xdm_srand (seed); + for (i = 0; i < len; i++) + { + value = xdm_rand (); + buf[i] ^= (value & 0xff00) >> 8; + } + + /* XXX add getrusage, popen("ps -ale") */ +} + +#endif /* HAVE_URANDOM */ + +#endif /* XCSECURITY */ diff --git a/xorg-server/os/backtrace.c b/xorg-server/os/backtrace.c new file mode 100644 index 000000000..b52dcded8 --- /dev/null +++ b/xorg-server/os/backtrace.c @@ -0,0 +1,201 @@ +/* + * 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 + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * them 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 MERCHANTIBILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS 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 +#endif + +#include "os.h" +#include "misc.h" + +#ifdef HAVE_BACKTRACE +#include + +void xorg_backtrace(void) +{ + void *array[32]; /* deeper nesting than this means something's wrong */ + size_t size, i; + char **strings; + ErrorF("\nBacktrace:\n"); + size = backtrace(array, 32); + strings = backtrace_symbols(array, size); + for (i = 0; i < size; i++) + ErrorF("%d: %s\n", i, strings[i]); + free(strings); +} + +#else /* not glibc or glibc < 2.1 */ + +# if defined(sun) && defined(__SVR4) +# define HAVE_PSTACK +# endif + +# if defined(HAVE_WALKCONTEXT) /* Solaris 9 & later */ + +# include +# include +# include +# include + +#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 = "
"; + 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/xorg-server/os/connection.c b/xorg-server/os/connection.c new file mode 100644 index 000000000..1ae50fef0 --- /dev/null +++ b/xorg-server/os/connection.c @@ -0,0 +1,1302 @@ +/*********************************************************** + +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 +#endif + +#ifdef WIN32 +#include +#endif +#include +#include +#define XSERV_t +#define TRANS_SERVER +#define TRANS_REOPEN +#include +#ifdef HAVE_LAUNCHD +#include +#endif +#include +#include +#include +#include + +#ifndef WIN32 +#if defined(Lynx) +#include +#else +#include +#endif + +#ifdef hpux +#include +#include +#endif + +#if defined(DGUX) +#include +#include +#include +#include +#include +#include +#include +#include +#endif + + +#ifdef AIXV3 +#include +#endif + +#if defined(TCPCONN) || defined(STREAMSCONN) +# include +# include +# if !defined(hpux) +# ifdef apollo +# ifndef NO_TCP_H +# include +# endif +# else +# ifdef CSRG_BASED +# include +# endif +# include +# endif +# endif +# include +#endif + +#ifndef Lynx +#include +#else +#include +#endif +#endif /* WIN32 */ +#include "misc.h" /* for typedef of pointer */ +#include "osdep.h" +#include +#include "opaque.h" +#include "dixstruct.h" +#ifdef XAPPGROUP +#include "appgroup.h" +#endif +#include "xace.h" + +#ifdef X_NOT_POSIX +#define Pid_t int +#else +#define Pid_t pid_t +#endif + +#ifdef DNETCONN +#include +#endif /* DNETCONN */ + +#ifdef HAS_GETPEERUCRED +# include +# include +#endif + +#ifdef XSERVER_DTRACE +# include +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 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; +_X_EXPORT 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 +#define MAXFD 500 + +struct _ct_node { + struct _ct_node *next; + int key; + int value; +}; + +struct _ct_node *ct_head[256]; + +void InitConnectionTranslation(void) +{ + bzero(ct_head, sizeof(ct_head)); +} + +int GetConnectionTranslation(int conn) +{ + struct _ct_node *node = ct_head[conn & 0xff]; + while (node != NULL) + { + if (node->key == conn) + return node->value; + node = node->next; + } + return 0; +} + +void SetConnectionTranslation(int conn, int client) +{ + struct _ct_node **node = ct_head + (conn & 0xff); + if (client == 0) /* remove entry */ + { + while (*node != NULL) + { + if ((*node)->key == conn) + { + struct _ct_node *temp = *node; + *node = (*node)->next; + free(temp); + return; + } + node = &((*node)->next); + } + return; + } else + { + while (*node != NULL) + { + if ((*node)->key == conn) + { + (*node)->value = client; + return; + } + node = &((*node)->next); + } + *node = (struct _ct_node*)xalloc(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; + xfree(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 (); +#ifdef __UNIXOS2__ + /* + * fg030505: under OS/2, xinit is not the parent process but + * the "grant parent" process of the server because execvpe() + * presents us an additional process number; + * GetPPID(pid) is part of libemxfix + */ + ParentProcess = GetPPID (ParentProcess); +#endif /* __UNIXOS2__ */ +#endif +} + +void +NotifyParentProcess(void) +{ +#if !defined(WIN32) + if (RunFromSmartParent) { + if (ParentProcess > 1) { + kill (ParentProcess, SIGUSR1); + } + } +#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= 0) && + (ListenTransCount >= 1)) + { + if (!PartialNetwork && partial) + { + FatalError ("Failed to establish all listening sockets"); + } + else + { + ListenTransFds = (int *) xalloc (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) || defined(MNX_TCPCONN) + case AF_INET: + sprintf(out, "IP %s", + inet_ntoa(((struct sockaddr_in *) saddr)->sin_addr)); + break; +#if defined(IPv6) && defined(AF_INET6) + case AF_INET6: { + char ipaddr[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET6, &((struct sockaddr_in6 *) saddr)->sin6_addr, + ipaddr, sizeof(ipaddr)); + sprintf(out, "IP %s", ipaddr); + } + break; +#endif +#endif +#ifdef DNETCONN + case AF_DECnet: + sprintf(out, "DN %s", + dnet_ntoa(&((struct sockaddr_dn *) saddr)->sdn_add)); + break; +#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); + if (auditTrailLevel > 1) { +#endif + 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); + +#ifdef XSERVER_DTRACE + } +#endif +} + +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; +#ifdef HAVE_LAUNCHD + struct sockaddr *saddr; +#endif + + priv = (OsCommPtr)client->osPrivate; + trans_conn = priv->trans_conn; + +#ifdef HAVE_LAUNCHD + saddr = (struct sockaddr *) (trans_conn->addr); + /* Allow any client to connect without authorization on a launchd socket, + because it is securely created -- this prevents a race condition on launch */ + if (saddr->sa_len > 11 && saddr->sa_family == AF_UNIX && + !strncmp(saddr->sa_data, "/tmp/launch", 11)) goto done; +#endif + + 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); + } + + xfree ((char *) 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); + + xfree ((char *) from); + } + } + priv->auth_id = auth_id; + done: + 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 = (OsCommPtr)xalloc(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))) + { + xfree (oc); + return NullClient; + } +#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; iosPrivate); + 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 = ffs (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); + } + } +#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 0) + CloseDownClient(clients[ConnectionTranslation[curclient]]); + mask &= ~((fd_mask)1 << curoff); + } + } +#else + XFD_COPYSET(&AllClients, &savedAllClients); + for (i = 0; i < XFD_SETCOUNT(&savedAllClients); i++) + { + curclient = XFD_FD(&savedAllClients, i); + FD_ZERO(&tmask); + FD_SET(curclient, &tmask); + do { + r = Select (curclient + 1, &tmask, NULL, NULL, ¬ime); + } while (r < 0 && (errno == EINTR || errno == EAGAIN)); + if (r < 0) + if (GetConnectionTranslation(curclient) > 0) + CloseDownClient(clients[GetConnectionTranslation(curclient)]); + } +#endif +} + + +/***************** + * CloseDownConnection + * Delete client from AllClients and free resources + *****************/ + +void +CloseDownConnection(ClientPtr client) +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + + if (oc->output && oc->output->count) + FlushClient(client, oc, (char *)NULL, 0); +#ifdef XDMCP + XdmcpCloseDisplay(oc->fd); +#endif + CloseDownFileDescriptor(oc); + FreeOsBuffers(oc); + xfree(client->osPrivate); + client->osPrivate = (pointer)NULL; + if (auditTrailLevel > 1) + AuditF("client %d disconnected\n", client->index); +} + +_X_EXPORT void +AddGeneralSocket(int fd) +{ + FD_SET(fd, &AllSockets); + if (GrabInProgress) + FD_SET(fd, &SavedAllSockets); +} + +_X_EXPORT void +AddEnabledDevice(int fd) +{ + FD_SET(fd, &EnabledDevices); + AddGeneralSocket(fd); +} + +_X_EXPORT void +RemoveGeneralSocket(int fd) +{ + FD_CLR(fd, &AllSockets); + if (GrabInProgress) + FD_CLR(fd, &SavedAllSockets); +} + +_X_EXPORT 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. + ****************/ + +_X_EXPORT void +IgnoreClient (ClientPtr client) +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + int connection = oc->fd; + + isItTimeToYield = TRUE; + if (!GrabInProgress || FD_ISSET(connection, &AllClients)) + { + if (FD_ISSET (connection, &ClientsWithInput)) + FD_SET(connection, &IgnoredClientsWithInput); + else + FD_CLR(connection, &IgnoredClientsWithInput); + FD_CLR(connection, &ClientsWithInput); + FD_CLR(connection, &AllSockets); + FD_CLR(connection, &AllClients); + FD_CLR(connection, &LastSelectMask); + } + else + { + if (FD_ISSET (connection, &SavedClientsWithInput)) + FD_SET(connection, &IgnoredClientsWithInput); + else + FD_CLR(connection, &IgnoredClientsWithInput); + FD_CLR(connection, &SavedClientsWithInput); + FD_CLR(connection, &SavedAllSockets); + FD_CLR(connection, &SavedAllClients); + } +} + +/**************** + * AttendClient + * Adds one client back into the input masks. + ****************/ + +_X_EXPORT void +AttendClient (ClientPtr client) +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + int connection = oc->fd; + if (!GrabInProgress || GrabInProgress == client->index || + FD_ISSET(connection, &GrabImperviousClients)) + { + FD_SET(connection, &AllClients); + FD_SET(connection, &AllSockets); + FD_SET(connection, &LastSelectMask); + if (FD_ISSET (connection, &IgnoredClientsWithInput)) + FD_SET(connection, &ClientsWithInput); + } + else + { + FD_SET(connection, &SavedAllClients); + FD_SET(connection, &SavedAllSockets); + if (FD_ISSET(connection, &IgnoredClientsWithInput)) + FD_SET(connection, &SavedClientsWithInput); + } +} + +/* make client impervious to grabs; assume only executing client calls this */ + +_X_EXPORT 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 */ + +_X_EXPORT void +MakeClientGrabPervious(ClientPtr client) +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + int connection = oc->fd; + + FD_CLR(connection, &GrabImperviousClients); + if (GrabInProgress && (GrabInProgress != client->index)) + { + if (FD_ISSET(connection, &ClientsWithInput)) + { + FD_SET(connection, &SavedClientsWithInput); + FD_CLR(connection, &ClientsWithInput); + } + FD_CLR(connection, &AllSockets); + FD_CLR(connection, &AllClients); + isItTimeToYield = TRUE; + } + + if (ServerGrabCallback) + { + ServerGrabInfoRec grabinfo; + grabinfo.client = client; + grabinfo.grabstate = CLIENT_PERVIOUS; + CallCallbacks(&ServerGrabCallback, &grabinfo); + } +} + diff --git a/xorg-server/os/io.c b/xorg-server/os/io.c new file mode 100644 index 000000000..e7ec60952 --- /dev/null +++ b/xorg-server/os/io.c @@ -0,0 +1,1139 @@ +/*********************************************************** + +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 +#endif + +#undef DEBUG_COMMUNICATION + +#ifdef WIN32 +#include +#endif +#include +#define XSERV_t +#define TRANS_SERVER +#define TRANS_REOPEN +#include +#include +#include +#if !defined(WIN32) +#ifndef Lynx +#include +#else +#include +#endif +#endif +#include +#define NEED_REPLIES +#include +#include "os.h" +#include "osdep.h" +#include +#include "opaque.h" +#include "dixstruct.h" +#include "misc.h" + +_X_EXPORT CallbackListPtr ReplyCallback; +_X_EXPORT 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 +#if defined(EAGAIN) && defined(EWOULDBLOCK) +#define ETEST(err) (err == EAGAIN || err == EWOULDBLOCK) +#else +#ifdef EAGAIN +#define ETEST(err) (err == EAGAIN) +#else +#define ETEST(err) (err == EWOULDBLOCK) +#endif +#endif +#else /* WIN32 The socket errorcodes differ from the normal errors*/ +#define ETEST(err) (err == EAGAIN || err == WSAEWOULDBLOCK) +#endif + +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) + +#ifdef BIGREQS +#include + +#define get_big_req_len(req,cli) ((cli)->swapped ? \ + lswapl(((xBigReq *)(req))->length) : \ + ((xBigReq *)(req))->length) +#endif + +#define MAX_TIMES_PER 10 + +/* + * A lot of the code in this file manipulates a ConnectionInputPtr: + * + * ----------------------------------------------- + * |------- bufcnt ------->| | | + * | |- gotnow ->| | | + * | |-------- needed ------>| | + * |-----------+--------- size --------+---------->| + * ----------------------------------------------- + * ^ ^ + * | | + * buffer bufptr + * + * buffer is a pointer to the start of the buffer. + * bufptr points to the start of the current request. + * bufcnt counts how many bytes are in the buffer. + * size is the size of the buffer in bytes. + * + * In several of the functions, gotnow and needed are local variables + * that do the following: + * + * gotnow is the number of bytes of the request that we're + * trying to read that are currently in the buffer. + * Typically, gotnow = (buffer + bufcnt) - bufptr + * + * needed = the length of the request that we're trying to + * read. Watch out: needed sometimes counts bytes and sometimes + * counts CARD32's. + */ + + +/***************************************************************** + * ReadRequestFromClient + * Returns one request in client->requestBuffer. The request + * length will be in client->req_len. Return status is: + * + * > 0 if successful, specifies length in bytes of the request + * = 0 if entire request is not yet available + * < 0 if client should be terminated + * + * The request returned must be contiguous so that it can be + * cast in the dispatcher to the correct request type. Because requests + * are variable length, ReadRequestFromClient() must look at the first 4 + * or 8 bytes of a request to determine the length (the request length is + * in the 3rd and 4th bytes of the request unless it is a Big Request + * (see the Big Request Extension), in which case the 3rd and 4th bytes + * are zero and the following 4 bytes are the request length. + * + * Note: in order to make the server scheduler (WaitForSomething()) + * "fair", the ClientsWithInput mask is used. This mask tells which + * clients have FULL requests left in their buffers. Clients with + * partial requests require a read. Basically, client buffers + * are drained before select() is called again. But, we can't keep + * reading from a client that is sending buckets of data (or has + * a partial request) because others clients need to be scheduled. + *****************************************************************/ + +#define YieldControl() \ + { isItTimeToYield = TRUE; \ + timesThisConnection = 0; } +#define YieldControlNoInput() \ + { YieldControl(); \ + FD_CLR(fd, &ClientsWithInput); } +#define YieldControlDeath() \ + { timesThisConnection = 0; } + +int +ReadRequestFromClient(ClientPtr client) +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + ConnectionInputPtr oci = oc->input; + int fd = oc->fd; + unsigned int gotnow, needed; + int result; + register xReq *request; + Bool need_header; +#ifdef BIGREQS + Bool move_header; +#endif + + /* If an input buffer was empty, either free it if it is too big + * or link it into our list of free input buffers. This means that + * different clients can share the same input buffer (at different + * times). This was done to save memory. + */ + + if (AvailableInput) + { + if (AvailableInput != oc) + { + register ConnectionInputPtr aci = AvailableInput->input; + if (aci->size > BUFWATERMARK) + { + xfree(aci->buffer); + xfree(aci); + } + else + { + aci->next = FreeInputs; + FreeInputs = aci; + } + AvailableInput->input = (ConnectionInputPtr)NULL; + } + AvailableInput = (OsCommPtr)NULL; + } + + /* make sure we have an input buffer */ + + if (!oci) + { + if ((oci = FreeInputs)) + { + FreeInputs = oci->next; + } + else if (!(oci = AllocateInputBuffer())) + { + YieldControlDeath(); + return -1; + } + oc->input = oci; + } + + /* advance to start of next request */ + + oci->bufptr += oci->lenLastReq; + + need_header = FALSE; +#ifdef BIGREQS + move_header = FALSE; +#endif + gotnow = oci->bufcnt + oci->buffer - oci->bufptr; + if (gotnow < sizeof(xReq)) + { + /* We don't have an entire xReq yet. Can't tell how big + * the request will be until we get the whole xReq. + */ + needed = sizeof(xReq); + need_header = TRUE; + } + else + { + /* We have a whole xReq. We can tell how big the whole + * request will be unless it is a Big Request. + */ + request = (xReq *)oci->bufptr; + needed = get_req_len(request, client); +#ifdef BIGREQS + if (!needed && client->big_requests) + { + /* It's a Big Request. */ + move_header = TRUE; + if (gotnow < sizeof(xBigReq)) + { + /* Still need more data to tell just how big. */ + needed = sizeof(xBigReq) >> 2; /* needed is in CARD32s now */ + need_header = TRUE; + } + else + needed = get_big_req_len(request, client); + } +#endif + client->req_len = needed; + needed <<= 2; /* needed is in bytes now */ + } + if (gotnow < needed) + { + /* Need to read more data, either so that we can get a + * complete xReq (if need_header is TRUE), a complete + * xBigReq (if move_header is TRUE), or the rest of the + * request (if need_header and move_header are both FALSE). + */ + + oci->lenLastReq = 0; +#ifdef BIGREQS + if (needed > maxBigRequestSize << 2) + { + /* request is too big for us to handle */ + YieldControlDeath(); + return -1; + } +#endif + 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 *)xrealloc(oci->buffer, needed); + if (!ibuf) + { + YieldControlDeath(); + return -1; + } + oci->size = needed; + oci->buffer = ibuf; + } + oci->bufptr = oci->buffer; + oci->bufcnt = gotnow; + } + /* XXX this is a workaround. This function is sometimes called + * after the trans_conn has been freed. In this case trans_conn + * will be null. Really ought to restructure things so that we + * never get here in those circumstances. + */ + if (!oc->trans_conn) + { + /* treat as if an error occured on the read, which is what + * used to happen + */ + YieldControlDeath(); + return -1; + } + result = _XSERVTransRead(oc->trans_conn, oci->buffer + oci->bufcnt, + oci->size - oci->bufcnt); + if (result <= 0) + { + if ((result < 0) && ETEST(errno)) + { +#if defined(SVR4) && defined(__i386__) && !defined(sun) + if (0) +#endif + { + YieldControlNoInput(); + return 0; + } + } + YieldControlDeath(); + return -1; + } + oci->bufcnt += result; + gotnow += result; + /* free up some space after huge requests */ + if ((oci->size > BUFWATERMARK) && + (oci->bufcnt < BUFSIZE) && (needed < BUFSIZE)) + { + char *ibuf; + + ibuf = (char *)xrealloc(oci->buffer, BUFSIZE); + if (ibuf) + { + oci->size = BUFSIZE; + oci->buffer = ibuf; + oci->bufptr = ibuf + oci->bufcnt - gotnow; + } + } + if (need_header && gotnow >= needed) + { + /* We wanted an xReq, now we've gotten it. */ + request = (xReq *)oci->bufptr; + needed = get_req_len(request, client); +#ifdef BIGREQS + if (!needed && client->big_requests) + { + move_header = TRUE; + if (gotnow < sizeof(xBigReq)) + needed = sizeof(xBigReq) >> 2; + else + needed = get_big_req_len(request, client); + } +#endif + client->req_len = needed; + needed <<= 2; + } + if (gotnow < needed) + { + /* Still don't have enough; punt. */ + YieldControlNoInput(); + return 0; + } + } + if (needed == 0) + { +#ifdef BIGREQS + if (client->big_requests) + needed = sizeof(xBigReq); + else +#endif + needed = sizeof(xReq); + } + oci->lenLastReq = needed; + + /* + * Check to see if client has at least one whole request in the + * buffer beyond the request we're returning to the caller. + * If there is only a partial request, treat like buffer + * is empty so that select() will be called again and other clients + * can get into the queue. + */ + + gotnow -= needed; + if (gotnow >= sizeof(xReq)) + { + request = (xReq *)(oci->bufptr + needed); + if (gotnow >= (result = (get_req_len(request, client) << 2)) +#ifdef BIGREQS + && (result || + (client->big_requests && + (gotnow >= sizeof(xBigReq) && + gotnow >= (get_big_req_len(request, client) << 2)))) +#endif + ) + FD_SET(fd, &ClientsWithInput); + else + { +#ifdef SMART_SCHEDULE + if (!SmartScheduleDisable) + FD_CLR(fd, &ClientsWithInput); + else +#endif + YieldControlNoInput(); + } + } + else + { + if (!gotnow) + AvailableInput = oc; +#ifdef SMART_SCHEDULE + if (!SmartScheduleDisable) + FD_CLR(fd, &ClientsWithInput); + else +#endif + YieldControlNoInput(); + } +#ifdef SMART_SCHEDULE + if (SmartScheduleDisable) +#endif + if (++timesThisConnection >= MAX_TIMES_PER) + YieldControl(); +#ifdef BIGREQS + if (move_header) + { + request = (xReq *)oci->bufptr; + oci->bufptr += (sizeof(xBigReq) - sizeof(xReq)); + *(xReq *)oci->bufptr = *request; + oci->lenLastReq -= (sizeof(xBigReq) - sizeof(xReq)); + client->req_len -= (sizeof(xBigReq) - sizeof(xReq)) >> 2; + } +#endif + client->requestBuffer = (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) + { + xfree(aci->buffer); + xfree(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 *)xrealloc(oci->buffer, gotnow + count); + if (!ibuf) + return(FALSE); + oci->size = gotnow + count; + oci->buffer = ibuf; + oci->bufptr = ibuf + oci->bufcnt - gotnow; + } + moveup = count - (oci->bufptr - oci->buffer); + if (moveup > 0) + { + if (gotnow > 0) + memmove(oci->bufptr + moveup, oci->bufptr, gotnow); + oci->bufptr += moveup; + oci->bufcnt += moveup; + } + memmove(oci->bufptr - count, data, count); + oci->bufptr -= count; + gotnow += count; + if ((gotnow >= sizeof(xReq)) && + (gotnow >= (int)(get_req_len((xReq *)oci->bufptr, client) << 2))) + FD_SET(fd, &ClientsWithInput); + else + YieldControlNoInput(); + return(TRUE); +} + +/***************************************************************** + * ResetRequestFromClient + * Reset to reexecute the current request, and yield. + * + **********************/ + +_X_EXPORT void +ResetCurrentRequest(ClientPtr client) +{ + OsCommPtr oc = (OsCommPtr)client->osPrivate; + register ConnectionInputPtr oci = oc->input; + int fd = oc->fd; + register xReq *request; + int gotnow, needed; + if (AvailableInput == oc) + AvailableInput = (OsCommPtr)NULL; + oci->lenLastReq = 0; + gotnow = oci->bufcnt + oci->buffer - oci->bufptr; + if (gotnow < sizeof(xReq)) + { + YieldControlNoInput(); + } + else + { + request = (xReq *)oci->bufptr; + needed = get_req_len(request, client); +#ifdef BIGREQS + if (!needed && client->big_requests) + { + oci->bufptr -= sizeof(xBigReq) - sizeof(xReq); + *(xReq *)oci->bufptr = *request; + ((xBigReq *)oci->bufptr)->length = client->req_len; + if (client->swapped) + { + char n; + swapl(&((xBigReq *)oci->bufptr)->length, n); + } + } +#endif + if (gotnow >= (needed << 2)) + { + if (FD_ISSET(fd, &AllClients)) + { + FD_SET(fd, &ClientsWithInput); + } + else + { + FD_SET(fd, &IgnoredClientsWithInput); + } + YieldControl(); + } + else + YieldControlNoInput(); + } +} + + + +_X_EXPORT CallbackListPtr SkippedRequestsCallback = NULL; + + /* lookup table for adding padding bytes to data that is read from + or written to the X socket. */ +static int padlength[4] = {0, 3, 2, 1}; + + /******************** + * FlushAllOutput() + * Flush all clients with output. However, if some client still + * has input in the queue (more requests), then don't flush. This + * will prevent the output queue from being flushed every time around + * the round robin queue. Now, some say that it SHOULD be flushed + * every time around, but... + * + **********************/ + +void +FlushAllOutput(void) +{ + register int index, base; + register fd_mask mask; /* raphael */ + OsCommPtr oc; + register ClientPtr client; + Bool newoutput = NewOutputPending; +#if defined(WIN32) + fd_set newOutputPending; +#endif + + if (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(); +} + +_X_EXPORT 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. + *****************/ + +_X_EXPORT int +WriteToClient (ClientPtr who, int count, char *buf) +{ + OsCommPtr oc = (OsCommPtr)who->osPrivate; + ConnectionOutputPtr oco = oc->output; + int padBytes; +#ifdef DEBUG_COMMUNICATION + Bool multicount = FALSE; +#endif + if (!count) + return(0); +#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; + } + 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, char *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]; + 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 (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 *)xrealloc(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) + { + xfree(oco->buf); + xfree(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 = (ConnectionInputPtr)xalloc(sizeof(ConnectionInput)); + if (!oci) + return (ConnectionInputPtr)NULL; + oci->buffer = (char *)xalloc(BUFSIZE); + if (!oci->buffer) + { + xfree(oci); + return (ConnectionInputPtr)NULL; + } + oci->size = BUFSIZE; + oci->bufptr = oci->buffer; + oci->bufcnt = 0; + oci->lenLastReq = 0; + return oci; +} + +static ConnectionOutputPtr +AllocateOutputBuffer(void) +{ + ConnectionOutputPtr oco; + + oco = (ConnectionOutputPtr)xalloc(sizeof(ConnectionOutput)); + if (!oco) + return (ConnectionOutputPtr)NULL; + oco->buf = (unsigned char *) xcalloc(1, BUFSIZE); + if (!oco->buf) + { + xfree(oco); + return (ConnectionOutputPtr)NULL; + } + oco->size = BUFSIZE; + oco->count = 0; + return oco; +} + +void +FreeOsBuffers(OsCommPtr oc) +{ + ConnectionInputPtr oci; + ConnectionOutputPtr oco; + + if (AvailableInput == oc) + AvailableInput = (OsCommPtr)NULL; + if ((oci = oc->input)) + { + if (FreeInputs) + { + xfree(oci->buffer); + xfree(oci); + } + else + { + FreeInputs = oci; + oci->next = (ConnectionInputPtr)NULL; + oci->bufptr = oci->buffer; + oci->bufcnt = 0; + oci->lenLastReq = 0; + } + } + if ((oco = oc->output)) + { + if (FreeOutputs) + { + xfree(oco->buf); + xfree(oco); + } + else + { + FreeOutputs = oco; + oco->next = (ConnectionOutputPtr)NULL; + oco->count = 0; + } + } +} + +void +ResetOsBuffers(void) +{ + ConnectionInputPtr oci; + ConnectionOutputPtr oco; + + while ((oci = FreeInputs)) + { + FreeInputs = oci->next; + xfree(oci->buffer); + xfree(oci); + } + while ((oco = FreeOutputs)) + { + FreeOutputs = oco->next; + xfree(oco->buf); + xfree(oco); + } +} diff --git a/xorg-server/os/log.c b/xorg-server/os/log.c new file mode 100644 index 000000000..ee14624dc --- /dev/null +++ b/xorg-server/os/log.c @@ -0,0 +1,632 @@ +/* + +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 +#endif + +#include +#include +#include +#include +#include +#include /* for malloc() */ +#include + +#include "input.h" +#include "site.h" +#include "opaque.h" + +#ifdef WIN32 +#include +#define getpid(x) _getpid(x) +#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; + +/* 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) { + /* xalloc() can't be used yet. */ + logFileName = malloc(strlen(fname) + strlen(display) + 1); + if (!logFileName) + FatalError("Cannot allocate space for the log file name\n"); + sprintf(logFileName, fname, display); + + if (backup && *backup) { + struct stat buf; + + if (!stat(logFileName, &buf) && S_ISREG(buf.st_mode)) { + char *suffix; + char *oldLog; + + oldLog = malloc(strlen(logFileName) + strlen(backup) + + strlen(display) + 1); + suffix = malloc(strlen(backup) + strlen(display) + 1); + if (!oldLog || !suffix) + FatalError("Cannot allocate space for the log file name\n"); + sprintf(suffix, backup, display); + sprintf(oldLog, "%s%s", logFileName, suffix); + 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 xfree() */ + 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. */ + +_X_EXPORT void +LogVWrite(int verb, const char *f, va_list args) +{ + static char tmpBuffer[1024]; + int len = 0; + + /* + * Since a va_list can only be processed once, write the string to a + * buffer, and then write the buffer out to the appropriate output + * stream(s). + */ + if (verb < 0 || logFileVerbosity >= verb || logVerbosity >= verb) { + vsnprintf(tmpBuffer, sizeof(tmpBuffer), f, args); + len = strlen(tmpBuffer); + } + if ((verb < 0 || logVerbosity >= verb) && len > 0) + fwrite(tmpBuffer, len, 1, stderr); + if ((verb < 0 || logFileVerbosity >= verb) && len > 0) { + if (logFile) { + fwrite(tmpBuffer, len, 1, logFile); + if (logFlush) { + fflush(logFile); +#ifndef WIN32 + if (logSync) + fsync(fileno(logFile)); +#endif + } + } else if (needBuffer) { + /* + * Note, this code is used before OsInit() has been called, so + * xalloc() and friends can't be used. + */ + if (len > bufferUnused) { + bufferSize += 1024; + bufferUnused += 1024; + if (saveBuffer) + saveBuffer = realloc(saveBuffer, bufferSize); + else + saveBuffer = malloc(bufferSize); + if (!saveBuffer) + FatalError("realloc() failed while saving log messages\n"); + } + bufferUnused -= len; + memcpy(saveBuffer + bufferPos, tmpBuffer, len); + bufferPos += len; + } + } +} + +_X_EXPORT void +LogWrite(int verb, const char *f, ...) +{ + va_list args; + + va_start(args, f); + LogVWrite(verb, f, args); + va_end(args); +} + +_X_EXPORT void +LogVMessageVerb(MessageType type, int verb, const char *format, va_list args) +{ + const char *s = X_UNKNOWN_STRING; + char *tmpBuf = NULL; + + /* Ignore verbosity for X_ERROR */ + if (logVerbosity >= verb || logFileVerbosity >= verb || type == X_ERROR) { + switch (type) { + case X_PROBED: + s = X_PROBE_STRING; + break; + case X_CONFIG: + s = X_CONFIG_STRING; + break; + case X_DEFAULT: + s = X_DEFAULT_STRING; + break; + case X_CMDLINE: + s = X_CMDLINE_STRING; + break; + case X_NOTICE: + s = X_NOTICE_STRING; + break; + case X_ERROR: + s = X_ERROR_STRING; + if (verb > 0) + verb = 0; + break; + case X_WARNING: + s = X_WARNING_STRING; + break; + case X_INFO: + s = X_INFO_STRING; + break; + case X_NOT_IMPLEMENTED: + s = X_NOT_IMPLEMENTED_STRING; + break; + case X_UNKNOWN: + s = X_UNKNOWN_STRING; + break; + case X_NONE: + s = NULL; + break; + } + + /* + * Prefix the format string with the message type. We do it this way + * so that LogVWrite() is only called once per message. + */ + if (s) { + tmpBuf = malloc(strlen(format) + strlen(s) + 1 + 1); + /* Silently return if malloc fails here. */ + if (!tmpBuf) + return; + sprintf(tmpBuf, "%s ", s); + strcat(tmpBuf, format); + LogVWrite(verb, tmpBuf, args); + free(tmpBuf); + } else + LogVWrite(verb, format, args); + } +} + +/* Log message with verbosity level specified. */ +_X_EXPORT 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. */ +_X_EXPORT void +LogMessage(MessageType type, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + LogVMessageVerb(type, 1, format, ap); + va_end(ap); +} + +#ifdef __GNUC__ +void AbortServer(void) __attribute__((noreturn)); +#endif + +void +AbortServer(void) +{ + CloseWellKnownConnections(); + OsCleanup(TRUE); + CloseDownDevices(); + AbortDDX(); + fflush(stderr); + if (CoreDump) + abort(); + exit (1); +} + +#ifndef AUDIT_PREFIX +#define AUDIT_PREFIX "AUDIT: %s: %ld %s: " +#endif +#ifndef AUDIT_TIMEOUT +#define AUDIT_TIMEOUT ((CARD32)(120 * 1000)) /* 2 mn */ +#endif + +static int nrepeat = 0; +static int oldlen = -1; +static OsTimerPtr auditTimer = NULL; + +void +FreeAuditTimer(void) +{ + if (auditTimer != NULL) { + /* Force output of pending messages */ + TimerForce(auditTimer); + TimerFree(auditTimer); + auditTimer = NULL; + } +} + +static char * +AuditPrefix(void) +{ + time_t tm; + char *autime, *s; + char *tmpBuf; + int len; + + time(&tm); + autime = ctime(&tm); + if ((s = strchr(autime, '\n'))) + *s = '\0'; + if ((s = strrchr(argvGlobal[0], '/'))) + s++; + else + s = argvGlobal[0]; + len = strlen(AUDIT_PREFIX) + strlen(autime) + 10 + strlen(s) + 1; + tmpBuf = malloc(len); + if (!tmpBuf) + return NULL; + snprintf(tmpBuf, len, AUDIT_PREFIX, autime, (unsigned long)getpid(), s); + return tmpBuf; +} + +void +AuditF(const char * f, ...) +{ + va_list args; + + va_start(args, f); + + VAuditF(f, args); + va_end(args); +} + +static CARD32 +AuditFlush(OsTimerPtr timer, CARD32 now, pointer arg) +{ + char *prefix; + + if (nrepeat > 0) { + prefix = AuditPrefix(); + ErrorF("%slast message repeated %d times\n", + prefix != NULL ? prefix : "", nrepeat); + nrepeat = 0; + if (prefix != NULL) + free(prefix); + return AUDIT_TIMEOUT; + } else { + /* if the timer expires without anything to print, flush the message */ + oldlen = -1; + return 0; + } +} + +void +VAuditF(const char *f, va_list args) +{ + char *prefix; + char buf[1024]; + int len; + static char oldbuf[1024]; + + prefix = AuditPrefix(); + len = vsnprintf(buf, sizeof(buf), f, args); + +#if 1 + /* XXX Compressing duplicated messages is temporarily disabled to + * work around bugzilla 964: + * https://freedesktop.org/bugzilla/show_bug.cgi?id=964 + */ + ErrorF("%s%s", prefix != NULL ? prefix : "", buf); + oldlen = -1; + nrepeat = 0; +#else + 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); + } +#endif + if (prefix != NULL) + free(prefix); +} + +_X_EXPORT 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); + VErrorF(f, args); + va_end(args); + ErrorF("\n"); +#ifdef DDXOSFATALERROR + if (!beenhere) + OsVendorFatalError(); +#endif +#ifdef ABORTONFATALERROR + abort(); +#endif + if (!beenhere) { + beenhere = TRUE; + AbortServer(); + } else + abort(); + /*NOTREACHED*/ +} + +_X_EXPORT 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 +} + +_X_EXPORT void +ErrorF(const char * f, ...) +{ + va_list args; + + va_start(args, f); + VErrorF(f, args); + va_end(args); +} + +/* A perror() workalike. */ + +#ifndef NEED_STRERROR +#ifdef SYSV +#if !defined(ISC) || defined(ISC202) || defined(ISC22) +#define NEED_STRERROR +#endif +#endif +#endif + +#if defined(NEED_STRERROR) && !defined(strerror) +extern char *sys_errlist[]; +extern int sys_nerr; +#define strerror(n) \ + ((n) >= 0 && (n) < sys_nerr) ? sys_errlist[(n)] : "unknown error" +#endif + +_X_EXPORT void +Error(char *str) +{ + char *err = NULL; + int saveErrno = errno; + + if (str) { + err = malloc(strlen(strerror(saveErrno)) + strlen(str) + 2 + 1); + if (!err) + return; + sprintf(err, "%s: ", str); + strcat(err, strerror(saveErrno)); + LogWrite(-1, err); + } else + LogWrite(-1, strerror(saveErrno)); +} + +void +LogPrintMarkers(void) +{ + /* Show what the message marker symbols mean. */ + ErrorF("Markers: "); + LogMessageVerb(X_PROBED, -1, "probed, "); + LogMessageVerb(X_CONFIG, -1, "from config file, "); + LogMessageVerb(X_DEFAULT, -1, "default setting,\n\t"); + LogMessageVerb(X_CMDLINE, -1, "from command line, "); + LogMessageVerb(X_NOTICE, -1, "notice, "); + LogMessageVerb(X_INFO, -1, "informational,\n\t"); + LogMessageVerb(X_WARNING, -1, "warning, "); + LogMessageVerb(X_ERROR, -1, "error, "); + LogMessageVerb(X_NOT_IMPLEMENTED, -1, "not implemented, "); + LogMessageVerb(X_UNKNOWN, -1, "unknown.\n"); +} + diff --git a/xorg-server/os/mitauth.c b/xorg-server/os/mitauth.c new file mode 100644 index 000000000..db66c44fb --- /dev/null +++ b/xorg-server/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 +#endif + +#include +#include "os.h" +#include "osdep.h" +#include "dixstruct.h" + +static struct auth { + struct auth *next; + unsigned short len; + char *data; + XID id; +} *mit_auth; + +int +MitAddCookie ( + unsigned short data_length, + char *data, + XID id) +{ + struct auth *new; + + new = (struct auth *) xalloc (sizeof (struct auth)); + if (!new) + return 0; + new->data = (char *) xalloc ((unsigned) data_length); + if (!new->data) { + xfree(new); + return 0; + } + new->next = mit_auth; + mit_auth = new; + memmove(new->data, data, (int) data_length); + new->len = data_length; + new->id = id; + return 1; +} + +XID +MitCheckCookie ( + unsigned short data_length, + char *data, + ClientPtr client, + char **reason) +{ + struct auth *auth; + + for (auth = mit_auth; auth; auth=auth->next) { + if (data_length == auth->len && + 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; + xfree (auth->data); + xfree (auth); + } + mit_auth = 0; + return 0; +} + +XID +MitToID ( + unsigned short data_length, + char *data) +{ + struct auth *auth; + + for (auth = mit_auth; auth; auth=auth->next) { + if (data_length == auth->len && + memcmp (data, auth->data, data_length) == 0) + return auth->id; + } + return (XID) -1; +} + +int +MitFromID ( + XID id, + unsigned short *data_lenp, + char **datap) +{ + struct auth *auth; + + for (auth = mit_auth; auth; auth=auth->next) { + if (id == auth->id) { + *data_lenp = auth->len; + *datap = auth->data; + return 1; + } + } + return 0; +} + +int +MitRemoveCookie ( + unsigned short data_length, + char *data) +{ + struct auth *auth, *prev; + + prev = 0; + for (auth = mit_auth; auth; prev = auth, auth=auth->next) { + if (data_length == auth->len && + memcmp (data, auth->data, data_length) == 0) + { + if (prev) + prev->next = auth->next; + else + mit_auth = auth->next; + xfree (auth->data); + xfree (auth); + return 1; + } + } + return 0; +} + +#ifdef XCSECURITY + +static char cookie[16]; /* 128 bits */ + +XID +MitGenerateCookie ( + unsigned data_length, + char *data, + XID id, + unsigned *data_length_return, + char **data_return) +{ + int i = 0; + int status; + + while (data_length--) + { + cookie[i++] += *data++; + if (i >= sizeof (cookie)) i = 0; + } + GenerateRandomData(sizeof (cookie), cookie); + status = MitAddCookie(sizeof (cookie), cookie, id); + if (!status) + { + id = -1; + } + else + { + *data_return = cookie; + *data_length_return = sizeof (cookie); + } + return id; +} + +#endif /* XCSECURITY */ diff --git a/xorg-server/os/os.c b/xorg-server/os/os.c new file mode 100644 index 000000000..e69de29bb diff --git a/xorg-server/os/oscolor.c b/xorg-server/os/oscolor.c new file mode 100644 index 000000000..f3ff9beac --- /dev/null +++ b/xorg-server/os/oscolor.c @@ -0,0 +1,139 @@ +/*********************************************************** + +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 +#endif + +#include +#include "os.h" + +typedef struct _builtinColor { + unsigned char red; + unsigned char green; + unsigned char blue; + unsigned short name; +} BuiltinColor; + +/* These have to come after the struct definition because despair. */ +#include "oscolor.h" +#define NUM_BUILTIN_COLORS (sizeof (BuiltinColors) / sizeof (BuiltinColors[0])) + +static unsigned char +OsToLower (unsigned char a) +{ + if ((a >= XK_A) && (a <= XK_Z)) + return a + (XK_a - XK_A); + else if ((a >= XK_Agrave) && (a <= XK_Odiaeresis)) + return a + (XK_agrave - XK_Agrave); + else if ((a >= XK_Ooblique) && (a <= XK_Thorn)) + return a + (XK_oslash - XK_Ooblique); + else + return a; +} + +static int +OsStrCaseCmp (const unsigned char *s1, const unsigned char *s2, int l2) +{ + unsigned char c1, c2; + + for (;;) + { + c1 = OsToLower (*s1++); + if (l2 == 0) + c2 = '\0'; + else + c2 = OsToLower (*s2++); + if (!c1 || !c2) + break; + if (c1 != c2) + break; + l2--; + } + return c2 - c1; +} + +Bool +OsInitColors(void) +{ + return TRUE; +} + +Bool +OsLookupColor(int screen, + char *s_name, + unsigned int len, + unsigned short *pred, + unsigned short *pgreen, + unsigned short *pblue) +{ + const BuiltinColor *c; + unsigned char *name = (unsigned char *) s_name; + int low, mid, high; + int r; + + low = 0; + high = NUM_BUILTIN_COLORS - 1; + while (high >= low) + { + mid = (low + high) / 2; + c = &BuiltinColors[mid]; + r = OsStrCaseCmp (&BuiltinColorNames[c->name], name, len); + if (r == 0) + { + *pred = c->red * 0x101; + *pgreen = c->green * 0x101; + *pblue = c->blue * 0x101; + return TRUE; + } + if (r < 0) + high = mid - 1; + else + low = mid + 1; + } + return FALSE; +} diff --git a/xorg-server/os/oscolor.h b/xorg-server/os/oscolor.h new file mode 100644 index 000000000..3d0a76222 --- /dev/null +++ b/xorg-server/os/oscolor.h @@ -0,0 +1,1508 @@ +static const unsigned 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 */ +}; diff --git a/xorg-server/os/osdep.h b/xorg-server/os/osdep.h new file mode 100644 index 000000000..b6894c146 --- /dev/null +++ b/xorg-server/os/osdep.h @@ -0,0 +1,289 @@ +/*********************************************************** + +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 +#endif + +#ifndef _OSDEP_H_ +#define _OSDEP_H_ 1 + +#define BOTIMEOUT 200 /* in milliseconds */ +#define BUFSIZE 4096 +#define BUFWATERMARK 8192 + +#include + +#ifndef sgi /* SGI defines OPEN_MAX in a useless way */ +#ifndef X_NOT_POSIX +#ifdef _POSIX_SOURCE +#include +#else +#define _POSIX_SOURCE +#include +#undef _POSIX_SOURCE +#endif +#else /* X_NOT_POSIX */ +#ifdef WIN32 +#define _POSIX_ +#include +#undef _POSIX_ +#endif +#endif /* X_NOT_POSIX */ +#endif + +#ifdef __QNX__ +#define NOFILES_MAX 256 +#endif +#ifndef OPEN_MAX +#ifdef SVR4 +#define OPEN_MAX 256 +#else +#include +#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 + +/* + * 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(hpux) && !defined(SVR4) && !defined(SYSV) +#define HAS_GETDTABLESIZE +#endif +#endif + +#include + +typedef Bool (*ValidatorFunc)(ARRAY8Ptr Auth, ARRAY8Ptr Data, int packet_type); +typedef Bool (*GeneratorFunc)(ARRAY8Ptr Auth, ARRAY8Ptr Data, int packet_type); +typedef Bool (*AddAuthorFunc)(unsigned name_length, char *name, unsigned data_length, char *data); + +typedef struct _connectionInput { + struct _connectionInput *next; + char *buffer; /* contains current client input */ + char *bufptr; /* pointer to current start of data */ + int bufcnt; /* count of bytes in buffer */ + int lenLastReq; + int size; +} ConnectionInput, *ConnectionInputPtr; + +typedef struct _connectionOutput { + struct _connectionOutput *next; + int size; + unsigned char *buf; + int count; +} ConnectionOutput, *ConnectionOutputPtr; + +struct _osComm; + +#define AuthInitArgs void +typedef void (*AuthInitFunc) (AuthInitArgs); + +#define AuthAddCArgs unsigned short data_length, char *data, XID id +typedef int (*AuthAddCFunc) (AuthAddCArgs); + +#define AuthCheckArgs unsigned short data_length, char *data, ClientPtr client, char **reason +typedef XID (*AuthCheckFunc) (AuthCheckArgs); + +#define AuthFromIDArgs XID id, unsigned short *data_lenp, char **datap +typedef int (*AuthFromIDFunc) (AuthFromIDArgs); + +#define AuthGenCArgs unsigned data_length, char *data, XID id, unsigned *data_length_return, char **data_return +typedef XID (*AuthGenCFunc) (AuthGenCArgs); + +#define AuthRemCArgs unsigned short data_length, char *data +typedef int (*AuthRemCFunc) (AuthRemCArgs); + +#define AuthRstCArgs void +typedef int (*AuthRstCFunc) (AuthRstCArgs); + +#define AuthToIDArgs unsigned short data_length, char *data +typedef XID (*AuthToIDFunc) (AuthToIDArgs); + +typedef void (*OsCloseFunc)(ClientPtr); + +typedef int (*OsFlushFunc)(ClientPtr who, struct _osComm * oc, char* extraBuf, int extraCount); + +typedef struct _osComm { + int fd; + ConnectionInputPtr input; + ConnectionOutputPtr output; + XID auth_id; /* authorization id */ + CARD32 conn_time; /* timestamp if not established, else 0 */ + struct _XtransConnInfo *trans_conn; /* transport connection object */ +} OsCommRec, *OsCommPtr; + +extern int FlushClient( + ClientPtr /*who*/, + OsCommPtr /*oc*/, + char* /*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(); +#endif + +extern Bool NewOutputPending; +extern Bool AnyClientsWriteBlocked; + +extern WorkQueuePtr workQueue; + +/* added by raphael */ +#ifdef WIN32 +typedef long int fd_mask; +#endif +#define ffs mffs +extern int mffs(fd_mask); + +/* in auth.c */ +extern void GenerateRandomData (int len, char *buf); + +/* in mitauth.c */ +extern XID MitCheckCookie (AuthCheckArgs); +extern XID MitGenerateCookie (AuthGenCArgs); +extern XID MitToID (AuthToIDArgs); +extern int MitAddCookie (AuthAddCArgs); +extern int MitFromID (AuthFromIDArgs); +extern int MitRemoveCookie (AuthRemCArgs); +extern int MitResetCookie (AuthRstCArgs); + +/* in xdmauth.c */ +#ifdef HASXDMAUTH +extern XID XdmCheckCookie (AuthCheckArgs); +extern XID XdmToID (AuthToIDArgs); +extern int XdmAddCookie (AuthAddCArgs); +extern int XdmFromID (AuthFromIDArgs); +extern int XdmRemoveCookie (AuthRemCArgs); +extern int XdmResetCookie (AuthRstCArgs); +#endif + +/* in rpcauth.c */ +#ifdef SECURE_RPC +extern void SecureRPCInit (AuthInitArgs); +extern XID SecureRPCCheck (AuthCheckArgs); +extern XID SecureRPCToID (AuthToIDArgs); +extern int SecureRPCAdd (AuthAddCArgs); +extern int SecureRPCFromID (AuthFromIDArgs); +extern int SecureRPCRemove (AuthRemCArgs); +extern int SecureRPCReset (AuthRstCArgs); +#endif + +/* in xdmcp.c */ +extern void XdmcpUseMsg (void); +extern int XdmcpOptions(int argc, char **argv, int i); +extern void XdmcpRegisterConnection ( + int type, + char *address, + int addrlen); +extern void XdmcpRegisterAuthorizations (void); +extern void XdmcpRegisterAuthorization (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 ( + char *name, + int namelen, + char *data, + int datalen, + ValidatorFunc Validator, + GeneratorFunc Generator, + AddAuthorFunc AddAuth); + +struct sockaddr_in; +extern void XdmcpRegisterBroadcastAddress (struct sockaddr_in *addr); + +#ifdef HASXDMAUTH +extern void XdmAuthenticationInit (char *cookie, int cookie_length); +#endif + +#endif /* _OSDEP_H_ */ diff --git a/xorg-server/os/osinit.c b/xorg-server/os/osinit.c new file mode 100644 index 000000000..1bc8624dc --- /dev/null +++ b/xorg-server/os/osinit.c @@ -0,0 +1,233 @@ +/*********************************************************** + +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 +#endif + +#include +#include +#include "os.h" +#include "osdep.h" +#include + +#ifdef SMART_SCHEDULE +#include "dixstruct.h" +#endif + +#ifndef PATH_MAX +#ifdef MAXPATHLEN +#define PATH_MAX MAXPATHLEN +#else +#define PATH_MAX 1024 +#endif +#endif + +#if defined(Lynx) || defined(__SCO__) +#include +#endif + +#if !defined(SYSV) && !defined(WIN32) && !defined(Lynx) && !defined(QNX4) +#include +#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 + +Bool OsDelayInitColors = FALSE; + +void +OsInit(void) +{ + static Bool been_here = FALSE; + static char* admpath = ADMPATH; + static char* devnull = "/dev/null"; + char fname[PATH_MAX]; + +#ifdef macII + set42sig(); +#endif + + if (!been_here) { +#if !defined(__SCO__) && !defined(__CYGWIN__) && !defined(__UNIXWARE__) + fclose(stdin); + fclose(stdout); +#endif + /* + * If a write of zero bytes to stderr returns non-zero, i.e. -1, + * then writing to stderr failed, and we'll write somewhere else + * instead. (Apparently this never happens in the Real World.) + */ + if (write (2, fname, 0) == -1) + { + FILE *err; + + if (strlen (display) + strlen (admpath) + 1 < sizeof fname) + sprintf (fname, admpath, display); + else + strcpy (fname, devnull); + /* + * uses stdio to avoid os dependencies here, + * a real os would use + * open (fname, O_WRONLY|O_APPEND|O_CREAT, 0666) + */ + if (!(err = fopen (fname, "a+"))) + err = fopen (devnull, "w"); + if (err && (fileno(err) != 2)) { + dup2 (fileno (err), 2); + fclose (err); + } +#if defined(SYSV) || defined(SVR4) || defined(WIN32) || defined(__CYGWIN__) + { + static char buf[BUFSIZ]; + setvbuf (stderr, buf, _IOLBF, BUFSIZ); + } +#else + setlinebuf(stderr); +#endif + } + +#ifndef X_NOT_POSIX + if (getpgrp () == 0) + setpgid (0, 0); +#else +#if !defined(SYSV) && !defined(WIN32) + if (getpgrp (0) == 0) + setpgrp (0, getpid ()); +#endif +#endif + +#ifdef RLIMIT_DATA + if (limitDataSpace >= 0) + { + struct rlimit rlim; + + if (!getrlimit(RLIMIT_DATA, &rlim)) + { + if ((limitDataSpace > 0) && (limitDataSpace < rlim.rlim_max)) + rlim.rlim_cur = limitDataSpace; + else + rlim.rlim_cur = rlim.rlim_max; + (void)setrlimit(RLIMIT_DATA, &rlim); + } + } +#endif +#ifdef RLIMIT_STACK + if (limitStackSpace >= 0) + { + struct rlimit rlim; + + if (!getrlimit(RLIMIT_STACK, &rlim)) + { + if ((limitStackSpace > 0) && (limitStackSpace < rlim.rlim_max)) + rlim.rlim_cur = limitStackSpace; + else + rlim.rlim_cur = rlim.rlim_max; + (void)setrlimit(RLIMIT_STACK, &rlim); + } + } +#endif +#ifdef RLIMIT_NOFILE + if (limitNoFile >= 0) + { + struct rlimit rlim; + + if (!getrlimit(RLIMIT_NOFILE, &rlim)) + { + if ((limitNoFile > 0) && (limitNoFile < rlim.rlim_max)) + rlim.rlim_cur = limitNoFile; + else + rlim.rlim_cur = rlim.rlim_max; + (void)setrlimit(RLIMIT_NOFILE, &rlim); + } + } +#endif +#ifdef SERVER_LOCK + LockServer(); +#endif + been_here = TRUE; + } + TimerInit(); +#ifdef DDXOSINIT + OsVendorInit(); +#endif + /* + * No log file by default. OsVendorInit() should call LogInit() with the + * log file name if logging to a file is desired. + */ + LogInit(NULL, NULL); +#ifdef SMART_SCHEDULE + if (!SmartScheduleDisable) + if (!SmartScheduleInit ()) + SmartScheduleDisable = TRUE; +#endif + OsInitAllocator(); + if (!OsDelayInitColors) OsInitColors(); +} + +void +OsCleanup(Bool terminating) +{ +#ifdef SERVER_LOCK + if (terminating) + { + UnlockServer(); + } +#endif +} diff --git a/xorg-server/os/rpcauth.c b/xorg-server/os/rpcauth.c new file mode 100644 index 000000000..3451ac18b --- /dev/null +++ b/xorg-server/os/rpcauth.c @@ -0,0 +1,202 @@ +/* + +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 +#endif + +#ifdef SECURE_RPC + +#include +#include +#include "misc.h" +#include "os.h" +#include "dixstruct.h" + +#include + +#ifdef sun +/* only includes this if _KERNEL is #defined... */ +extern bool_t xdr_opaque_auth(XDR *, struct opaque_auth *); +#endif + +#if defined(DGUX) +#include +#include +#endif /* DGUX */ + +#ifdef ultrix +#include +#include +#endif + +static enum auth_stat why; + +static char * +authdes_ezdecode(char *inmsg, int len) +{ + struct rpc_msg msg; + char cred_area[MAX_AUTH_BYTES]; + char verf_area[MAX_AUTH_BYTES]; + char *temp_inmsg; + struct svc_req r; + bool_t res0, res1; + XDR xdr; + SVCXPRT xprt; + + temp_inmsg = (char *) xalloc(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 = (caddr_t) xalloc(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: + xfree(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, 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, 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, char *data) +{ + return 0; +} +#endif /* SECURE_RPC */ diff --git a/xorg-server/os/strlcat.c b/xorg-server/os/strlcat.c new file mode 100644 index 000000000..b57fcc563 --- /dev/null +++ b/xorg-server/os/strlcat.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1998 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE + * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include + +/* + * 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/xorg-server/os/strlcpy.c b/xorg-server/os/strlcpy.c new file mode 100644 index 000000000..989d0385e --- /dev/null +++ b/xorg-server/os/strlcpy.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 1998 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE + * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include + +/* + * 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/xorg-server/os/utils.c b/xorg-server/os/utils.c new file mode 100644 index 000000000..f58c76366 --- /dev/null +++ b/xorg-server/os/utils.c @@ -0,0 +1,2244 @@ +/* + +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 +#endif + +#ifdef __CYGWIN__ +#include +#include +#endif + +#if defined(WIN32) && !defined(__CYGWIN__) +#include +#endif +#include +#include +#include +#if !defined(WIN32) || !defined(__MINGW32__) +#include +#include +#endif +#include "misc.h" +#include +#define XSERV_t +#define TRANS_SERVER +#define TRANS_REOPEN +#include +#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 +#undef _POSIX_C_SOURCE +#else +#if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE) +#include +#else +#define _POSIX_SOURCE +#include +#undef _POSIX_SOURCE +#endif +#endif +#ifndef WIN32 +#include +#endif +#if !defined(SYSV) && !defined(WIN32) && !defined(Lynx) && !defined(QNX4) +#include +#endif +#include +#include /* for isspace */ +#include + +#if defined(DGUX) +#include +#include +#endif + +#include /* for malloc() */ + +#if defined(TCPCONN) || defined(STREAMSCONN) +# ifndef WIN32 +# include +# endif +#endif + +#include "opaque.h" + +#ifdef SMART_SCHEDULE +#include "dixstruct.h" +#endif + +#ifdef XKB +#include +#endif + +#ifdef RENDER +#include "picture.h" +#endif + +#ifdef XPRINT +#include "DiPrint.h" +#endif + +_X_EXPORT Bool noTestExtensions; +#ifdef BIGREQS +_X_EXPORT Bool noBigReqExtension = FALSE; +#endif +#ifdef COMPOSITE +_X_EXPORT Bool noCompositeExtension = FALSE; +#endif + +#ifdef DAMAGE +_X_EXPORT Bool noDamageExtension = FALSE; +#endif +#ifdef DBE +_X_EXPORT Bool noDbeExtension = FALSE; +#endif +#ifdef DPMSExtension +_X_EXPORT Bool noDPMSExtension = FALSE; +#endif +#ifdef EVI +_X_EXPORT Bool noEVIExtension = FALSE; +#endif +#ifdef FONTCACHE +_X_EXPORT Bool noFontCacheExtension = FALSE; +#endif +#ifdef GLXEXT +_X_EXPORT Bool noGlxExtension = FALSE; +_X_EXPORT Bool noGlxVisualInit = FALSE; +#endif +#ifdef SCREENSAVER +_X_EXPORT Bool noScreenSaverExtension = FALSE; +#endif +#ifdef MITSHM +_X_EXPORT Bool noMITShmExtension = FALSE; +#endif +#ifdef MITMISC +_X_EXPORT Bool noMITMiscExtension = FALSE; +#endif +#ifdef MULTIBUFFER +_X_EXPORT Bool noMultibufferExtension = FALSE; +#endif +#ifdef RANDR +_X_EXPORT Bool noRRExtension = FALSE; +#endif +#ifdef RENDER +_X_EXPORT Bool noRenderExtension = FALSE; +#endif +#ifdef SHAPE +_X_EXPORT Bool noShapeExtension = FALSE; +#endif +#ifdef XCSECURITY +_X_EXPORT Bool noSecurityExtension = FALSE; +#endif +#ifdef XSYNC +_X_EXPORT Bool noSyncExtension = FALSE; +#endif +#ifdef TOGCUP +_X_EXPORT Bool noXcupExtension = FALSE; +#endif +#ifdef RES +_X_EXPORT Bool noResExtension = FALSE; +#endif +#ifdef XAPPGROUP +_X_EXPORT Bool noXagExtension = FALSE; +#endif +#ifdef XCMISC +_X_EXPORT Bool noXCMiscExtension = FALSE; +#endif +#ifdef XEVIE +/* Xevie is disabled by default for now until the + * interface is stable */ +_X_EXPORT Bool noXevieExtension = TRUE; +#endif +#ifdef XF86BIGFONT +_X_EXPORT Bool noXFree86BigfontExtension = FALSE; +#endif +#ifdef XFreeXDGA +_X_EXPORT Bool noXFree86DGAExtension = FALSE; +#endif +#ifdef XF86DRI +_X_EXPORT Bool noXFree86DRIExtension = FALSE; +#endif +#ifdef XF86MISC +_X_EXPORT Bool noXFree86MiscExtension = FALSE; +#endif +#ifdef XF86VIDMODE +_X_EXPORT Bool noXFree86VidModeExtension = FALSE; +#endif +#ifdef XFIXES +_X_EXPORT Bool noXFixesExtension = FALSE; +#endif +/* |noXkbExtension| is defined in xc/programs/Xserver/xkb/xkbInit.c */ +#ifdef PANORAMIX +/* Xinerama is disabled by default unless enabled via +xinerama */ +_X_EXPORT Bool noPanoramiXExtension = TRUE; +#endif +#ifdef XINPUT +_X_EXPORT Bool noXInputExtension = FALSE; +#endif +#ifdef XIDLE +_X_EXPORT Bool noXIdleExtension = FALSE; +#endif +#ifdef XSELINUX +_X_EXPORT Bool noSELinuxExtension = TRUE; +_X_EXPORT int selinuxEnforcingState = SELINUX_MODE_DEFAULT; +#endif +#ifdef XV +_X_EXPORT Bool noXvExtension = FALSE; +#endif +#ifdef DRI2 +_X_EXPORT Bool noDRI2Extension = FALSE; +#endif + +#define X_INCLUDE_NETDB_H +#include + +#include + +Bool CoreDump; + +#ifdef PANORAMIX +Bool PanoramiXExtensionDisabledHack = FALSE; +#endif + +int auditTrailLevel = 1; + +_X_EXPORT Bool Must_have_memory = FALSE; + +#ifdef AIXV3 +int SyncOn = 0; +extern int SelectWaitTime; +#endif + +#if defined(SVR4) || defined(__linux__) || defined(CSRG_BASED) +#define HAS_SAVED_IDS_AND_SETEUID +#endif + +#ifdef MEMBUG +#define MEM_FAIL_SCALE 100000 +long Memory_fail = 0; +#include /* for random() */ +#endif + +static char *dev_tty_from_init = NULL; /* since we need to parse it anyway */ + +OsSigHandlerPtr +OsSignal(sig, handler) + int sig; + OsSigHandlerPtr handler; +{ +#ifdef X_NOT_POSIX + return signal(sig, handler); +#else + struct sigaction act, oact; + + sigemptyset(&act.sa_mask); + if (handler != SIG_IGN) + sigaddset(&act.sa_mask, sig); + act.sa_flags = 0; + act.sa_handler = handler; + if (sigaction(sig, &act, &oact)) + perror("sigaction"); + return oact.sa_handler; +#endif +} + +#ifdef SERVER_LOCK +/* + * Explicit support for a server lock file like the ones used for UUCP. + * For architectures with virtual terminals that can run more than one + * server at a time. This keeps the servers from stomping on each other + * if the user forgets to give them different display numbers. + */ +#define LOCK_DIR "/tmp" +#define LOCK_TMP_PREFIX "/.tX" +#define LOCK_PREFIX "/.X" +#define LOCK_SUFFIX "-lock" + +#if defined(DGUX) +#include +#include +#endif + +#ifndef PATH_MAX +#ifndef Lynx +#include +#else +#include +#endif +#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); +#ifndef USE_CHMOD + (void) fchmod(lfd, 0444); +#else + (void) chmod(tmp, 0444); +#endif + (void) close(lfd); + + /* + * OK. Now the tmp file exists. Try three times to move it in place + * for the lock. + */ + i = 0; + haslock = 0; + while ((!haslock) && (i++ < 3)) { + haslock = (link(tmp,LockFile) == 0); + if (haslock) { + /* + * We're done. + */ + break; + } + else { + /* + * Read the pid from the existing file + */ + lfd = open(LockFile, O_RDONLY); + 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); + } +} +#endif /* SERVER_LOCK */ + +/* Force connections to close on SIGHUP from init */ + +/*ARGSUSED*/ +SIGVAL +AutoResetServer (int sig) +{ + int olderrno = errno; + + dispatchException |= DE_RESET; + isItTimeToYield = TRUE; +#ifdef GPROF + chdir ("/tmp"); + exit (0); +#endif +#if defined(SYSV) && defined(X_NOT_POSIX) + OsSignal (SIGHUP, AutoResetServer); +#endif + errno = olderrno; +} + +/* Force connections to close and then exit on SIGTERM, SIGINT */ + +/*ARGSUSED*/ +_X_EXPORT SIGVAL +GiveUp(int sig) +{ + int olderrno = errno; + + dispatchException |= DE_TERMINATE; + isItTimeToYield = TRUE; +#if defined(SYSV) && defined(X_NOT_POSIX) + if (sig) + OsSignal(sig, SIG_IGN); +#endif + errno = olderrno; +} + +#if defined WIN32 && defined __MINGW32__ +_X_EXPORT CARD32 +GetTimeInMillis (void) +{ + return GetTickCount (); +} +#else +_X_EXPORT CARD32 +GetTimeInMillis(void) +{ + struct timeval tv; + +#ifdef MONOTONIC_CLOCK + struct timespec tp; + if (clock_gettime(CLOCK_MONOTONIC, &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 + +_X_EXPORT 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) +{ +#if !defined(AIXrt) && !defined(AIX386) + ErrorF("use: X [:] [option]\n"); + ErrorF("-a # mouse acceleration (pixels)\n"); + ErrorF("-ac disable access control restrictions\n"); +#ifdef MEMBUG + ErrorF("-alloc int chance alloc should fail\n"); +#endif + ErrorF("-audit int set audit trail level\n"); + ErrorF("-auth file select authorization file\n"); + ErrorF("-br create root window with black background\n"); + ErrorF("+bs enable any backing store support\n"); + ErrorF("-bs disable any backing store support\n"); + ErrorF("-c turns off key-click\n"); + ErrorF("c # key-click volume (0-100)\n"); + ErrorF("-cc int default color visual class\n"); +#ifdef COMMANDLINE_CHALLENGED_OPERATING_SYSTEMS + ErrorF("-config file read options from file\n"); +#endif + ErrorF("-core generate core dump on fatal error\n"); + ErrorF("-dpi int screen resolution in dots per inch\n"); +#ifdef DPMSExtension + ErrorF("dpms enables VESA DPMS monitor control\n"); + ErrorF("-dpms disables VESA DPMS monitor control\n"); +#endif + ErrorF("-deferglyphs [none|all|16] defer loading of [no|all|16-bit] glyphs\n"); + ErrorF("-f # bell base (0-100)\n"); + ErrorF("-fc string cursor font\n"); + ErrorF("-fn string default font name\n"); + ErrorF("-fp string default font path\n"); + ErrorF("-help prints message with these options\n"); + ErrorF("-I ignore all remaining arguments\n"); +#ifdef RLIMIT_DATA + ErrorF("-ld int limit data space to N Kb\n"); +#endif +#ifdef RLIMIT_NOFILE + ErrorF("-lf int limit number of open files to N\n"); +#endif +#ifdef RLIMIT_STACK + ErrorF("-ls int limit stack space to N Kb\n"); +#endif +#ifdef SERVER_LOCK + ErrorF("-nolock disable the locking mechanism\n"); +#endif +#ifndef NOLOGOHACK + ErrorF("-logo enable logo in screen saver\n"); + ErrorF("nologo disable logo in screen saver\n"); +#endif + ErrorF("-nolisten string don't listen on protocol\n"); + ErrorF("-noreset don't reset after last client exists\n"); + ErrorF("-reset reset after last client exists\n"); + ErrorF("-p # screen-saver pattern duration (minutes)\n"); + ErrorF("-pn accept failure to listen on all ports\n"); + ErrorF("-nopn reject failure to listen on all ports\n"); + ErrorF("-r turns off auto-repeat\n"); + ErrorF("r turns on auto-repeat \n"); +#ifdef RENDER + ErrorF("-render [default|mono|gray|color] set render color alloc policy\n"); +#endif + ErrorF("-s # screen-saver timeout (minutes)\n"); +#ifdef XPRINT + PrinterUseMsg(); +#endif + ErrorF("-su disable any save under support\n"); + ErrorF("-t # mouse threshold (pixels)\n"); + ErrorF("-terminate terminate at server reset\n"); + ErrorF("-to # connection time out\n"); + ErrorF("-tst disable testing extensions\n"); + ErrorF("ttyxx server started from init on /dev/ttyxx\n"); + ErrorF("v video blanking for screen-saver\n"); + ErrorF("-v screen-saver without video blanking\n"); + ErrorF("-wm WhenMapped default backing-store\n"); + ErrorF("-wr create root window with white background\n"); + ErrorF("-x string loads named extension at init time \n"); + ErrorF("-maxbigreqsize set maximal bigrequest size \n"); +#ifdef PANORAMIX + ErrorF("+xinerama Enable XINERAMA extension\n"); + ErrorF("-xinerama Disable XINERAMA extension\n"); +#endif +#ifdef SMART_SCHEDULE + ErrorF("-dumbSched Disable smart scheduling, enable old behavior\n"); + ErrorF("-schedInterval int Set scheduler interval in msec\n"); +#endif + ErrorF("+extension name Enable extension\n"); + ErrorF("-extension name Disable extension\n"); +#ifdef XDMCP + XdmcpUseMsg(); +#endif +#endif /* !AIXrt && ! AIX386 */ +#ifdef XKB + XkbUseMsg(); +#endif + ddxUseMsg(); +} + +/* This function performs a rudimentary sanity check + * on the display name passed in on the command-line, + * since this string is used to generate filenames. + * It is especially important that the display name + * not contain a "/" and not start with a "-". + * --kvajk + */ +static int +VerifyDisplayName(const char *d) +{ + if ( d == (char *)0 ) return( 0 ); /* null */ + if ( *d == '\0' ) return( 0 ); /* empty */ + if ( *d == '-' ) return( 0 ); /* could be confused for an option */ + if ( *d == '.' ) return( 0 ); /* must not equal "." or ".." */ + if ( strchr(d, '/') != (char *)0 ) return( 0 ); /* very important!!! */ + return( 1 ); +} + +/* + * This function is responsible for doing initalisation of any global + * variables at an very early point of server startup (even before + * |ProcessCommandLine()|. + */ +void InitGlobals(void) +{ + ddxInitGlobals(); +} + + +/* + * This function parses the command line. Handles device-independent fields + * and allows ddx to handle additional fields. It is not allowed to modify + * argc or any of the strings pointed to by argv. + */ +void +ProcessCommandLine(int argc, char *argv[]) +{ + int i, skip; + + defaultKeyboardControl.autoRepeat = TRUE; + +#ifdef NO_PART_NET + PartialNetwork = FALSE; +#else + PartialNetwork = TRUE; +#endif + + for ( i = 1; i < argc; i++ ) + { + /* call ddx first, so it can peek/override if it wants */ + if((skip = ddxProcessArgument(argc, argv, i))) + { + i += (skip - 1); + } + else if(argv[i][0] == ':') + { + /* initialize display */ + display = argv[i]; + display++; + if( ! VerifyDisplayName( display ) ) { + ErrorF("Bad display name: %s\n", display); + UseMsg(); + FatalError("Bad display name, exiting: %s\n", display); + } + } + else if ( strcmp( argv[i], "-a") == 0) + { + if(++i < argc) + defaultPointerControl.num = atoi(argv[i]); + else + UseMsg(); + } + else if ( strcmp( argv[i], "-ac") == 0) + { + defeatAccessControl = TRUE; + } +#ifdef MEMBUG + else if ( strcmp( argv[i], "-alloc") == 0) + { + if(++i < argc) + Memory_fail = atoi(argv[i]); + else + UseMsg(); + } +#endif + else if ( strcmp( argv[i], "-audit") == 0) + { + if(++i < argc) + auditTrailLevel = atoi(argv[i]); + else + UseMsg(); + } + else if ( strcmp( argv[i], "-auth") == 0) + { + if(++i < argc) + InitAuthorization (argv[i]); + else + UseMsg(); + } + else if ( strcmp( argv[i], "-br") == 0) + blackRoot = TRUE; + else if ( strcmp( argv[i], "+bs") == 0) + enableBackingStore = TRUE; + else if ( strcmp( argv[i], "-bs") == 0) + disableBackingStore = TRUE; + else if ( strcmp( argv[i], "c") == 0) + { + if(++i < argc) + defaultKeyboardControl.click = atoi(argv[i]); + else + UseMsg(); + } + else if ( strcmp( argv[i], "-c") == 0) + { + defaultKeyboardControl.click = 0; + } + else if ( strcmp( argv[i], "-cc") == 0) + { + if(++i < argc) + defaultColorVisualClass = atoi(argv[i]); + else + UseMsg(); + } + else if ( strcmp( argv[i], "-core") == 0) + { + CoreDump = TRUE; +#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 + } + 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) + DPMSEnabledSwitch = TRUE; + 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); + } +#ifdef XKB + else if ( (skip=XkbProcessArguments(argc,argv,i))!=0 ) { + if (skip>0) + i+= skip-1; + else UseMsg(); + } +#endif +#ifdef RLIMIT_DATA + else if ( strcmp( argv[i], "-ld") == 0) + { + if(++i < argc) + { + limitDataSpace = atoi(argv[i]); + if (limitDataSpace > 0) + limitDataSpace *= 1024; + } + else + UseMsg(); + } +#endif +#ifdef RLIMIT_NOFILE + else if ( strcmp( argv[i], "-lf") == 0) + { + if(++i < argc) + limitNoFile = atoi(argv[i]); + else + UseMsg(); + } +#endif +#ifdef RLIMIT_STACK + else if ( strcmp( argv[i], "-ls") == 0) + { + if(++i < argc) + { + limitStackSpace = atoi(argv[i]); + if (limitStackSpace > 0) + limitStackSpace *= 1024; + } + else + UseMsg(); + } +#endif +#ifdef SERVER_LOCK + else if ( strcmp ( argv[i], "-nolock") == 0) + { +#if !defined(WIN32) && !defined(__CYGWIN__) + if (getuid() != 0) + ErrorF("Warning: the -nolock option can only be used by root\n"); + else +#endif + nolock = TRUE; + } +#endif +#ifndef NOLOGOHACK + else if ( strcmp( argv[i], "-logo") == 0) + { + logoScreenSaver = 1; + } + else if ( strcmp( argv[i], "nologo") == 0) + { + logoScreenSaver = 0; + } +#endif + else if ( strcmp( argv[i], "-nolisten") == 0) + { + if(++i < argc) { + 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], "-s") == 0) + { + if(++i < argc) + defaultScreenSaverTime = ((CARD32)atoi(argv[i])) * + MILLI_PER_MIN; + else + UseMsg(); + } + else if ( strcmp( argv[i], "-su") == 0) + disableSaveUnders = TRUE; + else if ( strcmp( argv[i], "-t") == 0) + { + if(++i < argc) + defaultPointerControl.threshold = atoi(argv[i]); + else + UseMsg(); + } + else if ( strcmp( argv[i], "-terminate") == 0) + { + dispatchExceptionAtReset = DE_TERMINATE; + } + else if ( strcmp( argv[i], "-to") == 0) + { + if(++i < argc) + TimeOutValue = ((CARD32)atoi(argv[i])) * MILLI_PER_SECOND; + else + UseMsg(); + } + else if ( strcmp( argv[i], "-tst") == 0) + { + noTestExtensions = TRUE; + } + else if ( strcmp( argv[i], "v") == 0) + defaultScreenSaverBlanking = PreferBlanking; + else if ( strcmp( argv[i], "-v") == 0) + defaultScreenSaverBlanking = DontPreferBlanking; + else if ( strcmp( argv[i], "-wm") == 0) + defaultBackingStore = WhenMapped; + else if ( strcmp( argv[i], "-wr") == 0) + whiteRoot = TRUE; + 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], "-x") == 0) + { + if(++i >= argc) + UseMsg(); + /* For U**x, which doesn't support dynamic loading, there's nothing + * to do when we see a -x. Either the extension is linked in or + * it isn't */ + } + else if ( strcmp( argv[i], "-I") == 0) + { + /* ignore all remaining arguments */ + break; + } + else if (strncmp (argv[i], "tty", 3) == 0) + { + /* just in case any body is interested */ + dev_tty_from_init = argv[i]; + } +#ifdef XDMCP + else if ((skip = XdmcpOptions(argc, argv, i)) != i) + { + i = skip - 1; + } +#endif +#ifdef XPRINT + else if ((skip = PrinterOptions(argc, argv, i)) != i) + { + i = skip - 1; + } +#endif +#ifdef AIXV3 + else if ( strcmp( argv[i], "-timeout") == 0) + { + if(++i < argc) + SelectWaitTime = atoi(argv[i]); + else + UseMsg(); + } + else if ( strcmp( argv[i], "-sync") == 0) + { + SyncOn++; + } +#endif +#ifdef SMART_SCHEDULE + 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(); + } +#endif +#ifdef RENDER + else if ( strcmp( argv[i], "-render" ) == 0) + { + if (++i < argc) + { + int policy = PictureParseCmapPolicy (argv[i]); + + if (policy != PictureCmapPolicyInvalid) + PictureCmapPolicy = policy; + else + UseMsg (); + } + else + UseMsg (); + } +#endif + else if ( strcmp( argv[i], "+extension") == 0) + { + if (++i < argc) + { + if (!EnableDisableExtension(argv[i], TRUE)) + EnableDisableExtensionError(argv[i], TRUE); + } + else + UseMsg(); + } + else if ( strcmp( argv[i], "-extension") == 0) + { + if (++i < argc) + { + if (!EnableDisableExtension(argv[i], FALSE)) + EnableDisableExtensionError(argv[i], FALSE); + } + else + UseMsg(); + } + else + { + ErrorF("Unrecognized option: %s\n", argv[i]); + UseMsg(); + FatalError("Unrecognized option: %s\n", argv[i]); + } + } +} + +#ifdef COMMANDLINE_CHALLENGED_OPERATING_SYSTEMS +static void +InsertFileIntoCommandLine( + int *resargc, char ***resargv, + int prefix_argc, char **prefix_argv, + char *filename, + int suffix_argc, char **suffix_argv) +{ + struct stat st; + FILE *f; + char *p; + char *q; + int insert_argc; + char *buf; + int len; + int i; + + f = fopen(filename, "r"); + if (!f) + FatalError("Can't open option file %s\n", filename); + + fstat(fileno(f), &st); + + buf = (char *) xalloc((unsigned) st.st_size + 1); + if (!buf) + FatalError("Out of Memory\n"); + + len = fread(buf, 1, (unsigned) st.st_size, f); + + fclose(f); + + if (len < 0) + FatalError("Error reading option file %s\n", filename); + + buf[len] = '\0'; + + p = buf; + q = buf; + insert_argc = 0; + + while (*p) + { + while (isspace(*p)) + p++; + if (!*p) + break; + if (*p == '#') + { + while (*p && *p != '\n') + p++; + } else + { + while (*p && !isspace(*p)) + *q++ = *p++; + /* Since p and q might still be pointing at the same place, we */ + /* need to step p over the whitespace now before we add the null. */ + if (*p) + p++; + *q++ = '\0'; + insert_argc++; + } + } + + buf = (char *) xrealloc(buf, q - buf); + if (!buf) + FatalError("Out of memory reallocing option buf\n"); + + *resargc = prefix_argc + insert_argc + suffix_argc; + *resargv = (char **) xalloc((*resargc + 1) * sizeof(char *)); + if (!*resargv) + FatalError("Out of Memory\n"); + + memcpy(*resargv, prefix_argv, prefix_argc * sizeof(char *)); + + p = buf; + for (i = 0; i < insert_argc; i++) + { + (*resargv)[prefix_argc + i] = p; + p += strlen(p) + 1; + } + + memcpy(*resargv + prefix_argc + insert_argc, + suffix_argv, suffix_argc * sizeof(char *)); + + (*resargv)[*resargc] = NULL; +} /* end InsertFileIntoCommandLine */ + + +void +ExpandCommandLine(int *pargc, char ***pargv) +{ + int i; + +#if !defined(WIN32) && !defined(__CYGWIN__) + if (getuid() != geteuid()) + return; +#endif + + for (i = 1; i < *pargc; i++) + { + if ( (0 == strcmp((*pargv)[i], "-config")) && (i < (*pargc - 1)) ) + { + InsertFileIntoCommandLine(pargc, pargv, + i, *pargv, + (*pargv)[i+1], /* filename */ + *pargc - i - 2, *pargv + i + 2); + i--; + } + } +} /* end ExpandCommandLine */ +#endif + +/* Implement a simple-minded font authorization scheme. The authorization + name is "hp-hostname-1", the contents are simply the host name. */ +int +set_font_authorizations(char **authorizations, int *authlen, 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) + bzero(&hints, sizeof(hints)); + hints.ai_flags = AI_CANONNAME; + if (getaddrinfo(hname, NULL, &hints, &ai) == 0) { + hnameptr = ai->ai_canonname; + } else { + hnameptr = hname; + } +#else + host = _XGethostbyname(hname, hparams); + if (host == NULL) + hnameptr = hname; + else + hnameptr = host->h_name; +#endif + + len = strlen(hnameptr) + 1; + result = xalloc(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 */ +} + +/* XALLOC -- X's internal memory allocator. Why does it return unsigned + * long * instead of the more common char *? Well, if you read K&R you'll + * see they say that alloc must return a pointer "suitable for conversion" + * to whatever type you really want. In a full-blown generic allocator + * there's no way to solve the alignment problems without potentially + * wasting lots of space. But we have a more limited problem. We know + * we're only ever returning pointers to structures which will have to + * be long word aligned. So we are making a stronger guarantee. It might + * have made sense to make Xalloc return char * to conform with people's + * expectations of malloc, but this makes lint happier. + */ + +#ifndef INTERNAL_MALLOC + +_X_EXPORT void * +Xalloc(unsigned long amount) +{ + register pointer ptr; + + if ((long)amount <= 0) { + return (unsigned long *)NULL; + } + /* aligned extra on long word boundary */ + amount = (amount + (sizeof(long) - 1)) & ~(sizeof(long) - 1); +#ifdef MEMBUG + if (!Must_have_memory && Memory_fail && + ((random() % MEM_FAIL_SCALE) < Memory_fail)) + return (unsigned long *)NULL; +#endif + if ((ptr = (pointer)malloc(amount))) { + return (unsigned long *)ptr; + } + if (Must_have_memory) + FatalError("Out of memory"); + return (unsigned long *)NULL; +} + +/***************** + * XNFalloc + * "no failure" realloc, alternate interface to Xalloc w/o Must_have_memory + *****************/ + +_X_EXPORT void * +XNFalloc(unsigned long amount) +{ + register pointer ptr; + + if ((long)amount <= 0) + { + return (unsigned long *)NULL; + } + /* aligned extra on long word boundary */ + amount = (amount + (sizeof(long) - 1)) & ~(sizeof(long) - 1); + ptr = (pointer)malloc(amount); + if (!ptr) + { + FatalError("Out of memory"); + } + return ((unsigned long *)ptr); +} + +/***************** + * Xcalloc + *****************/ + +_X_EXPORT void * +Xcalloc(unsigned long amount) +{ + unsigned long *ret; + + ret = Xalloc (amount); + if (ret) + bzero ((char *) ret, (int) amount); + return ret; +} + +/***************** + * XNFcalloc + *****************/ + +_X_EXPORT void * +XNFcalloc(unsigned long amount) +{ + unsigned long *ret; + + ret = Xalloc (amount); + if (ret) + bzero ((char *) ret, (int) amount); + else if ((long)amount > 0) + FatalError("Out of memory"); + return ret; +} + +/***************** + * Xrealloc + *****************/ + +_X_EXPORT void * +Xrealloc(pointer ptr, unsigned long amount) +{ +#ifdef MEMBUG + if (!Must_have_memory && Memory_fail && + ((random() % MEM_FAIL_SCALE) < Memory_fail)) + return (unsigned long *)NULL; +#endif + if ((long)amount <= 0) + { + if (ptr && !amount) + free(ptr); + return (unsigned long *)NULL; + } + amount = (amount + (sizeof(long) - 1)) & ~(sizeof(long) - 1); + if (ptr) + ptr = (pointer)realloc((char *)ptr, amount); + else + ptr = (pointer)malloc(amount); + if (ptr) + return (unsigned long *)ptr; + if (Must_have_memory) + FatalError("Out of memory"); + return (unsigned long *)NULL; +} + +/***************** + * XNFrealloc + * "no failure" realloc, alternate interface to Xrealloc w/o Must_have_memory + *****************/ + +_X_EXPORT void * +XNFrealloc(pointer ptr, unsigned long amount) +{ + if (( ptr = (pointer)Xrealloc( ptr, amount ) ) == NULL) + { + if ((long)amount > 0) + FatalError( "Out of memory" ); + } + return ((unsigned long *)ptr); +} + +/***************** + * Xfree + * calls free + *****************/ + +_X_EXPORT void +Xfree(pointer ptr) +{ + if (ptr) + free((char *)ptr); +} + +void +OsInitAllocator (void) +{ +#ifdef MEMBUG + static int been_here; + + /* Check the memory system after each generation */ + if (been_here) + CheckMemory (); + else + been_here = 1; +#endif +} +#endif /* !INTERNAL_MALLOC */ + + +char * +Xstrdup(const char *s) +{ + char *sd; + + if (s == NULL) + return NULL; + + sd = (char *)Xalloc(strlen(s) + 1); + if (sd != NULL) + strcpy(sd, s); + return sd; +} + + +_X_EXPORT char * +XNFstrdup(const char *s) +{ + char *sd; + + if (s == NULL) + return NULL; + + sd = (char *)XNFalloc(strlen(s) + 1); + strcpy(sd, s); + return sd; +} + +#ifdef SMART_SCHEDULE + +#ifdef SIGVTALRM +#define SMART_SCHEDULE_POSSIBLE +#endif + +#ifdef SMART_SCHEDULE_POSSIBLE +#define SMART_SCHEDULE_SIGNAL SIGALRM +#define SMART_SCHEDULE_TIMER ITIMER_REAL +#endif + +void +SmartScheduleStopTimer (void) +{ +#ifdef SMART_SCHEDULE_POSSIBLE + 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); +#endif +} + +void +SmartScheduleStartTimer (void) +{ +#ifdef SMART_SCHEDULE_POSSIBLE + 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); +#endif +} + +#ifdef SMART_SCHEDULE_POSSIBLE +static void +SmartScheduleTimer (int sig) +{ + SmartScheduleTime += SmartScheduleInterval; +} +#endif + +Bool +SmartScheduleInit (void) +{ +#ifdef SMART_SCHEDULE_POSSIBLE + struct sigaction act; + + if (SmartScheduleDisable) + return TRUE; + + bzero ((char *) &act, sizeof(struct sigaction)); + + /* Set up the timer signal function */ + act.sa_handler = SmartScheduleTimer; + sigemptyset (&act.sa_mask); + sigaddset (&act.sa_mask, SMART_SCHEDULE_SIGNAL); + if (sigaction (SMART_SCHEDULE_SIGNAL, &act, 0) < 0) + { + perror ("sigaction for smart scheduler"); + return FALSE; + } + return TRUE; +#else + return FALSE; +#endif +} +#endif + +#ifdef SIG_BLOCK +static sigset_t PreviousSignalMask; +static int BlockedSignalCount; +#endif + +void +OsBlockSignals (void) +{ +#ifdef SIG_BLOCK + if (BlockedSignalCount++ == 0) + { + sigset_t set; + + sigemptyset (&set); +#ifdef SIGALRM + sigaddset (&set, SIGALRM); +#endif +#ifdef SIGVTALRM + sigaddset (&set, SIGVTALRM); +#endif +#ifdef SIGWINCH + sigaddset (&set, SIGWINCH); +#endif +#ifdef SIGIO + sigaddset (&set, SIGIO); +#endif +#ifdef SIGTSTP + sigaddset (&set, SIGTSTP); +#endif +#ifdef SIGTTIN + sigaddset (&set, SIGTTIN); +#endif +#ifdef SIGTTOU + sigaddset (&set, SIGTTOU); +#endif +#ifdef SIGCHLD + sigaddset (&set, SIGCHLD); +#endif + sigprocmask (SIG_BLOCK, &set, &PreviousSignalMask); + } +#endif +} + +void +OsReleaseSignals (void) +{ +#ifdef SIG_BLOCK + if (--BlockedSignalCount == 0) + { + sigprocmask (SIG_SETMASK, &PreviousSignalMask, 0); + } +#endif +} + +#if !defined(WIN32) +/* + * "safer" versions of system(3), popen(3) and pclose(3) which give up + * all privs before running a command. + * + * This is based on the code in FreeBSD 2.2 libc. + * + * XXX It'd be good to redirect stderr so that it ends up in the log file + * as well. As it is now, xkbcomp messages don't end up in the log file. + */ + +int +System(char *command) +{ + int pid, p; +#ifdef SIGCHLD + void (*csig)(int); +#endif + int status; + + if (!command) + return(1); + +#ifdef SIGCHLD + csig = signal(SIGCHLD, SIG_DFL); + if (csig == SIG_ERR) { + perror("signal"); + return -1; + } +#endif + +#ifdef DEBUG + ErrorF("System: `%s'\n", command); +#endif + + 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); + + } + +#ifdef SIGCHLD + if (signal(SIGCHLD, csig) == SIG_ERR) { + perror("signal"); + return -1; + } +#endif + + return p == -1 ? -1 : status; +} + +static struct pid { + struct pid *next; + FILE *fp; + int pid; +} *pidlist; + +void (*old_alarm)(int) = 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 = (struct pid *)xalloc(sizeof(struct pid))) == NULL) + return NULL; + + if (pipe(pdes) < 0) { + xfree(cur); + return NULL; + } + + /* Ignore the smart scheduler while this is going on */ + old_alarm = signal(SIGALRM, SIG_IGN); + if (old_alarm == SIG_ERR) { + perror("signal"); + return NULL; + } + + switch (pid = fork()) { + case -1: /* error */ + close(pdes[0]); + close(pdes[1]); + xfree(cur); + if (signal(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; + +#ifdef DEBUG + ErrorF("Popen: `%s', fp = %p\n", command, iop); +#endif + + 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 = (struct pid *)xalloc(sizeof(struct pid))) == NULL) + return NULL; + + if (pipe(pdes) < 0) { + xfree(cur); + return NULL; + } + + switch (pid = fork()) { + case -1: /* error */ + close(pdes[0]); + close(pdes[1]); + xfree(cur); + return NULL; + case 0: /* child */ + if (setgid(getgid()) == -1) + _exit(127); + if (setuid(getuid()) == -1) + _exit(127); + if (*type == 'r') { + if (pdes[1] != 1) { + /* stdout */ + dup2(pdes[1], 1); + close(pdes[1]); + } + close(pdes[0]); + } else { + if (pdes[0] != 0) { + /* stdin */ + dup2(pdes[0], 0); + close(pdes[0]); + } + close(pdes[1]); + } + execl("/bin/cat", "cat", file, (char *)NULL); + _exit(127); + } + + /* Avoid EINTR during stdio calls */ + OsBlockSignals (); + + /* parent */ + if (*type == 'r') { + iop = fdopen(pdes[0], type); + close(pdes[1]); + } else { + iop = fdopen(pdes[1], type); + close(pdes[0]); + } + + cur->fp = iop; + cur->pid = pid; + cur->next = pidlist; + pidlist = cur; + +#ifdef DEBUG + ErrorF("Fopen(%s), fp = %p\n", file, iop); +#endif + + return iop; +#else + int ruid, euid; + + ruid = getuid(); + euid = geteuid(); + + if (seteuid(ruid) == -1) { + return NULL; + } + iop = fopen(file, type); + + if (seteuid(euid) == -1) { + fclose(iop); + return NULL; + } + return iop; +#endif /* HAS_SAVED_IDS_AND_SETEUID */ +} + +int +Pclose(pointer iop) +{ + struct pid *cur, *last; + int pstat; + int pid; + +#ifdef DEBUG + ErrorF("Pclose: fp = %p\n", iop); +#endif + + fclose(iop); + + for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next) + if (cur->fp == iop) + break; + if (cur == NULL) + return -1; + + do { + pid = waitpid(cur->pid, &pstat, 0); + } while (pid == -1 && errno == EINTR); + + if (last == NULL) + pidlist = cur->next; + else + last->next = cur->next; + xfree(cur); + + /* allow EINTR again */ + OsReleaseSignals (); + + if (old_alarm && signal(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 +#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 defined(__QNX__) && !defined(__QNXNTO__) + char cmd_name[64]; +#endif + +#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 +#include +#include +#endif /* USE_PAM */ + +void +CheckUserAuthorization(void) +{ +#ifdef USE_PAM + static struct pam_conv conv = { + misc_conv, + NULL + }; + + pam_handle_t *pamh = NULL; + struct passwd *pw; + int retval; + + if (getuid() != geteuid()) { + pw = getpwuid(getuid()); + if (pw == NULL) + FatalError("getpwuid() failed for uid %d\n", getuid()); + + retval = pam_start("xserver", pw->pw_name, &conv, &pamh); + if (retval != PAM_SUCCESS) + FatalError("pam_start() failed.\n" + "\tMissing or mangled PAM config file or module?\n"); + + retval = pam_authenticate(pamh, 0); + if (retval != PAM_SUCCESS) { + pam_end(pamh, retval); + FatalError("PAM authentication failed, cannot start X server.\n" + "\tPerhaps you do not have console ownership?\n"); + } + + retval = pam_acct_mgmt(pamh, 0); + if (retval != PAM_SUCCESS) { + pam_end(pamh, retval); + FatalError("PAM authentication failed, cannot start X server.\n" + "\tPerhaps you do not have console ownership?\n"); + } + + /* this is not a session, so do not do session management */ + pam_end(pamh, PAM_SUCCESS); + } +#endif +} + +#ifdef __SCO__ +#include + +static void +lockit (int fd, short what) +{ + struct flock lck; + + lck.l_whence = 0; + lck.l_start = 0; + lck.l_len = 1; + lck.l_type = what; + + (void)fcntl (fd, F_SETLKW, &lck); +} + +/* SCO OpenServer 5 lacks pread/pwrite. Emulate them. */ +ssize_t +pread (int fd, void *buf, size_t nbytes, off_t offset) +{ + off_t saved; + ssize_t ret; + + lockit (fd, F_RDLCK); + saved = lseek (fd, 0, SEEK_CUR); + lseek (fd, offset, SEEK_SET); + ret = read (fd, buf, nbytes); + lseek (fd, saved, SEEK_SET); + lockit (fd, F_UNLCK); + + return ret; +} + +ssize_t +pwrite (int fd, const void *buf, size_t nbytes, off_t offset) +{ + off_t saved; + ssize_t ret; + + lockit (fd, F_WRLCK); + saved = lseek (fd, 0, SEEK_CUR); + lseek (fd, offset, SEEK_SET); + ret = write (fd, buf, nbytes); + lseek (fd, saved, SEEK_SET); + lockit (fd, F_UNLCK); + + return ret; +} +#endif /* __SCO__ */ diff --git a/xorg-server/os/xdmauth.c b/xorg-server/os/xdmauth.c new file mode 100644 index 000000000..d143ddefc --- /dev/null +++ b/xorg-server/os/xdmauth.c @@ -0,0 +1,497 @@ +/* + +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 +#endif + +#include +#include +#define XSERV_t +#define TRANS_SERVER +#define TRANS_REOPEN +#include +#include "os.h" +#include "osdep.h" +#include "dixstruct.h" + +#ifdef HASXDMAUTH + +static Bool authFromXDMCP; + +#ifdef XDMCP +#include +#undef REQUEST +#include + +/* 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, &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 (&rho, &privateKey, outgoingData->data, 8); + } + return TRUE; +} + +static Bool +XdmAuthenticationAddAuth (int name_len, char *name, + int data_len, char *data) +{ + Bool ret; + XdmcpUnwrap (data, (unsigned char *)&privateKey, data, data_len); + authFromXDMCP = TRUE; + ret = AddAuthorization (name_len, name, data_len, data); + authFromXDMCP = FALSE; + return ret; +} + + +#define atox(c) ('0' <= c && c <= '9' ? c - '0' : \ + 'a' <= c && c <= 'f' ? c - 'a' + 10 : \ + 'A' <= c && c <= 'F' ? c - 'A' + 10 : -1) + +static int +HexToBinary (char *in, char *out, int len) +{ + int top, bottom; + + while (len > 0) + { + top = atox(in[0]); + if (top == -1) + return 0; + bottom = atox(in[1]); + if (bottom == -1) + return 0; + *out++ = (top << 4) | bottom; + in += 2; + len -= 2; + } + if (len) + return 0; + *out++ = '\0'; + return 1; +} + +void +XdmAuthenticationInit (char *cookie, int cookie_len) +{ + bzero (privateKey.data, 8); + if (!strncmp (cookie, "0x", 2) || !strncmp (cookie, "0X", 2)) + { + if (cookie_len > 2 + 2 * 8) + cookie_len = 2 + 2 * 8; + HexToBinary (cookie + 2, (char *)privateKey.data, cookie_len - 2); + } + else + { + if (cookie_len > 7) + cookie_len = 7; + memmove (privateKey.data + 1, cookie, cookie_len); + } + XdmcpGenerateKey (&rho); + XdmcpRegisterAuthentication (XdmAuthenticationName, XdmAuthenticationNameLen, + (unsigned char *)&rho, + sizeof (rho), + (ValidatorFunc)XdmAuthenticationValidator, + (GeneratorFunc)XdmAuthenticationGenerator, + (AddAuthorFunc)XdmAuthenticationAddAuth); +} + +#endif /* XDMCP */ + +/* XDM-AUTHORIZATION-1 */ +typedef struct _XdmAuthorization { + struct _XdmAuthorization *next; + XdmAuthKeyRec rho; + XdmAuthKeyRec key; + XID id; +} XdmAuthorizationRec, *XdmAuthorizationPtr; + +static XdmAuthorizationPtr xdmAuth; + +typedef struct _XdmClientAuth { + struct _XdmClientAuth *next; + XdmAuthKeyRec rho; + char client[6]; + long time; +} XdmClientAuthRec, *XdmClientAuthPtr; + +static XdmClientAuthPtr xdmClients; +static long clockOffset; +static Bool gotClock; + +#define TwentyMinutes (20 * 60) +#define TwentyFiveMinutes (25 * 60) + +static Bool +XdmClientAuthCompare (XdmClientAuthPtr a, XdmClientAuthPtr b) +{ + int i; + + if (!XdmcpCompareKeys (&a->rho, &b->rho)) + return FALSE; + for (i = 0; i < 6; i++) + if (a->client[i] != b->client[i]) + return FALSE; + return a->time == b->time; +} + +static void +XdmClientAuthDecode (unsigned char *plain, XdmClientAuthPtr auth) +{ + int i, j; + + j = 0; + for (i = 0; i < 8; i++) + { + auth->rho.data[i] = plain[j]; + ++j; + } + for (i = 0; i < 6; i++) + { + auth->client[i] = plain[j]; + ++j; + } + auth->time = 0; + for (i = 0; i < 4; i++) + { + auth->time |= plain[j] << ((3 - i) << 3); + j++; + } +} + +static void +XdmClientAuthTimeout (long now) +{ + XdmClientAuthPtr client, next, prev; + + prev = 0; + for (client = xdmClients; client; client=next) + { + next = client->next; + if (abs (now - client->time) > TwentyFiveMinutes) + { + if (prev) + prev->next = next; + else + xdmClients = next; + xfree (client); + } + else + prev = client; + } +} + +static XdmClientAuthPtr +XdmAuthorizationValidate (unsigned char *plain, int length, + XdmAuthKeyPtr rho, ClientPtr xclient, char **reason) +{ + XdmClientAuthPtr client, existing; + long now; + int i; + + if (length != (192 / 8)) { + if (reason) + *reason = "Bad XDM authorization key length"; + return NULL; + } + client = (XdmClientAuthPtr) xalloc (sizeof (XdmClientAuthRec)); + if (!client) + return NULL; + XdmClientAuthDecode (plain, client); + if (!XdmcpCompareKeys (&client->rho, rho)) + { + xfree (client); + if (reason) + *reason = "Invalid XDM-AUTHORIZATION-1 key (failed key comparison)"; + return NULL; + } + for (i = 18; i < 24; i++) + if (plain[i] != 0) { + xfree (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) { + xfree (client); + xfree (addr); + if (reason) + *reason = "Invalid XDM-AUTHORIZATION-1 key (failed address comparison)"; + return NULL; + + } +#endif + xfree (addr); + } + } + now = time(0); + if (!gotClock) + { + clockOffset = client->time - now; + gotClock = TRUE; + } + now += clockOffset; + XdmClientAuthTimeout (now); + if (abs (client->time - now) > TwentyMinutes) + { + xfree (client); + if (reason) + *reason = "Excessive XDM-AUTHORIZATION-1 time offset"; + return NULL; + } + for (existing = xdmClients; existing; existing=existing->next) + { + if (XdmClientAuthCompare (existing, client)) + { + xfree (client); + if (reason) + *reason = "XDM authorization key matches an existing client!"; + return NULL; + } + } + return client; +} + +int +XdmAddCookie (unsigned short data_length, char *data, XID id) +{ + XdmAuthorizationPtr new; + unsigned char *rho_bits, *key_bits; + + switch (data_length) + { + case 16: /* auth from files is 16 bytes long */ +#ifdef XDMCP + if (authFromXDMCP) + { + /* R5 xdm sent bogus authorization data in the accept packet, + * but we can recover */ + rho_bits = rho.data; + key_bits = (unsigned char *) data; + key_bits[0] = '\0'; + } + else +#endif + { + rho_bits = (unsigned char *) data; + key_bits = (unsigned char *) (data + 8); + } + break; +#ifdef XDMCP + case 8: /* auth from XDMCP is 8 bytes long */ + rho_bits = rho.data; + key_bits = (unsigned char *) data; + break; +#endif + default: + return 0; + } + /* the first octet of the key must be zero */ + if (key_bits[0] != '\0') + return 0; + new = (XdmAuthorizationPtr) xalloc (sizeof (XdmAuthorizationRec)); + if (!new) + return 0; + new->next = xdmAuth; + xdmAuth = new; + memmove (new->key.data, key_bits, (int) 8); + memmove (new->rho.data, rho_bits, (int) 8); + new->id = id; + return 1; +} + +XID +XdmCheckCookie (unsigned short cookie_length, char *cookie, + ClientPtr xclient, char **reason) +{ + XdmAuthorizationPtr auth; + XdmClientAuthPtr client; + unsigned char *plain; + + /* Auth packets must be a multiple of 8 bytes long */ + if (cookie_length & 7) + return (XID) -1; + plain = (unsigned char *) xalloc (cookie_length); + if (!plain) + return (XID) -1; + for (auth = xdmAuth; auth; auth=auth->next) { + XdmcpUnwrap (cookie, (unsigned char *)&auth->key, plain, cookie_length); + if ((client = XdmAuthorizationValidate (plain, cookie_length, &auth->rho, xclient, reason)) != NULL) + { + client->next = xdmClients; + xdmClients = client; + xfree (plain); + return auth->id; + } + } + xfree (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; + xfree (auth); + } + xdmAuth = 0; + for (client = xdmClients; client; client=next_client) + { + next_client = client->next; + xfree (client); + } + xdmClients = (XdmClientAuthPtr) 0; + return 1; +} + +XID +XdmToID (unsigned short cookie_length, char *cookie) +{ + XdmAuthorizationPtr auth; + XdmClientAuthPtr client; + unsigned char *plain; + + plain = (unsigned char *) xalloc (cookie_length); + if (!plain) + return (XID) -1; + for (auth = xdmAuth; auth; auth=auth->next) { + XdmcpUnwrap (cookie, (unsigned char *)&auth->key, plain, cookie_length); + if ((client = XdmAuthorizationValidate (plain, cookie_length, &auth->rho, NULL, NULL)) != NULL) + { + xfree (client); + xfree (cookie); + xfree (plain); + return auth->id; + } + } + xfree (cookie); + xfree (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, 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 = ρ + 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; + xfree (auth); + return 1; + } + } + return 0; +} + +#endif diff --git a/xorg-server/os/xdmcp.c b/xorg-server/os/xdmcp.c new file mode 100644 index 000000000..310f33bc0 --- /dev/null +++ b/xorg-server/os/xdmcp.c @@ -0,0 +1,1670 @@ +/* + * 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 +#endif + +#ifdef WIN32 +#include +#endif + +#include + +#if !defined(WIN32) +#ifndef Lynx +#include +#include +#else +#include +#endif +#include +#include +#endif + +#include +#include +#include +#include +#include "misc.h" +#include +#include "osdep.h" +#include "input.h" +#include "dixstruct.h" +#include "opaque.h" + +#if defined(DGUX) +#include +#include +#endif + +#ifdef STREAMSCONN +#include +#include +#include +#endif + +#ifdef XDMCP +#undef REQUEST + +#ifdef XDMCP_NO_IPV6 +#undef IPv6 +#endif + +#include + +#define X_INCLUDE_NETDB_H +#include + +extern char *defaultDisplayClass; + +static int xdmcpSocket, sessionSocket; +static xdmcp_states state; +#if defined(IPv6) && defined(AF_INET6) +static int xdmcpSocket6; +static struct sockaddr_storage req_sockaddr; +#else +static struct sockaddr_in req_sockaddr; +#endif +static int req_socklen; +static CARD32 SessionID; +static CARD32 timeOutTime; +static int timeOutRtx; +static 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( + struct sockaddr *from, + int fromlen, + ARRAY8Ptr AuthenticationName, + ARRAY8Ptr hostname, + ARRAY8Ptr status); + +static void XdmcpSelectHost( + struct sockaddr *host_sockaddr, + int host_len, + ARRAY8Ptr AuthenticationName); + +static void get_xdmcp_sock(void); + +static void send_query_msg(void); + +static void recv_willing_msg( + struct sockaddr * /*from*/, + int /*fromlen*/, + unsigned /*length*/); + +static void send_request_msg(void); + +static void recv_accept_msg(unsigned /*length*/); + +static void recv_decline_msg(unsigned /*length*/); + +static void send_manage_msg(void); + +static void recv_refuse_msg(unsigned /*length*/); + +static void recv_failed_msg(unsigned /*length*/); + +static void send_keepalive_msg(void); + +static void recv_alive_msg(unsigned /*length*/); + +static void XdmcpFatal( + char * /*type*/, + ARRAY8Ptr /*status*/); + +static void XdmcpWarning(char * /*str*/); + +static void get_manager_by_name( + int /*argc*/, + char ** /*argv*/, + int /*i*/); + +static void get_fromaddr_by_name(int /*argc*/, char ** /*argv*/, int /*i*/); + +#if defined(IPv6) && defined(AF_INET6) +static int get_mcast_options(int /*argc*/, char ** /*argv*/, int /*i*/); +#endif + +static void receive_packet(int /*socketfd*/); + +static void send_packet(void); + +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 (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 (struct sockaddr_in *addr) +{ + struct sockaddr_in *bcast; + if (NumBroadcastAddresses >= MAX_BROADCAST) + return; + bcast = &BroadcastAddresses[NumBroadcastAddresses++]; + bzero (bcast, sizeof (struct sockaddr_in)); +#ifdef BSD44SOCKETS + bcast->sin_len = addr->sin_len; +#endif + bcast->sin_family = addr->sin_family; + bcast->sin_port = htons (xdm_udp_port); + bcast->sin_addr = addr->sin_addr; +} + +/* + * Each authentication type is registered here; Validator + * will be called to check all access attempts using + * the specified authentication type + */ + +static ARRAYofARRAY8 AuthenticationNames, AuthenticationDatas; +typedef struct _AuthenticationFuncs { + ValidatorFunc Validator; + GeneratorFunc Generator; + AddAuthorFunc AddAuth; +} AuthenticationFuncsRec, *AuthenticationFuncsPtr; + +static AuthenticationFuncsPtr AuthenticationFuncsList; + +void +XdmcpRegisterAuthentication ( + char *name, + int namelen, + char *data, + int datalen, + ValidatorFunc Validator, + GeneratorFunc Generator, + AddAuthorFunc AddAuth) +{ + int i; + ARRAY8 AuthenticationName, AuthenticationData; + static AuthenticationFuncsPtr newFuncs; + + if (!XdmcpAllocARRAY8 (&AuthenticationName, namelen)) + return; + if (!XdmcpAllocARRAY8 (&AuthenticationData, datalen)) + { + XdmcpDisposeARRAY8 (&AuthenticationName); + return; + } + for (i = 0; i < namelen; i++) + AuthenticationName.data[i] = name[i]; + for (i = 0; i < datalen; i++) + AuthenticationData.data[i] = data[i]; + if (!(XdmcpReallocARRAYofARRAY8 (&AuthenticationNames, + AuthenticationNames.length + 1) && + XdmcpReallocARRAYofARRAY8 (&AuthenticationDatas, + AuthenticationDatas.length + 1) && + (newFuncs = (AuthenticationFuncsPtr) xalloc ( + (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; + xfree (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 (ARRAY8Ptr name) +{ + int i; + + for (i = 0; i < AuthenticationNames.length; i++) + if (XdmcpARRAY8Equal (&AuthenticationNames.data[i], name)) + { + AuthenticationName = &AuthenticationNames.data[i]; + AuthenticationData = &AuthenticationDatas.data[i]; + AuthenticationFuncs = &AuthenticationFuncsList[i]; + break; + } +} + +/* + * Register the host address for the display + */ + +static ARRAY16 ConnectionTypes; +static ARRAYofARRAY8 ConnectionAddresses; +static long xdmcpGeneration; + +void +XdmcpRegisterConnection ( + int type, + char *address, + int addrlen) +{ + int i; + CARD8 *newAddress; + + if (xdmcpGeneration != serverGeneration) + { + XdmcpDisposeARRAY16 (&ConnectionTypes); + XdmcpDisposeARRAYofARRAY8 (&ConnectionAddresses); + xdmcpGeneration = serverGeneration; + } + if (xdm_from != NULL) { /* Only register the requested address */ + const void *regAddr = address; + const void *fromAddr = NULL; + int regAddrlen = addrlen; + + if (addrlen == sizeof(struct in_addr)) { + if (SOCKADDR_FAMILY(FromAddress) == AF_INET) { + fromAddr = &((struct sockaddr_in *)&FromAddress)->sin_addr; + } +#if defined(IPv6) && defined(AF_INET6) + else if ((SOCKADDR_FAMILY(FromAddress) == AF_INET6) && + IN6_IS_ADDR_V4MAPPED( + &((struct sockaddr_in6 *)&FromAddress)->sin6_addr)) { + fromAddr = &((struct sockaddr_in6 *)&FromAddress)->sin6_addr.s6_addr[12]; + } +#endif + } +#if defined(IPv6) && defined(AF_INET6) + else if (addrlen == sizeof(struct in6_addr)) { + if (SOCKADDR_FAMILY(FromAddress) == AF_INET6) { + fromAddr = &((struct sockaddr_in6 *)&FromAddress)->sin6_addr; + } else if ((SOCKADDR_FAMILY(FromAddress) == AF_INET) && + IN6_IS_ADDR_V4MAPPED((struct in6_addr *) address)) { + fromAddr = &((struct sockaddr_in *)&FromAddress)->sin_addr; + regAddr = &((struct sockaddr_in6 *)&address)->sin6_addr.s6_addr[12]; + regAddrlen = sizeof(struct in_addr); + } + } +#endif + if (fromAddr && memcmp(regAddr, fromAddr, regAddrlen) != 0) { + return; + } + } + newAddress = (CARD8 *) xalloc (addrlen * sizeof (CARD8)); + if (!newAddress) + return; + if (!XdmcpReallocARRAY16 (&ConnectionTypes, ConnectionTypes.length + 1)) + { + xfree (newAddress); + return; + } + if (!XdmcpReallocARRAYofARRAY8 (&ConnectionAddresses, + ConnectionAddresses.length + 1)) + { + xfree (newAddress); + return; + } + ConnectionTypes.data[ConnectionTypes.length - 1] = (CARD16) type; + for (i = 0; i < addrlen; i++) + newAddress[i] = address[i]; + ConnectionAddresses.data[ConnectionAddresses.length-1].data = newAddress; + ConnectionAddresses.data[ConnectionAddresses.length-1].length = addrlen; +} + +/* + * Register an Authorization Name. XDMCP advertises this list + * to the manager. + */ + +static ARRAYofARRAY8 AuthorizationNames; + +void +XdmcpRegisterAuthorizations (void) +{ + XdmcpDisposeARRAYofARRAY8 (&AuthorizationNames); + RegisterAuthorizations (); +} + +void +XdmcpRegisterAuthorization (char *name, int namelen) +{ + ARRAY8 authName; + int i; + + authName.data = (CARD8 *) xalloc (namelen * sizeof (CARD8)); + if (!authName.data) + return; + if (!XdmcpReallocARRAYofARRAY8 (&AuthorizationNames, AuthorizationNames.length +1)) + { + xfree (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 (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( + struct sockaddr *host_sockaddr, + int host_len, + ARRAY8Ptr AuthenticationName) +{ + state = XDM_START_CONNECTION; + memmove(&req_sockaddr, host_sockaddr, host_len); + req_socklen = host_len; + XdmcpSetAuthentication (AuthenticationName); + send_packet(); +} + +/* + * !!! this routine should be replaced by a routine that adds + * the host to the user's host menu. the current version just + * selects the first host to respond with willing message. + */ + +/*ARGSUSED*/ +static void +XdmcpAddHost( + struct sockaddr *from, + int fromlen, + ARRAY8Ptr AuthenticationName, + ARRAY8Ptr hostname, + ARRAY8Ptr status) +{ + XdmcpSelectHost(from, fromlen, AuthenticationName); +} + +/* + * A message is queued on the socket; read it and + * do the appropriate thing + */ + +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 (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]); + + 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 ( + char *type, + ARRAY8Ptr status) +{ + FatalError ("XDMCP fatal error: %s %*.*s\n", type, + status->length, status->length, status->data); +} + +static void +XdmcpWarning(char *str) +{ + ErrorF("XDMCP warning: %s\n", str); +} + +static void +get_addr_by_name( + char * argtype, + char * namestr, + int port, + int socktype, + SOCKADDR_TYPE *addr, + SOCKLEN_TYPE *addrlen +#if defined(IPv6) && defined(AF_INET6) + , + struct addrinfo **aip, + struct addrinfo **aifirstp +#endif + ) +{ +#if defined(IPv6) && defined(AF_INET6) + struct addrinfo *ai; + struct addrinfo hints; + char portstr[6]; + char *pport = portstr; + int gaierr; + + bzero(&hints, sizeof(hints)); + hints.ai_socktype = socktype; + + if (port == 0) { + pport = NULL; + } else if (port > 0 && port < 65535) { + sprintf(portstr, "%d", port); + } else { + FatalError("Xserver: port out of range: %d\n", port); + } + + if (*aifirstp != NULL) { + freeaddrinfo(*aifirstp); + *aifirstp = NULL; + } + + if ((gaierr = getaddrinfo(namestr, pport, &hints, aifirstp)) == 0) { + for (ai = *aifirstp; ai != NULL; ai = ai->ai_next) { + if (ai->ai_family == AF_INET || ai->ai_family == AF_INET6) + break; + } + if ((ai == NULL) || (ai->ai_addrlen > sizeof(SOCKADDR_TYPE))) { + FatalError ("Xserver: %s host %s not on supported network type\n", + argtype, namestr); + } else { + *aip = ai; + *addrlen = ai->ai_addrlen; + memcpy(addr, ai->ai_addr, ai->ai_addrlen); + } + } else { + FatalError("Xserver: %s: %s %s\n", gai_strerror(gaierr), argtype, namestr); + } +#else + struct hostent *hep; +#ifdef XTHREADS_NEEDS_BYNAMEPARAMS + _Xgethostbynameparams hparams; +#endif +#if defined(WIN32) && (defined(TCPCONN) || defined(DNETCONN)) + _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(argc, argv, i) + int argc, i; + char **argv; +{ + char *address = XDM_DEFAULT_MCAST_ADDR6; + int hopcount = 1; + struct addrinfo hints; + char portstr[6]; + int gaierr; + struct addrinfo *ai, *firstai; + + if ((i < argc) && (argv[i][0] != '-') && (argv[i][0] != '+')) { + address = argv[i++]; + if ((i < argc) && (argv[i][0] != '-') && (argv[i][0] != '+')) { + hopcount = strtol(argv[i++], NULL, 10); + if ((hopcount < 1) || (hopcount > 255)) { + FatalError("Xserver: multicast hop count out of range: %d\n", + hopcount); + } + } + } + + if (xdm_udp_port > 0 && xdm_udp_port < 65535) { + sprintf(portstr, "%d", xdm_udp_port); + } else { + FatalError("Xserver: port out of range: %d\n", xdm_udp_port); + } + bzero(&hints, sizeof(hints)); + hints.ai_socktype = SOCK_DGRAM; + + if ((gaierr = getaddrinfo(address, portstr, &hints, &firstai)) == 0) { + for (ai = firstai; ai != NULL; ai = ai->ai_next) { + if (((ai->ai_family == AF_INET) && + IN_MULTICAST(((struct sockaddr_in *) ai->ai_addr) + ->sin_addr.s_addr)) + || ((ai->ai_family == AF_INET6) && + IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *) ai->ai_addr) + ->sin6_addr))) + break; + } + if (ai == NULL) { + FatalError ("Xserver: address not supported multicast type %s\n", + address); + } else { + struct multicastinfo *mcastinfo, *mcl; + + mcastinfo = malloc(sizeof(struct multicastinfo)); + mcastinfo->next = NULL; + mcastinfo->ai = firstai; + mcastinfo->hops = hopcount; + + if (mcastlist == NULL) { + mcastlist = mcastinfo; + } else { + for (mcl = mcastlist; mcl->next != NULL; mcl = mcl->next) { + /* Do nothing - just find end of list */ + } + mcl->next = mcastinfo; + } + } + } else { + FatalError("Xserver: %s: %s\n", gai_strerror(gaierr), address); + } + return i; +} +#endif + +#else +static int xdmcp_non_empty; /* avoid complaint by ranlib */ +#endif /* XDMCP */ diff --git a/xorg-server/os/xprintf.c b/xorg-server/os/xprintf.c new file mode 100644 index 000000000..07eaa1f58 --- /dev/null +++ b/xorg-server/os/xprintf.c @@ -0,0 +1,104 @@ +/* + * printf routines which xalloc their buffer + */ +/* + * Copyright (c) 2004 Alexander Gottwald + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include "os.h" +#include +#include + +#ifndef va_copy +# ifdef __va_copy +# define va_copy __va_copy +# else +# error "no working va_copy was found" +# endif +#endif + +char * +Xvprintf(const char *format, va_list va) +{ + char *ret; + int size; + va_list va2; + + va_copy(va2, va); + size = vsnprintf(NULL, 0, format, va2); + va_end(va2); + + ret = (char *)Xalloc(size + 1); + if (ret == NULL) + return NULL; + + vsnprintf(ret, size + 1, format, va); + ret[size] = 0; + return ret; +} + +char *Xprintf(const char *format, ...) +{ + char *ret; + va_list va; + va_start(va, format); + ret = Xvprintf(format, va); + va_end(va); + return ret; +} + +char * +XNFvprintf(const char *format, va_list va) +{ + char *ret; + int size; + va_list va2; + + va_copy(va2, va); + size = vsnprintf(NULL, 0, format, va2); + va_end(va2); + + ret = (char *)XNFalloc(size + 1); + if (ret == NULL) + return NULL; + + vsnprintf(ret, size + 1, format, va); + ret[size] = 0; + return ret; +} + +char *XNFprintf(const char *format, ...) +{ + char *ret; + va_list va; + va_start(va, format); + ret = XNFvprintf(format, va); + va_end(va); + return ret; +} diff --git a/xorg-server/os/xstrans.c b/xorg-server/os/xstrans.c new file mode 100644 index 000000000..c086e225b --- /dev/null +++ b/xorg-server/os/xstrans.c @@ -0,0 +1,8 @@ +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#define TRANS_REOPEN +#define TRANS_SERVER +#define XSERV_t +#include -- cgit v1.2.3