aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/os
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/os')
-rw-r--r--xorg-server/os/Makefile.am122
-rw-r--r--xorg-server/os/WaitFor.c6
-rw-r--r--xorg-server/os/access.c363
-rw-r--r--xorg-server/os/auth.c12
-rw-r--r--xorg-server/os/client.c618
-rw-r--r--xorg-server/os/connection.c2654
-rw-r--r--xorg-server/os/io.c1
-rw-r--r--xorg-server/os/log.c18
-rw-r--r--xorg-server/os/makefile49
-rw-r--r--xorg-server/os/oscolor.c4
-rw-r--r--xorg-server/os/osinit.c5
-rw-r--r--xorg-server/os/utils.c3682
-rw-r--r--xorg-server/os/xdmcp.c142
-rw-r--r--xorg-server/os/xprintf.c7
-rw-r--r--xorg-server/os/xstrans.c4
15 files changed, 4104 insertions, 3583 deletions
diff --git a/xorg-server/os/Makefile.am b/xorg-server/os/Makefile.am
index 91ca110f4..d06f06ff5 100644
--- a/xorg-server/os/Makefile.am
+++ b/xorg-server/os/Makefile.am
@@ -1,61 +1,61 @@
-noinst_LTLIBRARIES = libos.la
-
-AM_CFLAGS = $(DIX_CFLAGS) $(SHA1_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 \
- client.c \
- connection.c \
- io.c \
- mitauth.c \
- oscolor.c \
- osdep.h \
- osinit.c \
- utils.c \
- strcasecmp.c \
- strcasestr.c \
- xdmauth.c \
- xsha1.c \
- xstrans.c \
- xprintf.c \
- $(XORG_SRCS)
-libos_la_LIBADD = @SHA1_LIBS@ $(DLOPEN_LIBS)
-
-if SECURE_RPC
-libos_la_SOURCES += $(SECURERPC_SRCS)
-endif
-
-if XDMCP
-libos_la_SOURCES += $(XDMCP_SRCS)
-endif
-
-if NEED_STRLCAT
-libos_la_SOURCES += $(STRLCAT_SRCS)
-endif
-
-EXTRA_DIST = $(SECURERPC_SRCS) $(INTERNALMALLOC_SRCS) \
- $(XDMCP_SRCS) $(STRLCAT_SRCS)
-
-if SPECIAL_DTRACE_OBJECTS
-# Generate dtrace object code for probes in libos & libdix
-dtrace.o: $(top_srcdir)/dix/Xserver.d $(am_libos_la_OBJECTS)
- $(AM_V_GEN)$(DTRACE) -G -C -o $@ -s $(top_srcdir)/dix/Xserver.d .libs/*.o ../dix/.libs/*.o
-
-noinst_PROGRAMS = os.O
-
-os.O: dtrace.o $(am_libos_la_OBJECTS)
- $(AM_V_GEN)ld -r -o $@ dtrace.o .libs/*.o
-endif
-
-os.c:
- touch $@
-
-CLEANFILES = os.c
+noinst_LTLIBRARIES = libos.la
+
+AM_CFLAGS = $(DIX_CFLAGS) $(SHA1_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 \
+ client.c \
+ connection.c \
+ io.c \
+ mitauth.c \
+ oscolor.c \
+ osdep.h \
+ osinit.c \
+ utils.c \
+ strcasecmp.c \
+ strcasestr.c \
+ xdmauth.c \
+ xsha1.c \
+ xstrans.c \
+ xprintf.c \
+ $(XORG_SRCS)
+libos_la_LIBADD = @SHA1_LIBS@ $(DLOPEN_LIBS)
+
+if SECURE_RPC
+libos_la_SOURCES += $(SECURERPC_SRCS)
+endif
+
+if XDMCP
+libos_la_SOURCES += $(XDMCP_SRCS)
+endif
+
+if NEED_STRLCAT
+libos_la_SOURCES += $(STRLCAT_SRCS)
+endif
+
+EXTRA_DIST = $(SECURERPC_SRCS) $(INTERNALMALLOC_SRCS) \
+ $(XDMCP_SRCS) $(STRLCAT_SRCS)
+
+if SPECIAL_DTRACE_OBJECTS
+# Generate dtrace object code for probes in libos & libdix
+dtrace.o: $(top_srcdir)/dix/Xserver.d $(am_libos_la_OBJECTS)
+ $(AM_V_GEN)$(DTRACE) -G -C -o $@ -s $(top_srcdir)/dix/Xserver.d .libs/*.o ../dix/.libs/*.o
+
+noinst_PROGRAMS = os.O
+
+os.O: dtrace.o $(am_libos_la_OBJECTS)
+ $(AM_V_GEN)ld -r -o $@ dtrace.o .libs/*.o
+endif
+
+os.c:
+ touch $@
+
+CLEANFILES = os.c
diff --git a/xorg-server/os/WaitFor.c b/xorg-server/os/WaitFor.c
index 867cb04b8..ddfa14903 100644
--- a/xorg-server/os/WaitFor.c
+++ b/xorg-server/os/WaitFor.c
@@ -213,6 +213,12 @@ WaitForSomething(int *pClientsReady)
wt = &waittime;
}
}
+ if (!wt)
+ {
+ wt = &waittime;
+ waittime.tv_sec = 0;
+ waittime.tv_usec = 100;
+ }
XFD_COPYSET(&AllSockets, &LastSelectMask);
}
diff --git a/xorg-server/os/access.c b/xorg-server/os/access.c
index 7ba4274ce..fc7f8366b 100644
--- a/xorg-server/os/access.c
+++ b/xorg-server/os/access.c
@@ -223,6 +223,10 @@ static int AccessEnabled = DEFAULT_ACCESS_CONTROL;
static int LocalHostEnabled = FALSE;
static int LocalHostRequested = FALSE;
static int UsingXdmcp = FALSE;
+static u_long *pInterfaces = NULL;
+static int ActiveInterfaces = 0;
+
+void match_interface(u_long u_lQuery);
/* FamilyServerInterpreted implementation */
static Bool siAddrMatch(int family, pointer addr, int len, HOST *host,
@@ -230,6 +234,84 @@ static Bool siAddrMatch(int family, pointer addr, int len, HOST *host,
static int siCheckAddr(const char *addrString, int length);
static void siTypesInitialize(void);
+#if NTDDI_VERSION < NTDDI_VISTA
+const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt)
+{
+ if (af == AF_INET)
+ {
+ struct sockaddr_in in;
+ memset(&in, 0, sizeof(in));
+ in.sin_family = AF_INET;
+ memcpy(&in.sin_addr, src, sizeof(struct in_addr));
+ if (getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in), dst, cnt, NULL, 0, NI_NUMERICHOST) != 0)
+ {
+ errno = WSAGetLastError();
+ return NULL;
+ }
+ else return dst;
+ }
+ else if (af == AF_INET6)
+ {
+ struct sockaddr_in6 in;
+ memset(&in, 0, sizeof(in));
+ in.sin6_family = AF_INET6;
+ memcpy(&in.sin6_addr, src, sizeof(struct in_addr6));
+ if (getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in6), dst, cnt, NULL, 0, NI_NUMERICHOST) != 0)
+ {
+ errno = WSAGetLastError();
+ return NULL;
+ }
+ else return dst;
+ }
+ errno = WSAEAFNOSUPPORT;
+ return NULL;
+}
+
+int inet_pton(int af, const char *src, void *dst)
+{
+ struct sockaddr_storage ss;
+ int sslen = sizeof(ss);
+ if (af == AF_INET)
+ {
+ struct in_addr out;
+ char buffer[INET_ADDRSTRLEN + 1];
+ strncpy (buffer, src, INET_ADDRSTRLEN);
+ buffer [INET_ADDRSTRLEN] = '\0';
+ if (WSAStringToAddressA(buffer, AF_INET, NULL, (struct sockaddr*)&ss, &sslen) == SOCKET_ERROR)
+ {
+ errno = WSAGetLastError();
+ return 0;
+ }
+ else
+ {
+ out = ((struct sockaddr_in *)&ss)->sin_addr;
+ memcpy (dst, &out, sizeof(struct in_addr));
+ return 1;
+ }
+ }
+ else if (af == AF_INET6)
+ {
+ struct in6_addr out6;
+ char buffer6[INET6_ADDRSTRLEN + 1];
+ strncpy (buffer6, src, INET6_ADDRSTRLEN);
+ buffer6 [INET6_ADDRSTRLEN] = '\0';
+ if (WSAStringToAddressA(buffer6, AF_INET6, NULL, (struct sockaddr*)&ss, &sslen) == SOCKET_ERROR)
+ {
+ errno = WSAGetLastError();
+ return 0;
+ }
+ else
+ {
+ out6 = ((struct sockaddr_in6 *)&ss)->sin6_addr;
+ memcpy (dst, &out6, sizeof(struct in6_addr));
+ return 1;
+ }
+ }
+ errno = WSAEAFNOSUPPORT;
+ return -1;
+}
+#endif
+
/*
* called when authorization is not enabled to add the
* local host to the access list
@@ -309,7 +391,7 @@ ifioctl (int fd, int cmd, char *arg)
#endif
/*
- * DefineSelf (fd):
+ * DefineSelf (fd, protocol):
*
* Define this host for access control. Find all the hosts the OS knows about
* for this fd and add them to the selfhosts list.
@@ -317,12 +399,11 @@ ifioctl (int fd, int cmd, char *arg)
#if !defined(SIOCGIFCONF)
void
-DefineSelf (int fd)
+DefineSelf (int fd, const int protocol)
{
#if !defined(TCPCONN) && !defined(STREAMSCONN) && !defined(UNIXCONN)
return;
#else
- register int n;
int len;
caddr_t addr;
int family;
@@ -334,6 +415,10 @@ DefineSelf (int fd)
struct {
char nodename[512];
} name;
+ HOST ha;
+ struct addrinfo *addresses;
+ struct addrinfo *a;
+ struct addrinfo hints;
#endif
register struct hostent *hp;
@@ -352,7 +437,6 @@ DefineSelf (int fd)
#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
@@ -364,80 +448,166 @@ DefineSelf (int fd)
gethostname(name.nodename, sizeof(name.nodename));
#endif
+ /* Colin's experiments with using getaddrinfo() instead of the IPv6-useless gethostbyname() */
+ memset( &hints, 0, sizeof(hints) );
+ if (protocol == 4) hints.ai_family = AF_INET;
+ else if (protocol == 6) hints.ai_family = AF_INET6;
+
+ if (getaddrinfo(name.nodename, NULL, &hints, &addresses) != 0) goto CarryOnTheOldWay;
+
+ if (protocol == 6) ErrorF ("DefineSelf - %s has IPv%d addresses...\n",
+ name.nodename, protocol);
+
+ for (a = addresses; a != NULL; a = a->ai_next) {
+ char ad[INET6_ADDRSTRLEN];
+ ha.family = a->ai_family;
+ if (a->ai_family == AF_INET6) {
+ ha.addr = (unsigned char *)
+ &((struct sockaddr_in6 *) a->ai_addr)->sin6_addr;
+ ha.len =
+ sizeof (((struct sockaddr_in6 *) a->ai_addr)->sin6_addr);
+ } else {
+ ha.addr = (unsigned char *)
+ &((struct sockaddr_in *) a->ai_addr)->sin_addr;
+ ha.len =
+ sizeof (((struct sockaddr_in *) a->ai_addr)->sin_addr);
+ }
+ inet_ntop(ha.family, ha.addr, ad, sizeof(ad));
+
+ if (ha.family == AF_INET6) {
+ ErrorF(" %s", ad);
+ saddr.sa.sa_family = AF_INET6;
+ inet6addr = (struct sockaddr_in6 *) (&(saddr.sa));
+ acopy (ha.addr, &(inet6addr->sin6_addr), ha.len);
+ len = sizeof(saddr.in6);
+ 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;
+ }
+ if (family == FamilyInternet6 &&
+ !(IN6_IS_ADDR_LOOPBACK((struct in6_addr *)addr))) {
+ XdmcpRegisterConnection (family, (char *)addr, len);
+ }
+ }
+ }
+ }
+ }
+ if (protocol == 6) ErrorF ("\n");
+ freeaddrinfo(addresses);
+ /* End of Colin's experiments */
+
+CarryOnTheOldWay:
+
hp = _XGethostbyname(name.nodename, hparams);
if (hp != NULL)
{
+ int i = 0, j = 0;
+ IN_ADDR Inter;
saddr.sa.sa_family = hp->h_addrtype;
switch (hp->h_addrtype) {
case AF_INET:
+ if (protocol == 6) return; /* We should not be here: gethostbyname() is useless with inet6! */
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)
+ if (!pInterfaces) match_interface(0);
+ if (ActiveInterfaces && pInterfaces && *pInterfaces)
{
- /* add this host to the host list. */
- MakeHost(host,len)
- if (host)
+ ErrorF ("DefineSelf - %s has %d usable IPv%d interface%s...\n address%s",
+ name.nodename, ActiveInterfaces, protocol,
+ ActiveInterfaces==1 ? "" : "s",
+ ActiveInterfaces==1 ? "" : "es");
+ for (i = 0; hp->h_addr_list[i]; i++)
{
- host->family = family;
- host->len = len;
- acopy ( addr, host->addr, len);
- host->next = selfhosts;
- selfhosts = host;
+ Inter.S_un.S_addr = *(u_long *)hp->h_addr_list[i];
+ ErrorF(" %s", inet_ntoa(Inter));
+ if (*pInterfaces == *(u_long *)hp->h_addr_list[i]) j = i;
}
-#ifdef XDMCP
- /*
- * If this is an Internet Address, but not the localhost
- * address (127.0.0.1), nor the bogus address (0.0.0.0),
- * register it.
- */
- if (family == FamilyInternet &&
- !(len == 4 &&
- ((addr[0] == 127) ||
- (addr[0] == 0 && addr[1] == 0 &&
- addr[2] == 0 && addr[3] == 0)))
- )
+ ErrorF ("\n");
+ }
+ break;
+#if 0 /* We never used to get here and AF_INET6 is now processed by getaddrinfo() */
+ case AF_INET6:
+ inet6addr = (struct sockaddr_in6 *) (&(saddr.sa));
+ acopy ( hp_addr, &(inet6addr->sin6_addr), hp->h_length);
+ len = sizeof(saddr.in6);
+ break;
+#endif
+ default:
+ goto DefineLocalHost;
+ }
+
+ for (i = -1; i < 0 || hp->h_addr_list[i]; i++)
+ {
+ if (i < 0) acopy ( hp->h_addr_list[j], &(inetaddr->sin_addr), hp->h_length);
+ else if (i == j) continue;
+ else acopy ( hp->h_addr_list[i], &(inetaddr->sin_addr), hp->h_length);
+ len = sizeof(saddr.sa);
+ 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)
{
- XdmcpRegisterConnection (family, (char *)addr, len);
- broad_addr = *inetaddr;
- ((struct sockaddr_in *) &broad_addr)->sin_addr.s_addr =
+ /* add this host to the host list. */
+ MakeHost(host,len)
+ if (host)
+ {
+ host->family = family;
+ host->len = len;
+ acopy ( addr, host->addr, len);
+ host->next = selfhosts;
+ selfhosts = host;
+ }
+ #ifdef XDMCP
+ /*
+ * If this is an Internet Address, but not the localhost
+ * address (127.0.0.1), nor the bogus address (0.0.0.0),
+ * register it.
+ */
+ if (family == FamilyInternet &&
+ !(len == 4 &&
+ ((addr[0] == 127) ||
+ (addr[0] == 0 && addr[1] == 0 &&
+ addr[2] == 0 && addr[3] == 0)))
+ )
+ {
+ XdmcpRegisterConnection (family, (char *)addr, len);
+ broad_addr = *inetaddr;
+ ((struct sockaddr_in *) &broad_addr)->sin_addr.s_addr =
htonl (INADDR_BROADCAST);
- XdmcpRegisterBroadcastAddress ((struct sockaddr_in *)
+ 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 */
}
-#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:
+ free(pInterfaces);
for (host = selfhosts;
host && !addrEqual(FamilyLocalHost, "", 0, host);
host = host->next);
@@ -874,18 +1044,19 @@ ResetHosts (char *display)
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);
+#ifdef __MINGW32__
+ snprintf(fname, sizeof(fname), "%s%s" ETC_HOST_SUFFIX, getenv("XHOSTPREFIX"),
+ display);
+#else
snprintf(fname, sizeof(fname), ETC_HOST_PREFIX "%s" ETC_HOST_SUFFIX,
display);
+#endif
if ((fd = fopen (fname, "r")) != 0)
{
@@ -959,9 +1130,13 @@ ResetHosts (char *display)
{
struct addrinfo *addresses;
struct addrinfo *a;
+ struct addrinfo hints;
int f;
- if (getaddrinfo(hostname, NULL, NULL, &addresses) == 0) {
+ memset( &hints, 0, sizeof(hints) );
+ if (family == FamilyInternet) hints.ai_family = AF_INET;
+ else if (family == FamilyInternet6) hints.ai_family = AF_INET6;
+ if (getaddrinfo(hostname, NULL, &hints, &addresses) == 0) {
for (a = addresses ; a != NULL ; a = a->ai_next) {
len = a->ai_addrlen;
f = ConvertAddr(a->ai_addr,&len,(pointer *)&addr);
@@ -1288,6 +1463,8 @@ NewHost (int family,
{
register HOST *host;
+ if (family == FamilyLocal) return TRUE; /* No FamilyLocal in Vcxsrv */
+
for (host = validhosts; host; host = host->next)
{
if (addrEqual (family, addr, len, host))
@@ -1750,6 +1927,7 @@ siHostnameAddrMatch(int family, pointer addr, int len,
char hostname[SI_HOSTNAME_MAXLEN];
struct addrinfo *addresses;
struct addrinfo *a;
+ struct addrinfo hints;
int f, hostaddrlen;
pointer hostaddr;
@@ -1759,7 +1937,10 @@ siHostnameAddrMatch(int family, pointer addr, int len,
strncpy(hostname, siAddr, siAddrLen);
hostname[siAddrLen] = '\0';
- if (getaddrinfo(hostname, NULL, NULL, &addresses) == 0) {
+ memset( &hints, 0, sizeof(hints) );
+ if (family == FamilyInternet) hints.ai_family = AF_INET;
+ else if (family == FamilyInternet6) hints.ai_family = AF_INET6;
+ if (getaddrinfo(hostname, NULL, &hints, &addresses) == 0) {
for (a = addresses ; a != NULL ; a = a->ai_next) {
hostaddrlen = a->ai_addrlen;
f = ConvertAddr(a->ai_addr,&hostaddrlen,&hostaddr);
@@ -1792,7 +1973,7 @@ siHostnameAddrMatch(int family, pointer addr, int len,
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++)
+ for (addrlist = (const char **)hp->h_addr_list; *addrlist; addrlist++)
#else
addrlist = &hp->h_addr;
#endif
@@ -2074,3 +2255,55 @@ siTypesInitialize(void)
&siLocalGroupPriv);
#endif
}
+
+void match_interface(u_long u_lQuery)
+{
+ WSADATA w;
+ SOCKET sd;
+ INTERFACE_INFO InterfaceList[25];
+ PSOCKADDR_IN pAddress, pNetmask;
+ u_long nBytesReturned, tempAddress;
+ u_long u_lAddress, u_lNetmask, u_lFlags;
+ int nNumInterfaces, i, j = 0;
+
+ if (WSAStartup(MAKEWORD(2,2), &w) != 0)
+ return;
+
+ sd = WSASocket(AF_INET, SOCK_DGRAM, 0, 0, 0, 0);
+ if (sd == INVALID_SOCKET)
+ {
+ WSACleanup();
+ return;
+ }
+
+ if (WSAIoctl(sd, SIO_GET_INTERFACE_LIST, 0, 0, &InterfaceList, sizeof(InterfaceList), &nBytesReturned, 0, 0) == SOCKET_ERROR)
+ {
+ closesocket(sd);
+ WSACleanup();
+ return;
+ }
+
+ nNumInterfaces = (int)(nBytesReturned/sizeof(INTERFACE_INFO));
+ pInterfaces = malloc(25*sizeof(u_long));
+ for (i = 0; i < nNumInterfaces; ++i)
+ {
+ pAddress = &InterfaceList[i].iiAddress.AddressIn;
+ u_lAddress = pAddress->sin_addr.S_un.S_addr;
+
+ pNetmask = &InterfaceList[i].iiNetmask.AddressIn;
+ u_lNetmask = pNetmask->sin_addr.S_un.S_addr;
+
+ u_lFlags = InterfaceList[i].iiFlags;
+ if ((u_lFlags & IFF_UP) && !(u_lFlags & IFF_LOOPBACK))
+ {
+ if ((u_lAddress & u_lNetmask) == (u_lQuery & u_lNetmask)) j = i;
+ *(pInterfaces + ActiveInterfaces) = u_lAddress;
+ ActiveInterfaces++;
+ }
+ }
+ tempAddress = *pInterfaces;
+ *pInterfaces = *(pInterfaces + j);
+ *(pInterfaces + j) = tempAddress;
+ closesocket(sd);
+ WSACleanup();
+}
diff --git a/xorg-server/os/auth.c b/xorg-server/os/auth.c
index 52868f0ba..f80e53155 100644
--- a/xorg-server/os/auth.c
+++ b/xorg-server/os/auth.c
@@ -318,11 +318,23 @@ GenerateAuthorization(
void
GenerateRandomData (int len, char *buf)
{
+#ifdef _MSC_VER
+ static HANDLE hAdvApi32;
+ static BOOLEAN (_stdcall * RtlGenRandom)(void *,unsigned long);
+
+ if (!hAdvApi32)
+ {
+ hAdvApi32=LoadLibrary("advapi32.dll");
+ RtlGenRandom=(BOOLEAN (_stdcall *)(void*,unsigned long))GetProcAddress(hAdvApi32,"SystemFunction036");
+ }
+ RtlGenRandom(buf, len);
+#else
int fd;
fd = open("/dev/urandom", O_RDONLY);
read(fd, buf, len);
close(fd);
+#endif
}
#endif /* XCSECURITY */
diff --git a/xorg-server/os/client.c b/xorg-server/os/client.c
index b5349778b..c7c59d69f 100644
--- a/xorg-server/os/client.c
+++ b/xorg-server/os/client.c
@@ -1,309 +1,309 @@
-/*
- * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All
- * rights reserved.
- * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-/**
- * @file
- *
- * This file contains functionality for identifying clients by various
- * means. The primary purpose of identification is to simply aid in
- * finding out which clients are using X server and how they are using
- * it. For example, it's often necessary to monitor what requests
- * clients are executing (to spot bad behaviour) and how they are
- * allocating resources in X server (to spot excessive resource
- * usage).
- *
- * This framework automatically allocates information, that can be
- * used for client identification, when a client connects to the
- * server. The information is freed when the client disconnects. The
- * allocated information is just a collection of various IDs, such as
- * PID and process name for local clients, that are likely to be
- * useful in analyzing X server usage.
- *
- * Users of the framework can query ID information about clients at
- * any time. To avoid repeated polling of IDs the users can also
- * subscribe for notifications about the availability of ID
- * information. IDs have been allocated before ClientStateCallback is
- * called with ClientStateInitial state. Similarly the IDs will be
- * released after ClientStateCallback is called with ClientStateGone
- * state.
- *
- * Author: Rami Ylimäki <rami.ylimaki@vincit.fi>
- */
-
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include "client.h"
-#include "os.h"
-#include "dixstruct.h"
-
-/**
- * Try to determine a PID for a client from its connection
- * information. This should be called only once when new client has
- * connected, use GetClientPid to determine the PID at other times.
- *
- * @param[in] client Connection linked to some process.
- *
- * @return PID of the client. Error (-1) if PID can't be determined
- * for the client.
- *
- * @see GetClientPid
- */
-pid_t DetermineClientPid(struct _Client *client)
-{
- LocalClientCredRec *lcc = NULL;
- pid_t pid = -1;
-
- if (client == NullClient)
- return pid;
-
- if (client == serverClient)
- return getpid();
-
- if (GetLocalClientCreds(client, &lcc) != -1)
- {
- if (lcc->fieldsSet & LCC_PID_SET)
- pid = lcc->pid;
- FreeLocalClientCreds(lcc);
- }
-
- return pid;
-}
-
-/**
- * Try to determine a command line string for a client based on its
- * PID. Note that mapping PID to a command hasn't been implemented for
- * some operating systems. This should be called only once when a new
- * client has connected, use GetClientCmdName/Args to determine the
- * string at other times.
- *
- * @param[in] pid Process ID of a client.
-
- * @param[out] cmdname Client process name without arguments. You must
- * release this by calling free. On error NULL is
- * returned. Pass NULL if you aren't interested in
- * this value.
- * @param[out] cmdargs Arguments to client process. Useful for
- * identifying a client that is executed from a
- * launcher program. You must release this by
- * calling free. On error NULL is returned. Pass
- * NULL if you aren't interested in this value.
- *
- * @see GetClientCmdName/Args
- */
-void DetermineClientCmd(pid_t pid, const char **cmdname, const char **cmdargs)
-{
- char path[PATH_MAX + 1];
- int totsize = 0;
- int cmdsize = 0;
- int argsize = 0;
- int fd = 0;
-
- if (cmdname)
- *cmdname = NULL;
- if (cmdargs)
- *cmdargs = NULL;
-
- if (pid == -1)
- return;
-
- /* Check if /proc/pid/cmdline exists. It's not supported on all
- * operating systems. */
- if (snprintf(path, sizeof(path), "/proc/%d/cmdline", pid) < 0)
- return;
- fd = open(path, O_RDONLY);
- if (fd < 0)
- return;
-
- /* Read the contents of /proc/pid/cmdline. It should contain the
- * process name and arguments. */
- totsize = read(fd, path, sizeof(path));
- close(fd);
- if (totsize <= 0)
- return;
- path[totsize - 1] = '\0';
-
- /* Contruct the process name without arguments. */
- cmdsize = strlen(path) + 1;
- if (cmdname)
- {
- char *name = malloc(cmdsize);
- if (name)
- {
- strncpy(name, path, cmdsize);
- name[cmdsize - 1] = '\0';
- *cmdname = name;
- }
- }
-
- /* Construct the arguments for client process. */
- argsize = totsize - cmdsize;
- if (cmdargs && (argsize > 0))
- {
- char *args = malloc(argsize);
- if (args)
- {
- int i = 0;
- for (i = 0; i < (argsize - 1); ++i)
- {
- const char c = path[cmdsize + i];
- args[i] = (c == '\0') ? ' ' : c;
- }
- args[argsize - 1] = '\0';
- *cmdargs = args;
- }
- }
-}
-
-/**
- * Called when a new client connects. Allocates client ID information.
- *
- * @param[in] client Recently connected client.
- */
-void ReserveClientIds(struct _Client *client)
-{
-#ifdef CLIENTIDS
- if (client == NullClient)
- return;
-
- assert(!client->clientIds);
- client->clientIds = calloc(1, sizeof(ClientIdRec));
- if (!client->clientIds)
- return;
-
- client->clientIds->pid = DetermineClientPid(client);
- if (client->clientIds->pid != -1)
- DetermineClientCmd(client->clientIds->pid, &client->clientIds->cmdname, &client->clientIds->cmdargs);
-
- DebugF("client(%lx): Reserved pid(%d).\n",
- client->clientAsMask, client->clientIds->pid);
- DebugF("client(%lx): Reserved cmdname(%s) and cmdargs(%s).\n",
- client->clientAsMask,
- client->clientIds->cmdname ? client->clientIds->cmdname : "NULL",
- client->clientIds->cmdargs ? client->clientIds->cmdargs : "NULL");
-#endif /* CLIENTIDS */
-}
-
-/**
- * Called when an existing client disconnects. Frees client ID
- * information.
- *
- * @param[in] client Recently disconnected client.
- */
-void ReleaseClientIds(struct _Client *client)
-{
-#ifdef CLIENTIDS
- if (client == NullClient)
- return;
-
- if (!client->clientIds)
- return;
-
- DebugF("client(%lx): Released pid(%d).\n",
- client->clientAsMask, client->clientIds->pid);
- DebugF("client(%lx): Released cmdline(%s) and cmdargs(%s).\n",
- client->clientAsMask,
- client->clientIds->cmdname ? client->clientIds->cmdname : "NULL",
- client->clientIds->cmdargs ? client->clientIds->cmdargs : "NULL");
-
- free((void *) client->clientIds->cmdname); /* const char * */
- free((void *) client->clientIds->cmdargs); /* const char * */
- free(client->clientIds);
- client->clientIds = NULL;
-#endif /* CLIENTIDS */
-}
-
-/**
- * Get cached PID of a client.
- *
- * param[in] client Client whose PID has been already cached.
- *
- * @return Cached client PID. Error (-1) if called:
- * - before ClientStateInitial client state notification
- * - after ClientStateGone client state notification
- * - for remote clients
- *
- * @see DetermineClientPid
- */
-pid_t GetClientPid(struct _Client *client)
-{
- if (client == NullClient)
- return -1;
-
- if (!client->clientIds)
- return -1;
-
- return client->clientIds->pid;
-}
-
-/**
- * Get cached command name string of a client.
- *
- * param[in] client Client whose command line string has been already
- * cached.
- *
- * @return Cached client command name. Error (NULL) if called:
- * - before ClientStateInitial client state notification
- * - after ClientStateGone client state notification
- * - for remote clients
- * - on OS that doesn't support mapping of PID to command line
- *
- * @see DetermineClientCmd
- */
-const char *GetClientCmdName(struct _Client *client)
-{
- if (client == NullClient)
- return NULL;
-
- if (!client->clientIds)
- return NULL;
-
- return client->clientIds->cmdname;
-}
-
-/**
- * Get cached command arguments string of a client.
- *
- * param[in] client Client whose command line string has been already
- * cached.
- *
- * @return Cached client command arguments. Error (NULL) if called:
- * - before ClientStateInitial client state notification
- * - after ClientStateGone client state notification
- * - for remote clients
- * - on OS that doesn't support mapping of PID to command line
- *
- * @see DetermineClientCmd
- */
-const char *GetClientCmdArgs(struct _Client *client)
-{
- if (client == NullClient)
- return NULL;
-
- if (!client->clientIds)
- return NULL;
-
- return client->clientIds->cmdargs;
-}
+/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All
+ * rights reserved.
+ * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/**
+ * @file
+ *
+ * This file contains functionality for identifying clients by various
+ * means. The primary purpose of identification is to simply aid in
+ * finding out which clients are using X server and how they are using
+ * it. For example, it's often necessary to monitor what requests
+ * clients are executing (to spot bad behaviour) and how they are
+ * allocating resources in X server (to spot excessive resource
+ * usage).
+ *
+ * This framework automatically allocates information, that can be
+ * used for client identification, when a client connects to the
+ * server. The information is freed when the client disconnects. The
+ * allocated information is just a collection of various IDs, such as
+ * PID and process name for local clients, that are likely to be
+ * useful in analyzing X server usage.
+ *
+ * Users of the framework can query ID information about clients at
+ * any time. To avoid repeated polling of IDs the users can also
+ * subscribe for notifications about the availability of ID
+ * information. IDs have been allocated before ClientStateCallback is
+ * called with ClientStateInitial state. Similarly the IDs will be
+ * released after ClientStateCallback is called with ClientStateGone
+ * state.
+ *
+ * Author: Rami Ylimäki <rami.ylimaki@vincit.fi>
+ */
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "client.h"
+#include "os.h"
+#include "dixstruct.h"
+
+/**
+ * Try to determine a PID for a client from its connection
+ * information. This should be called only once when new client has
+ * connected, use GetClientPid to determine the PID at other times.
+ *
+ * @param[in] client Connection linked to some process.
+ *
+ * @return PID of the client. Error (-1) if PID can't be determined
+ * for the client.
+ *
+ * @see GetClientPid
+ */
+pid_t DetermineClientPid(struct _Client *client)
+{
+ LocalClientCredRec *lcc = NULL;
+ pid_t pid = -1;
+
+ if (client == NullClient)
+ return pid;
+
+ if (client == serverClient)
+ return getpid();
+
+ if (GetLocalClientCreds(client, &lcc) != -1)
+ {
+ if (lcc->fieldsSet & LCC_PID_SET)
+ pid = lcc->pid;
+ FreeLocalClientCreds(lcc);
+ }
+
+ return pid;
+}
+
+/**
+ * Try to determine a command line string for a client based on its
+ * PID. Note that mapping PID to a command hasn't been implemented for
+ * some operating systems. This should be called only once when a new
+ * client has connected, use GetClientCmdName/Args to determine the
+ * string at other times.
+ *
+ * @param[in] pid Process ID of a client.
+
+ * @param[out] cmdname Client process name without arguments. You must
+ * release this by calling free. On error NULL is
+ * returned. Pass NULL if you aren't interested in
+ * this value.
+ * @param[out] cmdargs Arguments to client process. Useful for
+ * identifying a client that is executed from a
+ * launcher program. You must release this by
+ * calling free. On error NULL is returned. Pass
+ * NULL if you aren't interested in this value.
+ *
+ * @see GetClientCmdName/Args
+ */
+void DetermineClientCmd(pid_t pid, const char **cmdname, const char **cmdargs)
+{
+ char path[PATH_MAX + 1];
+ int totsize = 0;
+ int cmdsize = 0;
+ int argsize = 0;
+ int fd = 0;
+
+ if (cmdname)
+ *cmdname = NULL;
+ if (cmdargs)
+ *cmdargs = NULL;
+
+ if (pid == -1)
+ return;
+
+ /* Check if /proc/pid/cmdline exists. It's not supported on all
+ * operating systems. */
+ if (snprintf(path, sizeof(path), "/proc/%d/cmdline", pid) < 0)
+ return;
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ return;
+
+ /* Read the contents of /proc/pid/cmdline. It should contain the
+ * process name and arguments. */
+ totsize = read(fd, path, sizeof(path));
+ close(fd);
+ if (totsize <= 0)
+ return;
+ path[totsize - 1] = '\0';
+
+ /* Contruct the process name without arguments. */
+ cmdsize = strlen(path) + 1;
+ if (cmdname)
+ {
+ char *name = malloc(cmdsize);
+ if (name)
+ {
+ strncpy(name, path, cmdsize);
+ name[cmdsize - 1] = '\0';
+ *cmdname = name;
+ }
+ }
+
+ /* Construct the arguments for client process. */
+ argsize = totsize - cmdsize;
+ if (cmdargs && (argsize > 0))
+ {
+ char *args = malloc(argsize);
+ if (args)
+ {
+ int i = 0;
+ for (i = 0; i < (argsize - 1); ++i)
+ {
+ const char c = path[cmdsize + i];
+ args[i] = (c == '\0') ? ' ' : c;
+ }
+ args[argsize - 1] = '\0';
+ *cmdargs = args;
+ }
+ }
+}
+
+/**
+ * Called when a new client connects. Allocates client ID information.
+ *
+ * @param[in] client Recently connected client.
+ */
+void ReserveClientIds(struct _Client *client)
+{
+#ifdef CLIENTIDS
+ if (client == NullClient)
+ return;
+
+ assert(!client->clientIds);
+ client->clientIds = calloc(1, sizeof(ClientIdRec));
+ if (!client->clientIds)
+ return;
+
+ client->clientIds->pid = DetermineClientPid(client);
+ if (client->clientIds->pid != -1)
+ DetermineClientCmd(client->clientIds->pid, &client->clientIds->cmdname, &client->clientIds->cmdargs);
+
+ DebugF("client(%lx): Reserved pid(%d).\n",
+ client->clientAsMask, client->clientIds->pid);
+ DebugF("client(%lx): Reserved cmdname(%s) and cmdargs(%s).\n",
+ client->clientAsMask,
+ client->clientIds->cmdname ? client->clientIds->cmdname : "NULL",
+ client->clientIds->cmdargs ? client->clientIds->cmdargs : "NULL");
+#endif /* CLIENTIDS */
+}
+
+/**
+ * Called when an existing client disconnects. Frees client ID
+ * information.
+ *
+ * @param[in] client Recently disconnected client.
+ */
+void ReleaseClientIds(struct _Client *client)
+{
+#ifdef CLIENTIDS
+ if (client == NullClient)
+ return;
+
+ if (!client->clientIds)
+ return;
+
+ DebugF("client(%lx): Released pid(%d).\n",
+ client->clientAsMask, client->clientIds->pid);
+ DebugF("client(%lx): Released cmdline(%s) and cmdargs(%s).\n",
+ client->clientAsMask,
+ client->clientIds->cmdname ? client->clientIds->cmdname : "NULL",
+ client->clientIds->cmdargs ? client->clientIds->cmdargs : "NULL");
+
+ free((void *) client->clientIds->cmdname); /* const char * */
+ free((void *) client->clientIds->cmdargs); /* const char * */
+ free(client->clientIds);
+ client->clientIds = NULL;
+#endif /* CLIENTIDS */
+}
+
+/**
+ * Get cached PID of a client.
+ *
+ * param[in] client Client whose PID has been already cached.
+ *
+ * @return Cached client PID. Error (-1) if called:
+ * - before ClientStateInitial client state notification
+ * - after ClientStateGone client state notification
+ * - for remote clients
+ *
+ * @see DetermineClientPid
+ */
+pid_t GetClientPid(struct _Client *client)
+{
+ if (client == NullClient)
+ return -1;
+
+ if (!client->clientIds)
+ return -1;
+
+ return client->clientIds->pid;
+}
+
+/**
+ * Get cached command name string of a client.
+ *
+ * param[in] client Client whose command line string has been already
+ * cached.
+ *
+ * @return Cached client command name. Error (NULL) if called:
+ * - before ClientStateInitial client state notification
+ * - after ClientStateGone client state notification
+ * - for remote clients
+ * - on OS that doesn't support mapping of PID to command line
+ *
+ * @see DetermineClientCmd
+ */
+const char *GetClientCmdName(struct _Client *client)
+{
+ if (client == NullClient)
+ return NULL;
+
+ if (!client->clientIds)
+ return NULL;
+
+ return client->clientIds->cmdname;
+}
+
+/**
+ * Get cached command arguments string of a client.
+ *
+ * param[in] client Client whose command line string has been already
+ * cached.
+ *
+ * @return Cached client command arguments. Error (NULL) if called:
+ * - before ClientStateInitial client state notification
+ * - after ClientStateGone client state notification
+ * - for remote clients
+ * - on OS that doesn't support mapping of PID to command line
+ *
+ * @see DetermineClientCmd
+ */
+const char *GetClientCmdArgs(struct _Client *client)
+{
+ if (client == NullClient)
+ return NULL;
+
+ if (!client->clientIds)
+ return NULL;
+
+ return client->clientIds->cmdargs;
+}
diff --git a/xorg-server/os/connection.c b/xorg-server/os/connection.c
index 0c580ab5e..6e6f9fc33 100644
--- a/xorg-server/os/connection.c
+++ b/xorg-server/os/connection.c
@@ -1,1307 +1,1347 @@
-/***********************************************************
-
-Copyright 1987, 1989, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-
-Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
-
- All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-******************************************************************/
-/*****************************************************************
- * Stuff to create connections --- OS dependent
- *
- * EstablishNewConnections, CreateWellKnownSockets, ResetWellKnownSockets,
- * CloseDownConnection, CheckConnections, AddEnabledDevice,
- * RemoveEnabledDevice, OnlyListToOneClient,
- * ListenToAllClients,
- *
- * (WaitForSomething is in its own file)
- *
- * In this implementation, a client socket table is not kept.
- * Instead, what would be the index into the table is just the
- * file descriptor of the socket. This won't work for if the
- * socket ids aren't small nums (0 - 2^8)
- *
- *****************************************************************/
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#ifdef WIN32
-#include <X11/Xwinsock.h>
-#endif
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#define XSERV_t
-#define TRANS_SERVER
-#define TRANS_REOPEN
-#include <X11/Xtrans/Xtrans.h>
-#include <X11/Xtrans/Xtransint.h>
-#include <errno.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#ifndef WIN32
-#include <sys/socket.h>
-
-
-
-#if defined(TCPCONN) || defined(STREAMSCONN)
-# include <netinet/in.h>
-# include <arpa/inet.h>
-# ifdef apollo
-# ifndef NO_TCP_H
-# include <netinet/tcp.h>
-# endif
-# else
-# ifdef CSRG_BASED
-# include <sys/param.h>
-# endif
-# include <netinet/tcp.h>
-# endif
-# include <arpa/inet.h>
-#endif
-
-#include <sys/uio.h>
-
-#endif /* WIN32 */
-#include "misc.h" /* for typedef of pointer */
-#include "osdep.h"
-#include <X11/Xpoll.h>
-#include "opaque.h"
-#include "dixstruct.h"
-#include "xace.h"
-
-#define Pid_t pid_t
-
-
-#ifdef HAS_GETPEERUCRED
-# include <ucred.h>
-# include <zone.h>
-#endif
-
-#ifdef XSERVER_DTRACE
-# include <sys/types.h>
-typedef const char *string;
-# ifndef HAS_GETPEERUCRED
-# define zoneid_t int
-# endif
-# include "../dix/Xserver-dtrace.h"
-#endif
-
-static int lastfdesc; /* maximum file descriptor */
-
-fd_set WellKnownConnections; /* Listener mask */
-fd_set EnabledDevices; /* mask for input devices that are on */
-fd_set AllSockets; /* select on this */
-fd_set AllClients; /* available clients */
-fd_set LastSelectMask; /* mask returned from last select call */
-fd_set ClientsWithInput; /* clients with FULL requests in buffer */
-fd_set ClientsWriteBlocked; /* clients who cannot receive output */
-fd_set OutputPending; /* clients with reply/event data ready to go */
-int MaxClients = 0;
-Bool NewOutputPending; /* not yet attempted to write some new output */
-Bool AnyClientsWriteBlocked; /* true if some client blocked on write */
-
-static Bool RunFromSmartParent; /* send SIGUSR1 to parent process */
-Bool RunFromSigStopParent; /* send SIGSTOP to our own process; Upstart (or
- equivalent) will send SIGCONT back. */
-Bool PartialNetwork; /* continue even if unable to bind all addrs */
-static Pid_t ParentProcess;
-
-static Bool debug_conns = FALSE;
-
-fd_set IgnoredClientsWithInput;
-static fd_set GrabImperviousClients;
-static fd_set SavedAllClients;
-static fd_set SavedAllSockets;
-static fd_set SavedClientsWithInput;
-int GrabInProgress = 0;
-
-#if !defined(WIN32)
-int *ConnectionTranslation = NULL;
-#else
-/*
- * On NT fds are not between 0 and MAXSOCKS, they are unrelated, and there is
- * not even a known maximum value, so use something quite arbitrary for now.
- * Do storage is a hash table of size 256. Collisions are handled in a linked
- * list.
- */
-
-#undef MAXSOCKS
-#define MAXSOCKS 500
-#undef MAXSELECT
-#define MAXSELECT 500
-
-struct _ct_node {
- struct _ct_node *next;
- int key;
- int value;
-};
-
-struct _ct_node *ct_head[256];
-
-void InitConnectionTranslation(void)
-{
- memset(ct_head, 0, sizeof(ct_head));
-}
-
-int GetConnectionTranslation(int conn)
-{
- struct _ct_node *node = ct_head[conn & 0xff];
- while (node != NULL)
- {
- if (node->key == conn)
- return node->value;
- node = node->next;
- }
- return 0;
-}
-
-void SetConnectionTranslation(int conn, int client)
-{
- struct _ct_node **node = ct_head + (conn & 0xff);
- if (client == 0) /* remove entry */
- {
- while (*node != NULL)
- {
- if ((*node)->key == conn)
- {
- struct _ct_node *temp = *node;
- *node = (*node)->next;
- free(temp);
- return;
- }
- node = &((*node)->next);
- }
- return;
- } else
- {
- while (*node != NULL)
- {
- if ((*node)->key == conn)
- {
- (*node)->value = client;
- return;
- }
- node = &((*node)->next);
- }
- *node = malloc(sizeof(struct _ct_node));
- (*node)->next = NULL;
- (*node)->key = conn;
- (*node)->value = client;
- return;
- }
-}
-
-void ClearConnectionTranslation(void)
-{
- unsigned i;
- for (i = 0; i < 256; i++)
- {
- struct _ct_node *node = ct_head[i];
- while (node != NULL)
- {
- struct _ct_node *temp = node;
- node = node->next;
- free(temp);
- }
- }
-}
-#endif
-
-static XtransConnInfo *ListenTransConns = NULL;
-static int *ListenTransFds = NULL;
-static int ListenTransCount;
-
-static void ErrorConnMax(XtransConnInfo /* trans_conn */);
-
-static XtransConnInfo
-lookup_trans_conn (int fd)
-{
- if (ListenTransFds)
- {
- int i;
- for (i = 0; i < ListenTransCount; i++)
- if (ListenTransFds[i] == fd)
- return ListenTransConns[i];
- }
-
- return NULL;
-}
-
-/* Set MaxClients and lastfdesc, and allocate ConnectionTranslation */
-
-void
-InitConnectionLimits(void)
-{
- lastfdesc = -1;
-
-#ifndef __CYGWIN__
-
-#if !defined(XNO_SYSCONF) && defined(_SC_OPEN_MAX)
- lastfdesc = sysconf(_SC_OPEN_MAX) - 1;
-#endif
-
-#ifdef HAS_GETDTABLESIZE
- if (lastfdesc < 0)
- lastfdesc = getdtablesize() - 1;
-#endif
-
-#ifdef _NFILE
- if (lastfdesc < 0)
- lastfdesc = _NFILE - 1;
-#endif
-
-#endif /* __CYGWIN__ */
-
- /* This is the fallback */
- if (lastfdesc < 0)
- lastfdesc = MAXSOCKS;
-
- if (lastfdesc > MAXSELECT)
- lastfdesc = MAXSELECT;
-
- if (lastfdesc > MAXCLIENTS)
- {
- lastfdesc = MAXCLIENTS;
- if (debug_conns)
- ErrorF( "REACHED MAXIMUM CLIENTS LIMIT %d\n", MAXCLIENTS);
- }
- MaxClients = lastfdesc;
-
-#ifdef DEBUG
- ErrorF("InitConnectionLimits: MaxClients = %d\n", MaxClients);
-#endif
-
-#if !defined(WIN32)
- if (!ConnectionTranslation)
- ConnectionTranslation = (int *)xnfalloc(sizeof(int)*(lastfdesc + 1));
-#else
- InitConnectionTranslation();
-#endif
-}
-
-/*
- * If SIGUSR1 was set to SIG_IGN when the server started, assume that either
- *
- * a- The parent process is ignoring SIGUSR1
- *
- * or
- *
- * b- The parent process is expecting a SIGUSR1
- * when the server is ready to accept connections
- *
- * In the first case, the signal will be harmless, in the second case,
- * the signal will be quite useful.
- */
-static void
-InitParentProcess(void)
-{
-#if !defined(WIN32)
- OsSigHandlerPtr handler;
- handler = OsSignal (SIGUSR1, SIG_IGN);
- if ( handler == SIG_IGN)
- RunFromSmartParent = TRUE;
- OsSignal(SIGUSR1, handler);
- ParentProcess = getppid ();
-#endif
-}
-
-void
-NotifyParentProcess(void)
-{
-#if !defined(WIN32)
- if (RunFromSmartParent) {
- if (ParentProcess > 1) {
- kill (ParentProcess, SIGUSR1);
- }
- }
- if (RunFromSigStopParent)
- raise (SIGSTOP);
-#endif
-}
-
-/*****************
- * CreateWellKnownSockets
- * At initialization, create the sockets to listen on for new clients.
- *****************/
-
-void
-CreateWellKnownSockets(void)
-{
- int i;
- int partial;
- char port[20];
-
- FD_ZERO(&AllSockets);
- FD_ZERO(&AllClients);
- FD_ZERO(&LastSelectMask);
- FD_ZERO(&ClientsWithInput);
-
-#if !defined(WIN32)
- for (i=0; i<MaxClients; i++) ConnectionTranslation[i] = 0;
-#else
- ClearConnectionTranslation();
-#endif
-
- FD_ZERO (&WellKnownConnections);
-
- sprintf (port, "%d", atoi (display));
-
- if ((_XSERVTransMakeAllCOTSServerListeners (port, &partial,
- &ListenTransCount, &ListenTransConns) >= 0) &&
- (ListenTransCount >= 1))
- {
- if (!PartialNetwork && partial)
- {
- FatalError ("Failed to establish all listening sockets");
- }
- else
- {
- ListenTransFds = malloc(ListenTransCount * sizeof (int));
-
- for (i = 0; i < ListenTransCount; i++)
- {
- int fd = _XSERVTransGetConnectionNumber (ListenTransConns[i]);
-
- ListenTransFds[i] = fd;
- FD_SET (fd, &WellKnownConnections);
-
- if (!_XSERVTransIsLocal (ListenTransConns[i]))
- {
- DefineSelf (fd);
- }
- }
- }
- }
-
- if (!XFD_ANYSET (&WellKnownConnections))
- FatalError ("Cannot establish any listening sockets - Make sure an X server isn't already running");
-#if !defined(WIN32)
- OsSignal (SIGPIPE, SIG_IGN);
- OsSignal (SIGHUP, AutoResetServer);
-#endif
- OsSignal (SIGINT, GiveUp);
- OsSignal (SIGTERM, GiveUp);
- XFD_COPYSET (&WellKnownConnections, &AllSockets);
- ResetHosts(display);
-
- InitParentProcess();
-
-#ifdef XDMCP
- XdmcpInit ();
-#endif
-}
-
-void
-ResetWellKnownSockets (void)
-{
- int i;
-
- ResetOsBuffers();
-
- for (i = 0; i < ListenTransCount; i++)
- {
- int status = _XSERVTransResetListener (ListenTransConns[i]);
-
- if (status != TRANS_RESET_NOOP)
- {
- if (status == TRANS_RESET_FAILURE)
- {
- /*
- * ListenTransConns[i] freed by xtrans.
- * Remove it from out list.
- */
-
- FD_CLR (ListenTransFds[i], &WellKnownConnections);
- ListenTransFds[i] = ListenTransFds[ListenTransCount - 1];
- ListenTransConns[i] = ListenTransConns[ListenTransCount - 1];
- ListenTransCount -= 1;
- i -= 1;
- }
- else if (status == TRANS_RESET_NEW_FD)
- {
- /*
- * A new file descriptor was allocated (the old one was closed)
- */
-
- int newfd = _XSERVTransGetConnectionNumber (ListenTransConns[i]);
-
- FD_CLR (ListenTransFds[i], &WellKnownConnections);
- ListenTransFds[i] = newfd;
- FD_SET(newfd, &WellKnownConnections);
- }
- }
- }
-
- ResetAuthorization ();
- ResetHosts(display);
- /*
- * restart XDMCP
- */
-#ifdef XDMCP
- XdmcpReset ();
-#endif
-}
-
-void
-CloseWellKnownConnections(void)
-{
- int i;
-
- for (i = 0; i < ListenTransCount; i++)
- _XSERVTransClose (ListenTransConns[i]);
-}
-
-static void
-AuthAudit (ClientPtr client, Bool letin,
- struct sockaddr *saddr, int len,
- unsigned int proto_n, char *auth_proto, int auth_id)
-{
- char addr[128];
- char *out = addr;
- char client_uid_string[64];
- LocalClientCredRec *lcc;
-#ifdef XSERVER_DTRACE
- pid_t client_pid = -1;
- zoneid_t client_zid = -1;
-#endif
-
- if (!len)
- strcpy(out, "local host");
- else
- switch (saddr->sa_family)
- {
- case AF_UNSPEC:
-#if defined(UNIXCONN) || defined(LOCALCONN)
- case AF_UNIX:
-#endif
- strcpy(out, "local host");
- break;
-#if defined(TCPCONN) || defined(STREAMSCONN)
- case AF_INET:
- sprintf(out, "IP %s",
- inet_ntoa(((struct sockaddr_in *) saddr)->sin_addr));
- break;
-#if defined(IPv6) && defined(AF_INET6)
- case AF_INET6: {
- char ipaddr[INET6_ADDRSTRLEN];
- inet_ntop(AF_INET6, &((struct sockaddr_in6 *) saddr)->sin6_addr,
- ipaddr, sizeof(ipaddr));
- sprintf(out, "IP %s", ipaddr);
- }
- break;
-#endif
-#endif
- default:
- strcpy(out, "unknown address");
- }
-
- if (GetLocalClientCreds(client, &lcc) != -1) {
- int slen; /* length written to client_uid_string */
-
- strcpy(client_uid_string, " ( ");
- slen = 3;
-
- if (lcc->fieldsSet & LCC_UID_SET) {
- snprintf(client_uid_string + slen,
- sizeof(client_uid_string) - slen,
- "uid=%ld ", (long) lcc->euid);
- slen = strlen(client_uid_string);
- }
-
- if (lcc->fieldsSet & LCC_GID_SET) {
- snprintf(client_uid_string + slen,
- sizeof(client_uid_string) - slen,
- "gid=%ld ", (long) lcc->egid);
- slen = strlen(client_uid_string);
- }
-
- if (lcc->fieldsSet & LCC_PID_SET) {
-#ifdef XSERVER_DTRACE
- client_pid = lcc->pid;
-#endif
- snprintf(client_uid_string + slen,
- sizeof(client_uid_string) - slen,
- "pid=%ld ", (long) lcc->pid);
- slen = strlen(client_uid_string);
- }
-
- if (lcc->fieldsSet & LCC_ZID_SET) {
-#ifdef XSERVER_DTRACE
- client_zid = lcc->zoneid;
-#endif
- snprintf(client_uid_string + slen,
- sizeof(client_uid_string) - slen,
- "zoneid=%ld ", (long) lcc->zoneid);
- slen = strlen(client_uid_string);
- }
-
- snprintf(client_uid_string + slen, sizeof(client_uid_string) - slen,
- ")");
- FreeLocalClientCreds(lcc);
- }
- else {
- client_uid_string[0] = '\0';
- }
-
-#ifdef XSERVER_DTRACE
- XSERVER_CLIENT_AUTH(client->index, addr, client_pid, client_zid);
-#endif
- if (auditTrailLevel > 1) {
- if (proto_n)
- AuditF("client %d %s from %s%s\n Auth name: %.*s ID: %d\n",
- client->index, letin ? "connected" : "rejected", addr,
- client_uid_string, (int)proto_n, auth_proto, auth_id);
- else
- AuditF("client %d %s from %s%s\n",
- client->index, letin ? "connected" : "rejected", addr,
- client_uid_string);
-
- }
-}
-
-XID
-AuthorizationIDOfClient(ClientPtr client)
-{
- if (client->osPrivate)
- return ((OsCommPtr)client->osPrivate)->auth_id;
- else
- return None;
-}
-
-
-/*****************************************************************
- * ClientAuthorized
- *
- * Sent by the client at connection setup:
- * typedef struct _xConnClientPrefix {
- * CARD8 byteOrder;
- * BYTE pad;
- * CARD16 majorVersion, minorVersion;
- * CARD16 nbytesAuthProto;
- * CARD16 nbytesAuthString;
- * } xConnClientPrefix;
- *
- * It is hoped that eventually one protocol will be agreed upon. In the
- * mean time, a server that implements a different protocol than the
- * client expects, or a server that only implements the host-based
- * mechanism, will simply ignore this information.
- *
- *****************************************************************/
-
-char *
-ClientAuthorized(ClientPtr client,
- unsigned int proto_n, char *auth_proto,
- unsigned int string_n, char *auth_string)
-{
- OsCommPtr priv;
- Xtransaddr *from = NULL;
- int family;
- int fromlen;
- XID auth_id;
- char *reason = NULL;
- XtransConnInfo trans_conn;
-
- priv = (OsCommPtr)client->osPrivate;
- trans_conn = priv->trans_conn;
-
- /* Allow any client to connect without authorization on a launchd socket,
- because it is securely created -- this prevents a race condition on launch */
- if(trans_conn->flags & TRANS_NOXAUTH) {
- auth_id = (XID) 0L;
- } else {
- auth_id = CheckAuthorization (proto_n, auth_proto, string_n, auth_string, client, &reason);
- }
-
- if (auth_id == (XID) ~0L)
- {
- if (_XSERVTransGetPeerAddr(trans_conn, &family, &fromlen, &from) != -1)
- {
- if (InvalidHost ((struct sockaddr *) from, fromlen, client))
- AuthAudit(client, FALSE, (struct sockaddr *) from,
- fromlen, proto_n, auth_proto, auth_id);
- else
- {
- auth_id = (XID) 0;
-#ifdef XSERVER_DTRACE
- if ((auditTrailLevel > 1) || XSERVER_CLIENT_AUTH_ENABLED())
-#else
- if (auditTrailLevel > 1)
-#endif
- AuthAudit(client, TRUE,
- (struct sockaddr *) from, fromlen,
- proto_n, auth_proto, auth_id);
- }
-
- free(from);
- }
-
- if (auth_id == (XID) ~0L) {
- if (reason)
- return reason;
- else
- return "Client is not authorized to connect to Server";
- }
- }
-#ifdef XSERVER_DTRACE
- else if ((auditTrailLevel > 1) || XSERVER_CLIENT_AUTH_ENABLED())
-#else
- else if (auditTrailLevel > 1)
-#endif
- {
- if (_XSERVTransGetPeerAddr (trans_conn,
- &family, &fromlen, &from) != -1)
- {
- AuthAudit(client, TRUE, (struct sockaddr *) from, fromlen,
- proto_n, auth_proto, auth_id);
-
- free(from);
- }
- }
- priv->auth_id = auth_id;
- priv->conn_time = 0;
-
-#ifdef XDMCP
- /* indicate to Xdmcp protocol that we've opened new client */
- XdmcpOpenDisplay(priv->fd);
-#endif /* XDMCP */
-
- XaceHook(XACE_AUTH_AVAIL, client, auth_id);
-
- /* At this point, if the client is authorized to change the access control
- * list, we should getpeername() information, and add the client to
- * the selfhosts list. It's not really the host machine, but the
- * true purpose of the selfhosts list is to see who may change the
- * access control list.
- */
- return((char *)NULL);
-}
-
-static ClientPtr
-AllocNewConnection (XtransConnInfo trans_conn, int fd, CARD32 conn_time)
-{
- OsCommPtr oc;
- ClientPtr client;
-
- if (
-#ifndef WIN32
- fd >= lastfdesc
-#else
- XFD_SETCOUNT(&AllClients) >= MaxClients
-#endif
- )
- return NullClient;
- oc = malloc(sizeof(OsCommRec));
- if (!oc)
- return NullClient;
- oc->trans_conn = trans_conn;
- oc->fd = fd;
- oc->input = (ConnectionInputPtr)NULL;
- oc->output = (ConnectionOutputPtr)NULL;
- oc->auth_id = None;
- oc->conn_time = conn_time;
- if (!(client = NextAvailableClient((pointer)oc)))
- {
- free(oc);
- return NullClient;
- }
- oc->local_client = ComputeLocalClient(client);
-#if !defined(WIN32)
- ConnectionTranslation[fd] = client->index;
-#else
- SetConnectionTranslation(fd, client->index);
-#endif
- if (GrabInProgress)
- {
- FD_SET(fd, &SavedAllClients);
- FD_SET(fd, &SavedAllSockets);
- }
- else
- {
- FD_SET(fd, &AllClients);
- FD_SET(fd, &AllSockets);
- }
-
-#ifdef DEBUG
- ErrorF("AllocNewConnection: client index = %d, socket fd = %d\n",
- client->index, fd);
-#endif
-#ifdef XSERVER_DTRACE
- XSERVER_CLIENT_CONNECT(client->index, fd);
-#endif
-
- return client;
-}
-
-/*****************
- * EstablishNewConnections
- * If anyone is waiting on listened sockets, accept them.
- * Returns a mask with indices of new clients. Updates AllClients
- * and AllSockets.
- *****************/
-
-/*ARGSUSED*/
-Bool
-EstablishNewConnections(ClientPtr clientUnused, pointer closure)
-{
- fd_set readyconnections; /* set of listeners that are ready */
- int curconn; /* fd of listener that's ready */
- register int newconn; /* fd of new client */
- CARD32 connect_time;
- register int i;
- register ClientPtr client;
- register OsCommPtr oc;
- fd_set tmask;
-
- XFD_ANDSET (&tmask, (fd_set*)closure, &WellKnownConnections);
- XFD_COPYSET(&tmask, &readyconnections);
- if (!XFD_ANYSET(&readyconnections))
- return TRUE;
- connect_time = GetTimeInMillis();
- /* kill off stragglers */
- for (i=1; i<currentMaxClients; i++)
- {
- if ((client = clients[i]))
- {
- oc = (OsCommPtr)(client->osPrivate);
- if ((oc && (oc->conn_time != 0) &&
- (connect_time - oc->conn_time) >= TimeOutValue) ||
- (client->noClientException != Success && !client->clientGone))
- CloseDownClient(client);
- }
- }
-#ifndef WIN32
- for (i = 0; i < howmany(XFD_SETSIZE, NFDBITS); i++)
- {
- while (readyconnections.fds_bits[i])
-#else
- for (i = 0; i < XFD_SETCOUNT(&readyconnections); i++)
-#endif
- {
- XtransConnInfo trans_conn, new_trans_conn;
- int status;
-
-#ifndef WIN32
- curconn = mffs (readyconnections.fds_bits[i]) - 1;
- readyconnections.fds_bits[i] &= ~((fd_mask)1 << curconn);
- curconn += (i * (sizeof(fd_mask)*8));
-#else
- curconn = XFD_FD(&readyconnections, i);
-#endif
-
- if ((trans_conn = lookup_trans_conn (curconn)) == NULL)
- continue;
-
- if ((new_trans_conn = _XSERVTransAccept (trans_conn, &status)) == NULL)
- continue;
-
- newconn = _XSERVTransGetConnectionNumber (new_trans_conn);
-
- if (newconn < lastfdesc)
- {
- int clientid;
-#if !defined(WIN32)
- clientid = ConnectionTranslation[newconn];
-#else
- clientid = GetConnectionTranslation(newconn);
-#endif
- if(clientid && (client = clients[clientid]))
- CloseDownClient(client);
- }
-
- _XSERVTransSetOption(new_trans_conn, TRANS_NONBLOCKING, 1);
-
- if(trans_conn->flags & TRANS_NOXAUTH)
- new_trans_conn->flags = new_trans_conn->flags | TRANS_NOXAUTH;
-
- if (!AllocNewConnection (new_trans_conn, newconn, connect_time))
- {
- ErrorConnMax(new_trans_conn);
- _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<howmany(XFD_SETSIZE, NFDBITS); i++)
- {
- mask = AllClients.fds_bits[i];
- while (mask)
- {
- curoff = mffs (mask) - 1;
- curclient = curoff + (i * (sizeof(fd_mask)*8));
- FD_ZERO(&tmask);
- FD_SET(curclient, &tmask);
- do {
- r = Select (curclient + 1, &tmask, NULL, NULL, &notime);
- } while (r < 0 && (errno == EINTR || errno == EAGAIN));
- if (r < 0)
- if (ConnectionTranslation[curclient] > 0)
- CloseDownClient(clients[ConnectionTranslation[curclient]]);
- mask &= ~((fd_mask)1 << curoff);
- }
- }
-#else
- XFD_COPYSET(&AllClients, &savedAllClients);
- for (i = 0; i < XFD_SETCOUNT(&savedAllClients); i++)
- {
- curclient = XFD_FD(&savedAllClients, i);
- FD_ZERO(&tmask);
- FD_SET(curclient, &tmask);
- do {
- r = Select (curclient + 1, &tmask, NULL, NULL, &notime);
- } while (r < 0 && (errno == EINTR || errno == EAGAIN));
- if (r < 0)
- if (GetConnectionTranslation(curclient) > 0)
- CloseDownClient(clients[GetConnectionTranslation(curclient)]);
- }
-#endif
-}
-
-
-/*****************
- * CloseDownConnection
- * Delete client from AllClients and free resources
- *****************/
-
-void
-CloseDownConnection(ClientPtr client)
-{
- OsCommPtr oc = (OsCommPtr)client->osPrivate;
-
- if (FlushCallback)
- CallCallbacks(&FlushCallback, NULL);
-
- if (oc->output && oc->output->count)
- FlushClient(client, oc, (char *)NULL, 0);
-#ifdef XDMCP
- XdmcpCloseDisplay(oc->fd);
-#endif
- CloseDownFileDescriptor(oc);
- FreeOsBuffers(oc);
- free(client->osPrivate);
- client->osPrivate = (pointer)NULL;
- if (auditTrailLevel > 1)
- AuditF("client %d disconnected\n", client->index);
-}
-
-void
-AddGeneralSocket(int fd)
-{
- FD_SET(fd, &AllSockets);
- if (GrabInProgress)
- FD_SET(fd, &SavedAllSockets);
-}
-
-void
-AddEnabledDevice(int fd)
-{
- FD_SET(fd, &EnabledDevices);
- AddGeneralSocket(fd);
-}
-
-void
-RemoveGeneralSocket(int fd)
-{
- FD_CLR(fd, &AllSockets);
- if (GrabInProgress)
- FD_CLR(fd, &SavedAllSockets);
-}
-
-void
-RemoveEnabledDevice(int fd)
-{
- FD_CLR(fd, &EnabledDevices);
- RemoveGeneralSocket(fd);
-}
-
-/*****************
- * OnlyListenToOneClient:
- * Only accept requests from one client. Continue to handle new
- * connections, but don't take any protocol requests from the new
- * ones. Note that if GrabInProgress is set, EstablishNewConnections
- * needs to put new clients into SavedAllSockets and SavedAllClients.
- * Note also that there is no timeout for this in the protocol.
- * This routine is "undone" by ListenToAllClients()
- *****************/
-
-int
-OnlyListenToOneClient(ClientPtr client)
-{
- OsCommPtr oc = (OsCommPtr)client->osPrivate;
- int rc, connection = oc->fd;
-
- rc = XaceHook(XACE_SERVER_ACCESS, client, DixGrabAccess);
- if (rc != Success)
- return rc;
-
- if (! GrabInProgress)
- {
- XFD_COPYSET(&ClientsWithInput, &SavedClientsWithInput);
- XFD_ANDSET(&ClientsWithInput,
- &ClientsWithInput, &GrabImperviousClients);
- if (FD_ISSET(connection, &SavedClientsWithInput))
- {
- FD_CLR(connection, &SavedClientsWithInput);
- FD_SET(connection, &ClientsWithInput);
- }
- XFD_UNSET(&SavedClientsWithInput, &GrabImperviousClients);
- XFD_COPYSET(&AllSockets, &SavedAllSockets);
- XFD_COPYSET(&AllClients, &SavedAllClients);
- XFD_UNSET(&AllSockets, &AllClients);
- XFD_ANDSET(&AllClients, &AllClients, &GrabImperviousClients);
- FD_SET(connection, &AllClients);
- XFD_ORSET(&AllSockets, &AllSockets, &AllClients);
- GrabInProgress = client->index;
- }
- return rc;
-}
-
-/****************
- * ListenToAllClients:
- * Undoes OnlyListentToOneClient()
- ****************/
-
-void
-ListenToAllClients(void)
-{
- if (GrabInProgress)
- {
- XFD_ORSET(&AllSockets, &AllSockets, &SavedAllSockets);
- XFD_ORSET(&AllClients, &AllClients, &SavedAllClients);
- XFD_ORSET(&ClientsWithInput, &ClientsWithInput, &SavedClientsWithInput);
- GrabInProgress = 0;
- }
-}
-
-/****************
- * IgnoreClient
- * Removes one client from input masks.
- * Must have cooresponding call to AttendClient.
- ****************/
-
-void
-IgnoreClient (ClientPtr client)
-{
- OsCommPtr oc = (OsCommPtr)client->osPrivate;
- int connection = oc->fd;
-
- client->ignoreCount++;
- if (client->ignoreCount > 1)
- return;
-
- isItTimeToYield = TRUE;
- if (!GrabInProgress || FD_ISSET(connection, &AllClients))
- {
- if (FD_ISSET (connection, &ClientsWithInput))
- FD_SET(connection, &IgnoredClientsWithInput);
- else
- FD_CLR(connection, &IgnoredClientsWithInput);
- FD_CLR(connection, &ClientsWithInput);
- FD_CLR(connection, &AllSockets);
- FD_CLR(connection, &AllClients);
- FD_CLR(connection, &LastSelectMask);
- }
- else
- {
- if (FD_ISSET (connection, &SavedClientsWithInput))
- FD_SET(connection, &IgnoredClientsWithInput);
- else
- FD_CLR(connection, &IgnoredClientsWithInput);
- FD_CLR(connection, &SavedClientsWithInput);
- FD_CLR(connection, &SavedAllSockets);
- FD_CLR(connection, &SavedAllClients);
- }
-}
-
-/****************
- * AttendClient
- * Adds one client back into the input masks.
- ****************/
-
-void
-AttendClient (ClientPtr client)
-{
- OsCommPtr oc = (OsCommPtr)client->osPrivate;
- int connection = oc->fd;
-
- client->ignoreCount--;
- if (client->ignoreCount)
- return;
-
- if (!GrabInProgress || GrabInProgress == client->index ||
- FD_ISSET(connection, &GrabImperviousClients))
- {
- FD_SET(connection, &AllClients);
- FD_SET(connection, &AllSockets);
- FD_SET(connection, &LastSelectMask);
- if (FD_ISSET (connection, &IgnoredClientsWithInput))
- FD_SET(connection, &ClientsWithInput);
- }
- else
- {
- FD_SET(connection, &SavedAllClients);
- FD_SET(connection, &SavedAllSockets);
- if (FD_ISSET(connection, &IgnoredClientsWithInput))
- FD_SET(connection, &SavedClientsWithInput);
- }
-}
-
-/* make client impervious to grabs; assume only executing client calls this */
-
-void
-MakeClientGrabImpervious(ClientPtr client)
-{
- OsCommPtr oc = (OsCommPtr)client->osPrivate;
- int connection = oc->fd;
-
- FD_SET(connection, &GrabImperviousClients);
-
- if (ServerGrabCallback)
- {
- ServerGrabInfoRec grabinfo;
- grabinfo.client = client;
- grabinfo.grabstate = CLIENT_IMPERVIOUS;
- CallCallbacks(&ServerGrabCallback, &grabinfo);
- }
-}
-
-/* make client pervious to grabs; assume only executing client calls this */
-
-void
-MakeClientGrabPervious(ClientPtr client)
-{
- OsCommPtr oc = (OsCommPtr)client->osPrivate;
- int connection = oc->fd;
-
- FD_CLR(connection, &GrabImperviousClients);
- if (GrabInProgress && (GrabInProgress != client->index))
- {
- if (FD_ISSET(connection, &ClientsWithInput))
- {
- FD_SET(connection, &SavedClientsWithInput);
- FD_CLR(connection, &ClientsWithInput);
- }
- FD_CLR(connection, &AllSockets);
- FD_CLR(connection, &AllClients);
- isItTimeToYield = TRUE;
- }
-
- if (ServerGrabCallback)
- {
- ServerGrabInfoRec grabinfo;
- grabinfo.client = client;
- grabinfo.grabstate = CLIENT_PERVIOUS;
- CallCallbacks(&ServerGrabCallback, &grabinfo);
- }
-}
-
-#ifdef XQUARTZ
-/* Add a fd (from launchd) to our listeners */
-void ListenOnOpenFD(int fd, int noxauth) {
- char port[256];
- XtransConnInfo ciptr;
- const char *display_env = getenv("DISPLAY");
-
- if(display_env && (strncmp(display_env, "/tmp/launch", 11) == 0)) {
- /* Make the path the launchd socket if our DISPLAY is set right */
- strcpy(port, display_env);
- } else {
- /* Just some default so things don't break and die. */
- sprintf(port, ":%d", atoi(display));
- }
-
- /* Make our XtransConnInfo
- * TRANS_SOCKET_LOCAL_INDEX = 5 from Xtrans.c
- */
- ciptr = _XSERVTransReopenCOTSServer(5, fd, port);
- if(ciptr == NULL) {
- ErrorF("Got NULL while trying to Reopen launchd port.\n");
- return;
- }
-
- if(noxauth)
- ciptr->flags = ciptr->flags | TRANS_NOXAUTH;
-
- /* Allocate space to store it */
- ListenTransFds = (int *) realloc(ListenTransFds, (ListenTransCount + 1) * sizeof (int));
- ListenTransConns = (XtransConnInfo *) realloc(ListenTransConns, (ListenTransCount + 1) * sizeof (XtransConnInfo));
-
- /* Store it */
- ListenTransConns[ListenTransCount] = ciptr;
- ListenTransFds[ListenTransCount] = fd;
-
- FD_SET(fd, &WellKnownConnections);
- FD_SET(fd, &AllSockets);
-
- /* Increment the count */
- ListenTransCount++;
-
- /* This *might* not be needed... /shrug */
- ResetAuthorization();
- ResetHosts(display);
-#ifdef XDMCP
- XdmcpReset();
-#endif
-}
-
-#endif
+/***********************************************************
+
+Copyright 1987, 1989, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+/*****************************************************************
+ * Stuff to create connections --- OS dependent
+ *
+ * EstablishNewConnections, CreateWellKnownSockets, ResetWellKnownSockets,
+ * CloseDownConnection, CheckConnections, AddEnabledDevice,
+ * RemoveEnabledDevice, OnlyListToOneClient,
+ * ListenToAllClients,
+ *
+ * (WaitForSomething is in its own file)
+ *
+ * In this implementation, a client socket table is not kept.
+ * Instead, what would be the index into the table is just the
+ * file descriptor of the socket. This won't work for if the
+ * socket ids aren't small nums (0 - 2^8)
+ *
+ *****************************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifdef WIN32
+#include <X11/Xwinsock.h>
+#ifdef _DEBUG
+#define DEBUG
+#endif
+#endif
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#define XSERV_t
+#define TRANS_SERVER
+#define TRANS_REOPEN
+#include <X11/Xtrans/Xtrans.h>
+#include <X11/Xtrans/Xtransint.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef WIN32
+#include <sys/socket.h>
+
+
+
+#if defined(TCPCONN) || defined(STREAMSCONN)
+# include <netinet/in.h>
+# include <arpa/inet.h>
+# ifdef apollo
+# ifndef NO_TCP_H
+# include <netinet/tcp.h>
+# endif
+# else
+# ifdef CSRG_BASED
+# include <sys/param.h>
+# endif
+# include <netinet/tcp.h>
+# endif
+# include <arpa/inet.h>
+#endif
+
+#include <sys/uio.h>
+
+#endif /* WIN32 */
+#include "misc.h" /* for typedef of pointer */
+#include "osdep.h"
+#include <X11/Xpoll.h>
+#include "opaque.h"
+#include "dixstruct.h"
+#include "xace.h"
+
+#ifdef _MSC_VER
+typedef int pid_t;
+#endif
+
+#define Pid_t pid_t
+
+
+#ifdef HAS_GETPEERUCRED
+# include <ucred.h>
+# include <zone.h>
+#endif
+
+#ifdef XSERVER_DTRACE
+# include <sys/types.h>
+typedef const char *string;
+# ifndef HAS_GETPEERUCRED
+# define zoneid_t int
+# endif
+# include "../dix/Xserver-dtrace.h"
+#endif
+
+static int lastfdesc; /* maximum file descriptor */
+
+fd_set WellKnownConnections; /* Listener mask */
+fd_set EnabledDevices; /* mask for input devices that are on */
+fd_set AllSockets; /* select on this */
+fd_set AllClients; /* available clients */
+fd_set LastSelectMask; /* mask returned from last select call */
+fd_set ClientsWithInput; /* clients with FULL requests in buffer */
+fd_set ClientsWriteBlocked; /* clients who cannot receive output */
+fd_set OutputPending; /* clients with reply/event data ready to go */
+int MaxClients = 0;
+Bool NewOutputPending; /* not yet attempted to write some new output */
+Bool AnyClientsWriteBlocked; /* true if some client blocked on write */
+
+#if !defined(_MSC_VER)
+static Bool RunFromSmartParent; /* send SIGUSR1 to parent process */
+static Pid_t ParentProcess;
+#endif
+Bool RunFromSigStopParent; /* send SIGSTOP to our own process; Upstart (or
+ equivalent) will send SIGCONT back. */
+Bool PartialNetwork; /* continue even if unable to bind all addrs */
+
+static Bool debug_conns = FALSE;
+
+fd_set IgnoredClientsWithInput;
+static fd_set GrabImperviousClients;
+static fd_set SavedAllClients;
+static fd_set SavedAllSockets;
+static fd_set SavedClientsWithInput;
+int GrabInProgress = 0;
+
+#if !defined(WIN32)
+int *ConnectionTranslation = NULL;
+#else
+/*
+ * On NT fds are not between 0 and MAXSOCKS, they are unrelated, and there is
+ * not even a known maximum value, so use something quite arbitrary for now.
+ * Do storage is a hash table of size 256. Collisions are handled in a linked
+ * list.
+ */
+
+#undef MAXSOCKS
+#define MAXSOCKS 500
+#undef MAXSELECT
+#define MAXSELECT 500
+
+struct _ct_node {
+ struct _ct_node *next;
+ int key;
+ int value;
+};
+
+struct _ct_node *ct_head[256];
+
+void InitConnectionTranslation(void)
+{
+ memset(ct_head, 0, sizeof(ct_head));
+}
+
+int GetConnectionTranslation(int conn)
+{
+ struct _ct_node *node = ct_head[conn & 0xff];
+ while (node != NULL)
+ {
+ if (node->key == conn)
+ return node->value;
+ node = node->next;
+ }
+ return 0;
+}
+
+void SetConnectionTranslation(int conn, int client)
+{
+ struct _ct_node **node = ct_head + (conn & 0xff);
+ if (client == 0) /* remove entry */
+ {
+ while (*node != NULL)
+ {
+ if ((*node)->key == conn)
+ {
+ struct _ct_node *temp = *node;
+ *node = (*node)->next;
+ free(temp);
+ return;
+ }
+ node = &((*node)->next);
+ }
+ return;
+ } else
+ {
+ while (*node != NULL)
+ {
+ if ((*node)->key == conn)
+ {
+ (*node)->value = client;
+ return;
+ }
+ node = &((*node)->next);
+ }
+ *node = malloc(sizeof(struct _ct_node));
+ (*node)->next = NULL;
+ (*node)->key = conn;
+ (*node)->value = client;
+ return;
+ }
+}
+
+void ClearConnectionTranslation(void)
+{
+ unsigned i;
+ for (i = 0; i < 256; i++)
+ {
+ struct _ct_node *node = ct_head[i];
+ while (node != NULL)
+ {
+ struct _ct_node *temp = node;
+ node = node->next;
+ free(temp);
+ }
+ }
+}
+#endif
+
+static XtransConnInfo *ListenTransConns = NULL;
+static int *ListenTransFds = NULL;
+static int ListenTransCount;
+
+static void ErrorConnMax(XtransConnInfo /* trans_conn */);
+
+static XtransConnInfo
+lookup_trans_conn (int fd)
+{
+ if (ListenTransFds)
+ {
+ int i;
+ for (i = 0; i < ListenTransCount; i++)
+ if (ListenTransFds[i] == fd)
+ return ListenTransConns[i];
+ }
+
+ return NULL;
+}
+
+int
+TransIsListening(char *protocol)
+{
+ /* look for this transport in the list of listeners */
+ int i;
+ for (i = 0; i < ListenTransCount; i++)
+ {
+ if (!strcmp(protocol, ListenTransConns[i]->transptr->TransName))
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+
+/* Set MaxClients and lastfdesc, and allocate ConnectionTranslation */
+
+void
+InitConnectionLimits(void)
+{
+ lastfdesc = -1;
+
+#ifndef __CYGWIN__
+
+#if !defined(XNO_SYSCONF) && defined(_SC_OPEN_MAX)
+ lastfdesc = sysconf(_SC_OPEN_MAX) - 1;
+#endif
+
+#ifdef HAS_GETDTABLESIZE
+ if (lastfdesc < 0)
+ lastfdesc = getdtablesize() - 1;
+#endif
+
+#ifdef _NFILE
+ if (lastfdesc < 0)
+ lastfdesc = _NFILE - 1;
+#endif
+
+#endif /* __CYGWIN__ */
+
+ /* This is the fallback */
+ if (lastfdesc < 0)
+ lastfdesc = MAXSOCKS;
+
+ if (lastfdesc > MAXSELECT)
+ lastfdesc = MAXSELECT;
+
+ if (lastfdesc > MAXCLIENTS)
+ {
+ lastfdesc = MAXCLIENTS;
+ if (debug_conns)
+ ErrorF( "REACHED MAXIMUM CLIENTS LIMIT %d\n", MAXCLIENTS);
+ }
+ MaxClients = lastfdesc;
+
+#ifdef DEBUG
+ ErrorF("InitConnectionLimits: MaxClients = %d\n", MaxClients);
+#endif
+
+#if !defined(WIN32)
+ if (!ConnectionTranslation)
+ ConnectionTranslation = (int *)xnfalloc(sizeof(int)*(lastfdesc + 1));
+#else
+ InitConnectionTranslation();
+#endif
+}
+
+/*
+ * If SIGUSR1 was set to SIG_IGN when the server started, assume that either
+ *
+ * a- The parent process is ignoring SIGUSR1
+ *
+ * or
+ *
+ * b- The parent process is expecting a SIGUSR1
+ * when the server is ready to accept connections
+ *
+ * In the first case, the signal will be harmless, in the second case,
+ * the signal will be quite useful.
+ */
+static void
+InitParentProcess(void)
+{
+#if !defined(WIN32)
+ OsSigHandlerPtr handler;
+ handler = OsSignal (SIGUSR1, SIG_IGN);
+ if ( handler == SIG_IGN)
+ RunFromSmartParent = TRUE;
+ OsSignal(SIGUSR1, handler);
+ ParentProcess = getppid ();
+#endif
+}
+
+void
+NotifyParentProcess(void)
+{
+#if !defined(WIN32)
+ if (RunFromSmartParent) {
+ if (ParentProcess > 1) {
+ kill (ParentProcess, SIGUSR1);
+ }
+ }
+ if (RunFromSigStopParent)
+ raise (SIGSTOP);
+#endif
+}
+
+/*****************
+ * CreateWellKnownSockets
+ * At initialization, create the sockets to listen on for new clients.
+ *****************/
+
+void
+CreateWellKnownSockets(void)
+{
+ int i;
+ int partial;
+ char port[20];
+
+ FD_ZERO(&AllSockets);
+ FD_ZERO(&AllClients);
+ FD_ZERO(&LastSelectMask);
+ FD_ZERO(&ClientsWithInput);
+
+#if !defined(WIN32)
+ for (i=0; i<MaxClients; i++) ConnectionTranslation[i] = 0;
+#else
+ ClearConnectionTranslation();
+#endif
+
+ FD_ZERO (&WellKnownConnections);
+
+ sprintf (port, "%d", atoi (display));
+
+ if ((_XSERVTransMakeAllCOTSServerListeners (port, &partial,
+ &ListenTransCount, &ListenTransConns) >= 0) &&
+ (ListenTransCount >= 1))
+ {
+ if (!PartialNetwork && partial)
+ {
+ FatalError ("Failed to establish all listening sockets");
+ }
+ else
+ {
+ ListenTransFds = malloc(ListenTransCount * sizeof (int));
+
+ for (i = ListenTransCount; i > 0; i--)
+ {
+ int fd = _XSERVTransGetConnectionNumber (ListenTransConns[i-1]);
+
+ ListenTransFds[i-1] = fd;
+ FD_SET (fd, &WellKnownConnections);
+
+ if (!_XSERVTransIsLocal (ListenTransConns[i-1]))
+ {
+ int protocol = 0;
+ if (!strcmp("inet", ListenTransConns[i-1]->transptr->TransName)) protocol = 4;
+ else if (!strcmp("inet6", ListenTransConns[i-1]->transptr->TransName)) protocol = 6;
+ DefineSelf (fd, protocol);
+ }
+ }
+ }
+ }
+
+ if (!XFD_ANYSET (&WellKnownConnections))
+ FatalError ("Cannot establish any listening sockets - Make sure an X server isn't already running");
+#if !defined(WIN32)
+ OsSignal (SIGPIPE, SIG_IGN);
+ OsSignal (SIGHUP, AutoResetServer);
+#endif
+ OsSignal (SIGINT, GiveUp);
+ OsSignal (SIGTERM, GiveUp);
+ XFD_COPYSET (&WellKnownConnections, &AllSockets);
+ ResetHosts(display);
+
+ InitParentProcess();
+
+#ifdef XDMCP
+ XdmcpInit ();
+#endif
+}
+
+void
+ResetWellKnownSockets (void)
+{
+ int i;
+
+ ResetOsBuffers();
+
+ for (i = 0; i < ListenTransCount; i++)
+ {
+ int status = _XSERVTransResetListener (ListenTransConns[i]);
+
+ if (status != TRANS_RESET_NOOP)
+ {
+ if (status == TRANS_RESET_FAILURE)
+ {
+ /*
+ * ListenTransConns[i] freed by xtrans.
+ * Remove it from out list.
+ */
+
+ FD_CLR (ListenTransFds[i], &WellKnownConnections);
+ ListenTransFds[i] = ListenTransFds[ListenTransCount - 1];
+ ListenTransConns[i] = ListenTransConns[ListenTransCount - 1];
+ ListenTransCount -= 1;
+ i -= 1;
+ }
+ else if (status == TRANS_RESET_NEW_FD)
+ {
+ /*
+ * A new file descriptor was allocated (the old one was closed)
+ */
+
+ int newfd = _XSERVTransGetConnectionNumber (ListenTransConns[i]);
+
+ FD_CLR (ListenTransFds[i], &WellKnownConnections);
+ ListenTransFds[i] = newfd;
+ FD_SET(newfd, &WellKnownConnections);
+ }
+ }
+ }
+
+ ResetAuthorization ();
+ ResetHosts(display);
+ /*
+ * restart XDMCP
+ */
+#ifdef XDMCP
+ XdmcpReset ();
+#endif
+}
+
+void
+CloseWellKnownConnections(void)
+{
+ int i;
+
+ for (i = 0; i < ListenTransCount; i++)
+ _XSERVTransClose (ListenTransConns[i]);
+}
+
+static void
+AuthAudit (ClientPtr client, Bool letin,
+ struct sockaddr *saddr, int len,
+ unsigned int proto_n, char *auth_proto, int auth_id)
+{
+ char addr[128];
+ char *out = addr;
+ char client_uid_string[64];
+ LocalClientCredRec *lcc;
+#ifdef XSERVER_DTRACE
+ pid_t client_pid = -1;
+ zoneid_t client_zid = -1;
+#endif
+
+ if (!len)
+ strcpy(out, "local host");
+ else
+ switch (saddr->sa_family)
+ {
+ case AF_UNSPEC:
+#if defined(UNIXCONN) || defined(LOCALCONN)
+ case AF_UNIX:
+#endif
+ strcpy(out, "local host");
+ break;
+#if defined(TCPCONN) || defined(STREAMSCONN)
+ case AF_INET:
+ sprintf(out, "IP %s",
+ inet_ntoa(((struct sockaddr_in *) saddr)->sin_addr));
+ break;
+#if defined(IPv6) && defined(AF_INET6)
+ case AF_INET6: {
+ char ipaddr[INET6_ADDRSTRLEN];
+ inet_ntop(AF_INET6, &((struct sockaddr_in6 *) saddr)->sin6_addr,
+ ipaddr, sizeof(ipaddr));
+ sprintf(out, "IP %s", ipaddr);
+ }
+ break;
+#endif
+#endif
+ default:
+ strcpy(out, "unknown address");
+ }
+
+ if (GetLocalClientCreds(client, &lcc) != -1) {
+ int slen; /* length written to client_uid_string */
+
+ strcpy(client_uid_string, " ( ");
+ slen = 3;
+
+ if (lcc->fieldsSet & LCC_UID_SET) {
+ snprintf(client_uid_string + slen,
+ sizeof(client_uid_string) - slen,
+ "uid=%ld ", (long) lcc->euid);
+ slen = strlen(client_uid_string);
+ }
+
+ if (lcc->fieldsSet & LCC_GID_SET) {
+ snprintf(client_uid_string + slen,
+ sizeof(client_uid_string) - slen,
+ "gid=%ld ", (long) lcc->egid);
+ slen = strlen(client_uid_string);
+ }
+
+ if (lcc->fieldsSet & LCC_PID_SET) {
+#ifdef XSERVER_DTRACE
+ client_pid = lcc->pid;
+#endif
+ snprintf(client_uid_string + slen,
+ sizeof(client_uid_string) - slen,
+ "pid=%ld ", (long) lcc->pid);
+ slen = strlen(client_uid_string);
+ }
+
+ if (lcc->fieldsSet & LCC_ZID_SET) {
+#ifdef XSERVER_DTRACE
+ client_zid = lcc->zoneid;
+#endif
+ snprintf(client_uid_string + slen,
+ sizeof(client_uid_string) - slen,
+ "zoneid=%ld ", (long) lcc->zoneid);
+ slen = strlen(client_uid_string);
+ }
+
+ snprintf(client_uid_string + slen, sizeof(client_uid_string) - slen,
+ ")");
+ FreeLocalClientCreds(lcc);
+ }
+ else {
+ client_uid_string[0] = '\0';
+ }
+
+#ifdef XSERVER_DTRACE
+ XSERVER_CLIENT_AUTH(client->index, addr, client_pid, client_zid);
+#endif
+ if (auditTrailLevel > 1) {
+ if (proto_n)
+ AuditF("client %d %s from %s%s\n Auth name: %.*s ID: %d\n",
+ client->index, letin ? "connected" : "rejected", addr,
+ client_uid_string, (int)proto_n, auth_proto, auth_id);
+ else
+ AuditF("client %d %s from %s%s\n",
+ client->index, letin ? "connected" : "rejected", addr,
+ client_uid_string);
+
+ }
+}
+
+XID
+AuthorizationIDOfClient(ClientPtr client)
+{
+ if (client->osPrivate)
+ return ((OsCommPtr)client->osPrivate)->auth_id;
+ else
+ return None;
+}
+
+
+/*****************************************************************
+ * ClientAuthorized
+ *
+ * Sent by the client at connection setup:
+ * typedef struct _xConnClientPrefix {
+ * CARD8 byteOrder;
+ * BYTE pad;
+ * CARD16 majorVersion, minorVersion;
+ * CARD16 nbytesAuthProto;
+ * CARD16 nbytesAuthString;
+ * } xConnClientPrefix;
+ *
+ * It is hoped that eventually one protocol will be agreed upon. In the
+ * mean time, a server that implements a different protocol than the
+ * client expects, or a server that only implements the host-based
+ * mechanism, will simply ignore this information.
+ *
+ *****************************************************************/
+
+char *
+ClientAuthorized(ClientPtr client,
+ unsigned int proto_n, char *auth_proto,
+ unsigned int string_n, char *auth_string)
+{
+ OsCommPtr priv;
+ Xtransaddr *from = NULL;
+ int family;
+ int fromlen;
+ XID auth_id;
+ char *reason = NULL;
+ XtransConnInfo trans_conn;
+
+ priv = (OsCommPtr)client->osPrivate;
+ trans_conn = priv->trans_conn;
+
+ /* Allow any client to connect without authorization on a launchd socket,
+ because it is securely created -- this prevents a race condition on launch */
+ if(trans_conn->flags & TRANS_NOXAUTH) {
+ auth_id = (XID) 0L;
+ } else {
+ auth_id = CheckAuthorization (proto_n, auth_proto, string_n, auth_string, client, &reason);
+ }
+
+ if (auth_id == (XID) ~0L)
+ {
+ if (_XSERVTransGetPeerAddr(trans_conn, &family, &fromlen, &from) != -1)
+ {
+ if (InvalidHost ((struct sockaddr *) from, fromlen, client))
+ AuthAudit(client, FALSE, (struct sockaddr *) from,
+ fromlen, proto_n, auth_proto, auth_id);
+ else
+ {
+ auth_id = (XID) 0;
+#ifdef XSERVER_DTRACE
+ if ((auditTrailLevel > 1) || XSERVER_CLIENT_AUTH_ENABLED())
+#else
+ if (auditTrailLevel > 1)
+#endif
+ AuthAudit(client, TRUE,
+ (struct sockaddr *) from, fromlen,
+ proto_n, auth_proto, auth_id);
+ }
+
+ free(from);
+ }
+
+ if (auth_id == (XID) ~0L) {
+ if (reason)
+ return reason;
+ else
+ return "Client is not authorized to connect to Server";
+ }
+ }
+#ifdef XSERVER_DTRACE
+ else if ((auditTrailLevel > 1) || XSERVER_CLIENT_AUTH_ENABLED())
+#else
+ else if (auditTrailLevel > 1)
+#endif
+ {
+ if (_XSERVTransGetPeerAddr (trans_conn,
+ &family, &fromlen, &from) != -1)
+ {
+ AuthAudit(client, TRUE, (struct sockaddr *) from, fromlen,
+ proto_n, auth_proto, auth_id);
+
+ free(from);
+ }
+ }
+ priv->auth_id = auth_id;
+ priv->conn_time = 0;
+
+#ifdef XDMCP
+ /* indicate to Xdmcp protocol that we've opened new client */
+ XdmcpOpenDisplay(priv->fd);
+#endif /* XDMCP */
+
+ XaceHook(XACE_AUTH_AVAIL, client, auth_id);
+
+ /* At this point, if the client is authorized to change the access control
+ * list, we should getpeername() information, and add the client to
+ * the selfhosts list. It's not really the host machine, but the
+ * true purpose of the selfhosts list is to see who may change the
+ * access control list.
+ */
+ return((char *)NULL);
+}
+
+static ClientPtr
+AllocNewConnection (XtransConnInfo trans_conn, int fd, CARD32 conn_time)
+{
+ OsCommPtr oc;
+ ClientPtr client;
+
+ if (
+#ifndef WIN32
+ fd >= lastfdesc
+#else
+ XFD_SETCOUNT(&AllClients) >= MaxClients
+#endif
+ )
+ return NullClient;
+ oc = malloc(sizeof(OsCommRec));
+ if (!oc)
+ return NullClient;
+ oc->trans_conn = trans_conn;
+ oc->fd = fd;
+ oc->input = (ConnectionInputPtr)NULL;
+ oc->output = (ConnectionOutputPtr)NULL;
+ oc->auth_id = None;
+ oc->conn_time = conn_time;
+ if (!(client = NextAvailableClient((pointer)oc)))
+ {
+ free(oc);
+ return NullClient;
+ }
+ oc->local_client = ComputeLocalClient(client);
+#if !defined(WIN32)
+ ConnectionTranslation[fd] = client->index;
+#else
+ SetConnectionTranslation(fd, client->index);
+#endif
+ if (GrabInProgress)
+ {
+ FD_SET(fd, &SavedAllClients);
+ FD_SET(fd, &SavedAllSockets);
+ }
+ else
+ {
+ FD_SET(fd, &AllClients);
+ FD_SET(fd, &AllSockets);
+ }
+
+#ifdef DEBUG
+ ErrorF("AllocNewConnection: client index = %d, socket fd = %d\n",
+ client->index, fd);
+#endif
+#ifdef XSERVER_DTRACE
+ XSERVER_CLIENT_CONNECT(client->index, fd);
+#endif
+
+ return client;
+}
+
+/*****************
+ * EstablishNewConnections
+ * If anyone is waiting on listened sockets, accept them.
+ * Returns a mask with indices of new clients. Updates AllClients
+ * and AllSockets.
+ *****************/
+
+/*ARGSUSED*/
+Bool
+EstablishNewConnections(ClientPtr clientUnused, pointer closure)
+{
+ fd_set readyconnections; /* set of listeners that are ready */
+ int curconn; /* fd of listener that's ready */
+ register int newconn; /* fd of new client */
+ CARD32 connect_time;
+ register int i;
+ register ClientPtr client;
+ register OsCommPtr oc;
+ fd_set tmask;
+
+ XFD_ANDSET (&tmask, (fd_set*)closure, &WellKnownConnections);
+ XFD_COPYSET(&tmask, &readyconnections);
+ if (!XFD_ANYSET(&readyconnections))
+ return TRUE;
+ connect_time = GetTimeInMillis();
+ /* kill off stragglers */
+ for (i=1; i<currentMaxClients; i++)
+ {
+ if ((client = clients[i]))
+ {
+ oc = (OsCommPtr)(client->osPrivate);
+ if ((oc && (oc->conn_time != 0) &&
+ (connect_time - oc->conn_time) >= TimeOutValue) ||
+ (client->noClientException != Success && !client->clientGone))
+ CloseDownClient(client);
+ }
+ }
+#ifndef WIN32
+ for (i = 0; i < howmany(XFD_SETSIZE, NFDBITS); i++)
+ {
+ while (readyconnections.fds_bits[i])
+#else
+ for (i = 0; i < XFD_SETCOUNT(&readyconnections); i++)
+#endif
+ {
+ XtransConnInfo trans_conn, new_trans_conn;
+ int status;
+
+#ifndef WIN32
+ curconn = mffs (readyconnections.fds_bits[i]) - 1;
+ readyconnections.fds_bits[i] &= ~((fd_mask)1 << curconn);
+ curconn += (i * (sizeof(fd_mask)*8));
+#else
+ curconn = XFD_FD(&readyconnections, i);
+#endif
+
+ if ((trans_conn = lookup_trans_conn (curconn)) == NULL)
+ continue;
+
+ if ((new_trans_conn = _XSERVTransAccept (trans_conn, &status)) == NULL)
+ continue;
+
+ newconn = _XSERVTransGetConnectionNumber (new_trans_conn);
+
+ if (newconn < lastfdesc)
+ {
+ int clientid;
+#if !defined(WIN32)
+ clientid = ConnectionTranslation[newconn];
+#else
+ clientid = GetConnectionTranslation(newconn);
+#endif
+ if(clientid && (client = clients[clientid]))
+ CloseDownClient(client);
+ }
+
+ _XSERVTransSetOption(new_trans_conn, TRANS_NONBLOCKING, 1);
+
+ if(trans_conn->flags & TRANS_NOXAUTH)
+ new_trans_conn->flags = new_trans_conn->flags | TRANS_NOXAUTH;
+
+ if (!AllocNewConnection (new_trans_conn, newconn, connect_time))
+ {
+ ErrorConnMax(new_trans_conn);
+ _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;
+ int curoff;
+#endif
+ fd_set tmask;
+ int curclient;
+ int i;
+ struct timeval notime;
+ int r;
+#ifdef WIN32
+ fd_set savedAllSockets;
+ unsigned j;
+#endif
+
+ notime.tv_sec = 0;
+ notime.tv_usec = 0;
+
+#ifndef WIN32
+ for (i=0; i<howmany(XFD_SETSIZE, NFDBITS); i++)
+ {
+ mask = AllClients.fds_bits[i];
+ while (mask)
+ {
+ curoff = mffs (mask) - 1;
+ curclient = curoff + (i * (sizeof(fd_mask)*8));
+ FD_ZERO(&tmask);
+ FD_SET(curclient, &tmask);
+ do {
+ r = Select (curclient + 1, &tmask, NULL, NULL, &notime);
+ } while (r < 0 && (errno == EINTR || errno == EAGAIN));
+ if (r < 0)
+ if (ConnectionTranslation[curclient] > 0)
+ CloseDownClient(clients[ConnectionTranslation[curclient]]);
+ mask &= ~((fd_mask)1 << curoff);
+ }
+ }
+#else
+ /* First test AllSockets and then AllClients are valid sockets */
+ XFD_COPYSET(&AllSockets, &savedAllSockets);
+ for (j=0; j<2; j++)
+ {
+ for (i = 0; i < XFD_SETCOUNT(&savedAllSockets); i++)
+ {
+ curclient = XFD_FD(&savedAllSockets, i);
+ FD_ZERO(&tmask);
+ FD_SET(curclient, &tmask);
+ do {
+ r = Select (curclient + 1, &tmask, NULL, NULL, &notime);
+ } while (r == SOCKET_ERROR && (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEWOULDBLOCK));
+ if (r < 0)
+ if (GetConnectionTranslation(curclient) > 0)
+ CloseDownClient(clients[GetConnectionTranslation(curclient)]);
+ }
+ XFD_COPYSET(&AllClients, &savedAllSockets);
+ }
+#endif
+}
+
+
+/*****************
+ * CloseDownConnection
+ * Delete client from AllClients and free resources
+ *****************/
+
+void
+CloseDownConnection(ClientPtr client)
+{
+ OsCommPtr oc = (OsCommPtr)client->osPrivate;
+
+ if (FlushCallback)
+ CallCallbacks(&FlushCallback, NULL);
+
+#ifdef DEBUG
+ ErrorF("CloseDownConnection: client index = %d, socket fd = %d\n",
+ client->index, oc->fd);
+#endif
+ if (oc->output && oc->output->count)
+ FlushClient(client, oc, (char *)NULL, 0);
+#ifdef XDMCP
+ XdmcpCloseDisplay(oc->fd);
+#endif
+ CloseDownFileDescriptor(oc);
+ FreeOsBuffers(oc);
+ free(client->osPrivate);
+ client->osPrivate = (pointer)NULL;
+ if (auditTrailLevel > 1)
+ AuditF("client %d disconnected\n", client->index);
+}
+
+void
+AddGeneralSocket(int fd)
+{
+ FD_SET(fd, &AllSockets);
+ if (GrabInProgress)
+ FD_SET(fd, &SavedAllSockets);
+}
+
+void
+AddEnabledDevice(int fd)
+{
+ FD_SET(fd, &EnabledDevices);
+ AddGeneralSocket(fd);
+}
+
+void
+RemoveGeneralSocket(int fd)
+{
+ FD_CLR(fd, &AllSockets);
+ if (GrabInProgress)
+ FD_CLR(fd, &SavedAllSockets);
+}
+
+void
+RemoveEnabledDevice(int fd)
+{
+ FD_CLR(fd, &EnabledDevices);
+ RemoveGeneralSocket(fd);
+}
+
+/*****************
+ * OnlyListenToOneClient:
+ * Only accept requests from one client. Continue to handle new
+ * connections, but don't take any protocol requests from the new
+ * ones. Note that if GrabInProgress is set, EstablishNewConnections
+ * needs to put new clients into SavedAllSockets and SavedAllClients.
+ * Note also that there is no timeout for this in the protocol.
+ * This routine is "undone" by ListenToAllClients()
+ *****************/
+
+int
+OnlyListenToOneClient(ClientPtr client)
+{
+ OsCommPtr oc = (OsCommPtr)client->osPrivate;
+ int rc, connection = oc->fd;
+
+ rc = XaceHook(XACE_SERVER_ACCESS, client, DixGrabAccess);
+ if (rc != Success)
+ return rc;
+
+ if (! GrabInProgress)
+ {
+ XFD_COPYSET(&ClientsWithInput, &SavedClientsWithInput);
+ XFD_ANDSET(&ClientsWithInput,
+ &ClientsWithInput, &GrabImperviousClients);
+ if (FD_ISSET(connection, &SavedClientsWithInput))
+ {
+ FD_CLR(connection, &SavedClientsWithInput);
+ FD_SET(connection, &ClientsWithInput);
+ }
+ XFD_UNSET(&SavedClientsWithInput, &GrabImperviousClients);
+ XFD_COPYSET(&AllSockets, &SavedAllSockets);
+ XFD_COPYSET(&AllClients, &SavedAllClients);
+ XFD_UNSET(&AllSockets, &AllClients);
+ XFD_ANDSET(&AllClients, &AllClients, &GrabImperviousClients);
+ FD_SET(connection, &AllClients);
+ XFD_ORSET(&AllSockets, &AllSockets, &AllClients);
+ GrabInProgress = client->index;
+ }
+ return rc;
+}
+
+/****************
+ * ListenToAllClients:
+ * Undoes OnlyListentToOneClient()
+ ****************/
+
+void
+ListenToAllClients(void)
+{
+ if (GrabInProgress)
+ {
+ XFD_ORSET(&AllSockets, &AllSockets, &SavedAllSockets);
+ XFD_ORSET(&AllClients, &AllClients, &SavedAllClients);
+ XFD_ORSET(&ClientsWithInput, &ClientsWithInput, &SavedClientsWithInput);
+ GrabInProgress = 0;
+ }
+}
+
+/****************
+ * IgnoreClient
+ * Removes one client from input masks.
+ * Must have cooresponding call to AttendClient.
+ ****************/
+
+void
+IgnoreClient (ClientPtr client)
+{
+ OsCommPtr oc = (OsCommPtr)client->osPrivate;
+ int connection = oc->fd;
+
+ client->ignoreCount++;
+ if (client->ignoreCount > 1)
+ return;
+
+ isItTimeToYield = TRUE;
+ if (!GrabInProgress || FD_ISSET(connection, &AllClients))
+ {
+ if (FD_ISSET (connection, &ClientsWithInput))
+ FD_SET(connection, &IgnoredClientsWithInput);
+ else
+ FD_CLR(connection, &IgnoredClientsWithInput);
+ FD_CLR(connection, &ClientsWithInput);
+ FD_CLR(connection, &AllSockets);
+ FD_CLR(connection, &AllClients);
+ FD_CLR(connection, &LastSelectMask);
+ }
+ else
+ {
+ if (FD_ISSET (connection, &SavedClientsWithInput))
+ FD_SET(connection, &IgnoredClientsWithInput);
+ else
+ FD_CLR(connection, &IgnoredClientsWithInput);
+ FD_CLR(connection, &SavedClientsWithInput);
+ FD_CLR(connection, &SavedAllSockets);
+ FD_CLR(connection, &SavedAllClients);
+ }
+}
+
+/****************
+ * AttendClient
+ * Adds one client back into the input masks.
+ ****************/
+
+void
+AttendClient (ClientPtr client)
+{
+ OsCommPtr oc = (OsCommPtr)client->osPrivate;
+ int connection = oc->fd;
+
+ client->ignoreCount--;
+ if (client->ignoreCount)
+ return;
+
+ if (!GrabInProgress || GrabInProgress == client->index ||
+ FD_ISSET(connection, &GrabImperviousClients))
+ {
+ FD_SET(connection, &AllClients);
+ FD_SET(connection, &AllSockets);
+ FD_SET(connection, &LastSelectMask);
+ if (FD_ISSET (connection, &IgnoredClientsWithInput))
+ FD_SET(connection, &ClientsWithInput);
+ }
+ else
+ {
+ FD_SET(connection, &SavedAllClients);
+ FD_SET(connection, &SavedAllSockets);
+ if (FD_ISSET(connection, &IgnoredClientsWithInput))
+ FD_SET(connection, &SavedClientsWithInput);
+ }
+}
+
+/* make client impervious to grabs; assume only executing client calls this */
+
+void
+MakeClientGrabImpervious(ClientPtr client)
+{
+ OsCommPtr oc = (OsCommPtr)client->osPrivate;
+ int connection = oc->fd;
+
+ FD_SET(connection, &GrabImperviousClients);
+
+ if (ServerGrabCallback)
+ {
+ ServerGrabInfoRec grabinfo;
+ grabinfo.client = client;
+ grabinfo.grabstate = CLIENT_IMPERVIOUS;
+ CallCallbacks(&ServerGrabCallback, &grabinfo);
+ }
+}
+
+/* make client pervious to grabs; assume only executing client calls this */
+
+void
+MakeClientGrabPervious(ClientPtr client)
+{
+ OsCommPtr oc = (OsCommPtr)client->osPrivate;
+ int connection = oc->fd;
+
+ FD_CLR(connection, &GrabImperviousClients);
+ if (GrabInProgress && (GrabInProgress != client->index))
+ {
+ if (FD_ISSET(connection, &ClientsWithInput))
+ {
+ FD_SET(connection, &SavedClientsWithInput);
+ FD_CLR(connection, &ClientsWithInput);
+ }
+ FD_CLR(connection, &AllSockets);
+ FD_CLR(connection, &AllClients);
+ isItTimeToYield = TRUE;
+ }
+
+ if (ServerGrabCallback)
+ {
+ ServerGrabInfoRec grabinfo;
+ grabinfo.client = client;
+ grabinfo.grabstate = CLIENT_PERVIOUS;
+ CallCallbacks(&ServerGrabCallback, &grabinfo);
+ }
+}
+
+#ifdef XQUARTZ
+/* Add a fd (from launchd) to our listeners */
+void ListenOnOpenFD(int fd, int noxauth) {
+ char port[256];
+ XtransConnInfo ciptr;
+ const char *display_env = getenv("DISPLAY");
+
+ if(display_env && (strncmp(display_env, "/tmp/launch", 11) == 0)) {
+ /* Make the path the launchd socket if our DISPLAY is set right */
+ strcpy(port, display_env);
+ } else {
+ /* Just some default so things don't break and die. */
+ sprintf(port, ":%d", atoi(display));
+ }
+
+ /* Make our XtransConnInfo
+ * TRANS_SOCKET_LOCAL_INDEX = 5 from Xtrans.c
+ */
+ ciptr = _XSERVTransReopenCOTSServer(5, fd, port);
+ if(ciptr == NULL) {
+ ErrorF("Got NULL while trying to Reopen launchd port.\n");
+ return;
+ }
+
+ if(noxauth)
+ ciptr->flags = ciptr->flags | TRANS_NOXAUTH;
+
+ /* Allocate space to store it */
+ ListenTransFds = (int *) realloc(ListenTransFds, (ListenTransCount + 1) * sizeof (int));
+ ListenTransConns = (XtransConnInfo *) realloc(ListenTransConns, (ListenTransCount + 1) * sizeof (XtransConnInfo));
+
+ /* Store it */
+ ListenTransConns[ListenTransCount] = ciptr;
+ ListenTransFds[ListenTransCount] = fd;
+
+ FD_SET(fd, &WellKnownConnections);
+ FD_SET(fd, &AllSockets);
+
+ /* Increment the count */
+ ListenTransCount++;
+
+ /* This *might* not be needed... /shrug */
+ ResetAuthorization();
+ ResetHosts(display);
+#ifdef XDMCP
+ XdmcpReset();
+#endif
+}
+
+#endif
diff --git a/xorg-server/os/io.c b/xorg-server/os/io.c
index a26b394b9..d2eb04649 100644
--- a/xorg-server/os/io.c
+++ b/xorg-server/os/io.c
@@ -952,6 +952,7 @@ FlushClient(ClientPtr who, OsCommPtr oc, const void *__extraBuf, int extraCount)
/* 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. */
+ errno=0;
FD_SET(connection, &ClientsWriteBlocked);
AnyClientsWriteBlocked = TRUE;
diff --git a/xorg-server/os/log.c b/xorg-server/os/log.c
index adcf16244..8b5d24b94 100644
--- a/xorg-server/os/log.c
+++ b/xorg-server/os/log.c
@@ -95,8 +95,14 @@ OR PERFORMANCE OF THIS SOFTWARE.
#ifdef WIN32
#include <process.h>
+#ifndef _MSC_VER
#define getpid(x) _getpid(x)
#endif
+#endif
+
+#ifdef _MSC_VER
+#define S_ISREG(m) (((m)&_S_IFMT) == _S_IFREG)
+#endif
#ifdef XF86BIGFONT
#include "xf86bigfontsrv.h"
@@ -261,7 +267,7 @@ LogSetParameter(LogParameter param, int value)
void
LogVWrite(int verb, const char *f, va_list args)
{
- static char tmpBuffer[1024];
+ char tmpBuffer[1024];
int len = 0;
static Bool newline = TRUE;
@@ -278,7 +284,8 @@ LogVWrite(int verb, const char *f, va_list args)
* stream(s).
*/
if (verb < 0 || logFileVerbosity >= verb || logVerbosity >= verb) {
- vsnprintf(tmpBuffer, sizeof(tmpBuffer), f, args);
+ vsnprintf(tmpBuffer, sizeof(tmpBuffer)-1, f, args);
+ tmpBuffer[sizeof(tmpBuffer)-1]=0;
len = strlen(tmpBuffer);
}
newline = (tmpBuffer[len-1] == '\n');
@@ -503,7 +510,7 @@ VAuditF(const char *f, va_list args)
if (auditTimer != NULL)
TimerForce(auditTimer);
ErrorF("%s%s", prefix != NULL ? prefix : "", buf);
- strlcpy(oldbuf, buf, sizeof(oldbuf));
+ strncpy(oldbuf, buf, sizeof(oldbuf));
oldlen = len;
nrepeat = 0;
auditTimer = TimerSet(auditTimer, 0, AUDIT_TIMEOUT, AuditFlush, NULL);
@@ -511,6 +518,8 @@ VAuditF(const char *f, va_list args)
free(prefix);
}
+extern char g_FatalErrorMessage[1024];
+
void
FatalError(const char *f, ...)
{
@@ -526,6 +535,9 @@ FatalError(const char *f, ...)
#ifdef __APPLE__
(void)vsnprintf(__crashreporter_info_buff__, sizeof(__crashreporter_info_buff__), f, args);
#endif
+#ifdef WIN32
+ vsnprintf(g_FatalErrorMessage, 1024, f, args);
+#endif
VErrorF(f, args);
va_end(args);
ErrorF("\n");
diff --git a/xorg-server/os/makefile b/xorg-server/os/makefile
new file mode 100644
index 000000000..779a1c95d
--- /dev/null
+++ b/xorg-server/os/makefile
@@ -0,0 +1,49 @@
+LIBRARY=libos
+
+ifeq ($(DEBUG),1)
+DEFINES += XSERVER_DTRACE
+endif
+SECURE_RPC=1
+XDMCP=1
+NEED_STRLCAT=1
+
+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 \
+ client.c \
+ connection.c \
+ io.c \
+ mitauth.c \
+ oscolor.c \
+ osdep.h \
+ osinit.c \
+ utils.c \
+ strcasecmp.c \
+ strcasestr.c \
+ xdmauth.c \
+ xsha1.c \
+ xstrans.c \
+ xprintf.c \
+ $(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
+
+CSRCS = $(filter %.c,$(libos_la_SOURCES))
+
+
diff --git a/xorg-server/os/oscolor.c b/xorg-server/os/oscolor.c
index 7f6b93880..4e1513f53 100644
--- a/xorg-server/os/oscolor.c
+++ b/xorg-server/os/oscolor.c
@@ -49,6 +49,10 @@ SOFTWARE.
#include <dix-config.h>
#endif
+#ifdef _MSC_VER
+#define strncasecmp _strnicmp
+#endif
+
#include <X11/keysym.h>
#include "os.h"
diff --git a/xorg-server/os/osinit.c b/xorg-server/os/osinit.c
index 69e4933e6..2080cb782 100644
--- a/xorg-server/os/osinit.c
+++ b/xorg-server/os/osinit.c
@@ -155,6 +155,7 @@ OsInit(void)
char fname[PATH_MAX];
if (!been_here) {
+#ifndef _MSC_VER
struct sigaction act, oact;
int i;
int siglist[] = { SIGSEGV, SIGQUIT, SIGILL, SIGFPE, SIGBUS,
@@ -198,7 +199,7 @@ OsInit(void)
int failure_signal = SIGQUIT;
dlinfo(RTLD_SELF, RTLD_DI_SETSIGNAL, &failure_signal);
#endif
-
+#endif
#if !defined(__CYGWIN__)
fclose(stdin);
fclose(stdout);
@@ -237,8 +238,10 @@ OsInit(void)
#endif
}
+#ifndef _MSC_VER
if (getpgrp () == 0)
setpgid (0, 0);
+#endif
#ifdef RLIMIT_DATA
if (limitDataSpace >= 0)
diff --git a/xorg-server/os/utils.c b/xorg-server/os/utils.c
index 36cb46f11..522253a89 100644
--- a/xorg-server/os/utils.c
+++ b/xorg-server/os/utils.c
@@ -1,1814 +1,1868 @@
-/*
-
-Copyright 1987, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall
-not be used in advertising or otherwise to promote the sale, use or
-other dealings in this Software without prior written authorization
-from The Open Group.
-
-
-Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
-Copyright 1994 Quarterdeck Office Systems.
-
- All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the names of Digital and
-Quarterdeck not be used in advertising or publicity pertaining to
-distribution of the software without specific, written prior
-permission.
-
-DIGITAL AND QUARTERDECK DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
-SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
-FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT
-OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
-OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
-OR PERFORMANCE OF THIS SOFTWARE.
-
-*/
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#ifdef __CYGWIN__
-#include <stdlib.h>
-#include <signal.h>
-/*
- Sigh... We really need a prototype for this to know it is stdcall,
- but #include-ing <windows.h> here is not a good idea...
-*/
-__stdcall unsigned long GetTickCount(void);
-#endif
-
-#if defined(WIN32) && !defined(__CYGWIN__)
-#include <X11/Xwinsock.h>
-#endif
-#include <X11/Xos.h>
-#include <stdio.h>
-#include <time.h>
-#if !defined(WIN32) || !defined(__MINGW32__)
-#include <sys/time.h>
-#include <sys/resource.h>
-#endif
-#include "misc.h"
-#include <X11/X.h>
-#define XSERV_t
-#define TRANS_SERVER
-#define TRANS_REOPEN
-#include <X11/Xtrans/Xtrans.h>
-#include "input.h"
-#include "dixfont.h"
-#include "osdep.h"
-#include "extension.h"
-#ifdef X_POSIX_C_SOURCE
-#define _POSIX_C_SOURCE X_POSIX_C_SOURCE
-#include <signal.h>
-#undef _POSIX_C_SOURCE
-#else
-#if defined(_POSIX_SOURCE)
-#include <signal.h>
-#else
-#define _POSIX_SOURCE
-#include <signal.h>
-#undef _POSIX_SOURCE
-#endif
-#endif
-#ifndef WIN32
-#include <sys/wait.h>
-#endif
-#if !defined(SYSV) && !defined(WIN32)
-#include <sys/resource.h>
-#endif
-#include <sys/stat.h>
-#include <ctype.h> /* for isspace */
-#include <stdarg.h>
-
-#include <stdlib.h> /* for malloc() */
-
-#if defined(TCPCONN) || defined(STREAMSCONN)
-# ifndef WIN32
-# include <netdb.h>
-# endif
-#endif
-
-#include "opaque.h"
-
-#include "dixstruct.h"
-
-#include "xkbsrv.h"
-
-#include "picture.h"
-
-Bool noTestExtensions;
-#ifdef COMPOSITE
-Bool noCompositeExtension = FALSE;
-#endif
-
-#ifdef DAMAGE
-Bool noDamageExtension = FALSE;
-#endif
-#ifdef DBE
-Bool noDbeExtension = FALSE;
-#endif
-#ifdef DPMSExtension
-Bool noDPMSExtension = FALSE;
-#endif
-#ifdef GLXEXT
-Bool noGlxExtension = FALSE;
-Bool noGlxVisualInit = FALSE;
-#endif
-#ifdef SCREENSAVER
-Bool noScreenSaverExtension = FALSE;
-#endif
-#ifdef MITSHM
-Bool noMITShmExtension = FALSE;
-#endif
-#ifdef RANDR
-Bool noRRExtension = FALSE;
-#endif
-Bool noRenderExtension = FALSE;
-#ifdef XCSECURITY
-Bool noSecurityExtension = FALSE;
-#endif
-#ifdef RES
-Bool noResExtension = FALSE;
-#endif
-#ifdef XF86BIGFONT
-Bool noXFree86BigfontExtension = FALSE;
-#endif
-#ifdef XFreeXDGA
-Bool noXFree86DGAExtension = FALSE;
-#endif
-#ifdef XF86DRI
-Bool noXFree86DRIExtension = FALSE;
-#endif
-#ifdef XF86VIDMODE
-Bool noXFree86VidModeExtension = FALSE;
-#endif
-#ifdef XFIXES
-Bool noXFixesExtension = FALSE;
-#endif
-#ifdef PANORAMIX
-/* Xinerama is disabled by default unless enabled via +xinerama */
-Bool noPanoramiXExtension = TRUE;
-#endif
-#ifdef XSELINUX
-Bool noSELinuxExtension = FALSE;
-int selinuxEnforcingState = SELINUX_MODE_DEFAULT;
-#endif
-#ifdef XV
-Bool noXvExtension = FALSE;
-#endif
-#ifdef DRI2
-Bool noDRI2Extension = FALSE;
-#endif
-
-Bool noGEExtension = FALSE;
-
-#define X_INCLUDE_NETDB_H
-#include <X11/Xos_r.h>
-
-#include <errno.h>
-
-Bool CoreDump;
-
-#ifdef PANORAMIX
-Bool PanoramiXExtensionDisabledHack = FALSE;
-#endif
-
-int auditTrailLevel = 1;
-
-#if defined(SVR4) || defined(__linux__) || defined(CSRG_BASED)
-#define HAS_SAVED_IDS_AND_SETEUID
-#endif
-
-OsSigHandlerPtr
-OsSignal(int sig, OsSigHandlerPtr handler)
-{
- struct sigaction act, oact;
-
- sigemptyset(&act.sa_mask);
- if (handler != SIG_IGN)
- sigaddset(&act.sa_mask, sig);
- act.sa_flags = 0;
- act.sa_handler = handler;
- if (sigaction(sig, &act, &oact))
- perror("sigaction");
- return oact.sa_handler;
-}
-
-/*
- * Explicit support for a server lock file like the ones used for UUCP.
- * For architectures with virtual terminals that can run more than one
- * server at a time. This keeps the servers from stomping on each other
- * if the user forgets to give them different display numbers.
- */
-#define LOCK_DIR "/tmp"
-#define LOCK_TMP_PREFIX "/.tX"
-#define LOCK_PREFIX "/.X"
-#define LOCK_SUFFIX "-lock"
-
-static Bool StillLocking = FALSE;
-static char LockFile[PATH_MAX];
-static Bool nolock = FALSE;
-
-/*
- * LockServer --
- * Check if the server lock file exists. If so, check if the PID
- * contained inside is valid. If so, then die. Otherwise, create
- * the lock file containing the PID.
- */
-void
-LockServer(void)
-{
- char tmp[PATH_MAX], pid_str[12];
- int lfd, i, haslock, l_pid, t;
- char *tmppath = NULL;
- int len;
- char port[20];
-
- if (nolock) return;
- /*
- * Path names
- */
- tmppath = LOCK_DIR;
-
- sprintf(port, "%d", atoi(display));
- len = strlen(LOCK_PREFIX) > strlen(LOCK_TMP_PREFIX) ? strlen(LOCK_PREFIX) :
- strlen(LOCK_TMP_PREFIX);
- len += strlen(tmppath) + strlen(port) + strlen(LOCK_SUFFIX) + 1;
- if (len > sizeof(LockFile))
- FatalError("Display name `%s' is too long\n", port);
- (void)sprintf(tmp, "%s" LOCK_TMP_PREFIX "%s" LOCK_SUFFIX, tmppath, port);
- (void)sprintf(LockFile, "%s" LOCK_PREFIX "%s" LOCK_SUFFIX, tmppath, port);
-
- /*
- * Create a temporary file containing our PID. Attempt three times
- * to create the file.
- */
- StillLocking = TRUE;
- i = 0;
- do {
- i++;
- lfd = open(tmp, O_CREAT | O_EXCL | O_WRONLY, 0644);
- if (lfd < 0)
- sleep(2);
- else
- break;
- } while (i < 3);
- if (lfd < 0) {
- unlink(tmp);
- i = 0;
- do {
- i++;
- lfd = open(tmp, O_CREAT | O_EXCL | O_WRONLY, 0644);
- if (lfd < 0)
- sleep(2);
- else
- break;
- } while (i < 3);
- }
- if (lfd < 0)
- FatalError("Could not create lock file in %s\n", tmp);
- (void) sprintf(pid_str, "%10ld\n", (long)getpid());
- (void) write(lfd, pid_str, 11);
- (void) chmod(tmp, 0444);
- (void) close(lfd);
-
- /*
- * OK. Now the tmp file exists. Try three times to move it in place
- * for the lock.
- */
- i = 0;
- haslock = 0;
- while ((!haslock) && (i++ < 3)) {
- haslock = (link(tmp,LockFile) == 0);
- if (haslock) {
- /*
- * We're done.
- */
- break;
- }
- else {
- /*
- * Read the pid from the existing file
- */
- lfd = open(LockFile, O_RDONLY);
- if (lfd < 0) {
- unlink(tmp);
- FatalError("Can't read lock file %s\n", LockFile);
- }
- pid_str[0] = '\0';
- if (read(lfd, pid_str, 11) != 11) {
- /*
- * Bogus lock file.
- */
- unlink(LockFile);
- close(lfd);
- continue;
- }
- pid_str[11] = '\0';
- sscanf(pid_str, "%d", &l_pid);
- close(lfd);
-
- /*
- * Now try to kill the PID to see if it exists.
- */
- errno = 0;
- t = kill(l_pid, 0);
- if ((t< 0) && (errno == ESRCH)) {
- /*
- * Stale lock file.
- */
- unlink(LockFile);
- continue;
- }
- else if (((t < 0) && (errno == EPERM)) || (t == 0)) {
- /*
- * Process is still active.
- */
- unlink(tmp);
- FatalError("Server is already active for display %s\n%s %s\n%s\n",
- port, "\tIf this server is no longer running, remove",
- LockFile, "\tand start again.");
- }
- }
- }
- unlink(tmp);
- if (!haslock)
- FatalError("Could not create server lock file: %s\n", LockFile);
- StillLocking = FALSE;
-}
-
-/*
- * UnlockServer --
- * Remove the server lock file.
- */
-void
-UnlockServer(void)
-{
- if (nolock) return;
-
- if (!StillLocking){
-
- (void) unlink(LockFile);
- }
-}
-
-/* Force connections to close on SIGHUP from init */
-
-void
-AutoResetServer (int sig)
-{
- int olderrno = errno;
-
- dispatchException |= DE_RESET;
- isItTimeToYield = TRUE;
- errno = olderrno;
-}
-
-/* Force connections to close and then exit on SIGTERM, SIGINT */
-
-void
-GiveUp(int sig)
-{
- int olderrno = errno;
-
- dispatchException |= DE_TERMINATE;
- isItTimeToYield = TRUE;
- errno = olderrno;
-}
-
-#if (defined WIN32 && defined __MINGW32__) || defined(__CYGWIN__)
-CARD32
-GetTimeInMillis (void)
-{
- return GetTickCount ();
-}
-#else
-CARD32
-GetTimeInMillis(void)
-{
- struct timeval tv;
-
-#ifdef MONOTONIC_CLOCK
- struct timespec tp;
- static clockid_t clockid;
- if (!clockid) {
-#ifdef CLOCK_MONOTONIC_COARSE
- if (clock_getres(CLOCK_MONOTONIC_COARSE, &tp) == 0 &&
- (tp.tv_nsec / 1000) <= 1000 &&
- clock_gettime(CLOCK_MONOTONIC_COARSE, &tp) == 0)
- clockid = CLOCK_MONOTONIC_COARSE;
- else
-#endif
- if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
- clockid = CLOCK_MONOTONIC;
- else
- clockid = ~0L;
- }
- if (clockid != ~0L && clock_gettime(clockid, &tp) == 0)
- return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L);
-#endif
-
- X_GETTIMEOFDAY(&tv);
- return(tv.tv_sec * 1000) + (tv.tv_usec / 1000);
-}
-#endif
-
-void
-AdjustWaitForDelay (pointer waitTime, unsigned long newdelay)
-{
- static struct timeval delay_val;
- struct timeval **wt = (struct timeval **) waitTime;
- unsigned long olddelay;
-
- if (*wt == NULL)
- {
- delay_val.tv_sec = newdelay / 1000;
- delay_val.tv_usec = 1000 * (newdelay % 1000);
- *wt = &delay_val;
- }
- else
- {
- olddelay = (*wt)->tv_sec * 1000 + (*wt)->tv_usec / 1000;
- if (newdelay < olddelay)
- {
- (*wt)->tv_sec = newdelay / 1000;
- (*wt)->tv_usec = 1000 * (newdelay % 1000);
- }
- }
-}
-
-void UseMsg(void)
-{
- ErrorF("use: X [:<display>] [option]\n");
- ErrorF("-a # default pointer acceleration (factor)\n");
- ErrorF("-ac disable access control restrictions\n");
- ErrorF("-audit int set audit trail level\n");
- ErrorF("-auth file select authorization file\n");
- ErrorF("-br create root window with black background\n");
- ErrorF("+bs enable any backing store support\n");
- ErrorF("-bs disable any backing store support\n");
- ErrorF("-c turns off key-click\n");
- ErrorF("c # key-click volume (0-100)\n");
- ErrorF("-cc int default color visual class\n");
- ErrorF("-nocursor disable the cursor\n");
- ErrorF("-core generate core dump on fatal error\n");
- ErrorF("-dpi int screen resolution in dots per inch\n");
-#ifdef DPMSExtension
- ErrorF("-dpms disables VESA DPMS monitor control\n");
-#endif
- ErrorF("-deferglyphs [none|all|16] defer loading of [no|all|16-bit] glyphs\n");
- ErrorF("-f # bell base (0-100)\n");
- ErrorF("-fc string cursor font\n");
- ErrorF("-fn string default font name\n");
- ErrorF("-fp string default font path\n");
- ErrorF("-help prints message with these options\n");
- ErrorF("-I ignore all remaining arguments\n");
-#ifdef RLIMIT_DATA
- ErrorF("-ld int limit data space to N Kb\n");
-#endif
-#ifdef RLIMIT_NOFILE
- ErrorF("-lf int limit number of open files to N\n");
-#endif
-#ifdef RLIMIT_STACK
- ErrorF("-ls int limit stack space to N Kb\n");
-#endif
- ErrorF("-nolock disable the locking mechanism\n");
- ErrorF("-nolisten string don't listen on protocol\n");
- ErrorF("-noreset don't reset after last client exists\n");
- ErrorF("-background [none] create root window with no background\n");
- ErrorF("-reset reset after last client exists\n");
- ErrorF("-p # screen-saver pattern duration (minutes)\n");
- ErrorF("-pn accept failure to listen on all ports\n");
- ErrorF("-nopn reject failure to listen on all ports\n");
- ErrorF("-r turns off auto-repeat\n");
- ErrorF("r turns on auto-repeat \n");
- ErrorF("-render [default|mono|gray|color] set render color alloc policy\n");
- ErrorF("-retro start with classic stipple and cursor\n");
- ErrorF("-s # screen-saver timeout (minutes)\n");
- ErrorF("-t # default pointer threshold (pixels/t)\n");
- ErrorF("-terminate terminate at server reset\n");
- ErrorF("-to # connection time out\n");
- ErrorF("-tst disable testing extensions\n");
- ErrorF("ttyxx server started from init on /dev/ttyxx\n");
- ErrorF("v video blanking for screen-saver\n");
- ErrorF("-v screen-saver without video blanking\n");
- ErrorF("-wm WhenMapped default backing-store\n");
- ErrorF("-wr create root window with white background\n");
- ErrorF("-maxbigreqsize set maximal bigrequest size \n");
-#ifdef PANORAMIX
- ErrorF("+xinerama Enable XINERAMA extension\n");
- ErrorF("-xinerama Disable XINERAMA extension\n");
-#endif
- ErrorF("-dumbSched Disable smart scheduling, enable old behavior\n");
- ErrorF("-schedInterval int Set scheduler interval in msec\n");
- ErrorF("-sigstop Enable SIGSTOP based startup\n");
- ErrorF("+extension name Enable extension\n");
- ErrorF("-extension name Disable extension\n");
-#ifdef XDMCP
- XdmcpUseMsg();
-#endif
- XkbUseMsg();
- ddxUseMsg();
-}
-
-/* This function performs a rudimentary sanity check
- * on the display name passed in on the command-line,
- * since this string is used to generate filenames.
- * It is especially important that the display name
- * not contain a "/" and not start with a "-".
- * --kvajk
- */
-static int
-VerifyDisplayName(const char *d)
-{
- if ( d == (char *)0 ) return 0; /* null */
- if ( *d == '\0' ) return 0; /* empty */
- if ( *d == '-' ) return 0; /* could be confused for an option */
- if ( *d == '.' ) return 0; /* must not equal "." or ".." */
- if ( strchr(d, '/') != (char *)0 ) return 0; /* very important!!! */
- return 1;
-}
-
-/*
- * This function parses the command line. Handles device-independent fields
- * and allows ddx to handle additional fields. It is not allowed to modify
- * argc or any of the strings pointed to by argv.
- */
-void
-ProcessCommandLine(int argc, char *argv[])
-{
- int i, skip;
-
- defaultKeyboardControl.autoRepeat = TRUE;
-
-#ifdef NO_PART_NET
- PartialNetwork = FALSE;
-#else
- PartialNetwork = TRUE;
-#endif
-
- for ( i = 1; i < argc; i++ )
- {
- /* call ddx first, so it can peek/override if it wants */
- if((skip = ddxProcessArgument(argc, argv, i)))
- {
- i += (skip - 1);
- }
- else if(argv[i][0] == ':')
- {
- /* initialize display */
- display = argv[i];
- display++;
- if( ! VerifyDisplayName( display ) ) {
- ErrorF("Bad display name: %s\n", display);
- UseMsg();
- FatalError("Bad display name, exiting: %s\n", display);
- }
- }
- else if ( strcmp( argv[i], "-a") == 0)
- {
- if(++i < argc)
- defaultPointerControl.num = atoi(argv[i]);
- else
- UseMsg();
- }
- else if ( strcmp( argv[i], "-ac") == 0)
- {
- defeatAccessControl = TRUE;
- }
- else if ( strcmp( argv[i], "-audit") == 0)
- {
- if(++i < argc)
- auditTrailLevel = atoi(argv[i]);
- else
- UseMsg();
- }
- else if ( strcmp( argv[i], "-auth") == 0)
- {
- if(++i < argc)
- InitAuthorization (argv[i]);
- else
- UseMsg();
- }
- else if ( strcmp( argv[i], "-br") == 0) ; /* default */
- else if ( strcmp( argv[i], "+bs") == 0)
- enableBackingStore = TRUE;
- else if ( strcmp( argv[i], "-bs") == 0)
- disableBackingStore = TRUE;
- else if ( strcmp( argv[i], "c") == 0)
- {
- if(++i < argc)
- defaultKeyboardControl.click = atoi(argv[i]);
- else
- UseMsg();
- }
- else if ( strcmp( argv[i], "-c") == 0)
- {
- defaultKeyboardControl.click = 0;
- }
- else if ( strcmp( argv[i], "-cc") == 0)
- {
- if(++i < argc)
- defaultColorVisualClass = atoi(argv[i]);
- else
- UseMsg();
- }
- else if ( strcmp( argv[i], "-core") == 0)
- {
-#if !defined(WIN32) || !defined(__MINGW32__)
- struct rlimit core_limit;
- getrlimit (RLIMIT_CORE, &core_limit);
- core_limit.rlim_cur = core_limit.rlim_max;
- setrlimit (RLIMIT_CORE, &core_limit);
-#endif
- CoreDump = TRUE;
- }
- else if ( strcmp( argv[i], "-nocursor") == 0)
- {
- EnableCursor = FALSE;
- }
- else if ( strcmp( argv[i], "-dpi") == 0)
- {
- if(++i < argc)
- monitorResolution = atoi(argv[i]);
- else
- UseMsg();
- }
-#ifdef DPMSExtension
- else if ( strcmp( argv[i], "dpms") == 0)
- /* ignored for compatibility */ ;
- else if ( strcmp( argv[i], "-dpms") == 0)
- DPMSDisabledSwitch = TRUE;
-#endif
- else if ( strcmp( argv[i], "-deferglyphs") == 0)
- {
- if(++i >= argc || !ParseGlyphCachingMode(argv[i]))
- UseMsg();
- }
- else if ( strcmp( argv[i], "-f") == 0)
- {
- if(++i < argc)
- defaultKeyboardControl.bell = atoi(argv[i]);
- else
- UseMsg();
- }
- else if ( strcmp( argv[i], "-fc") == 0)
- {
- if(++i < argc)
- defaultCursorFont = argv[i];
- else
- UseMsg();
- }
- else if ( strcmp( argv[i], "-fn") == 0)
- {
- if(++i < argc)
- defaultTextFont = argv[i];
- else
- UseMsg();
- }
- else if ( strcmp( argv[i], "-fp") == 0)
- {
- if(++i < argc)
- {
- defaultFontPath = argv[i];
- }
- else
- UseMsg();
- }
- else if ( strcmp( argv[i], "-help") == 0)
- {
- UseMsg();
- exit(0);
- }
- else if ( (skip=XkbProcessArguments(argc,argv,i))!=0 ) {
- if (skip>0)
- i+= skip-1;
- else UseMsg();
- }
-#ifdef RLIMIT_DATA
- else if ( strcmp( argv[i], "-ld") == 0)
- {
- if(++i < argc)
- {
- limitDataSpace = atoi(argv[i]);
- if (limitDataSpace > 0)
- limitDataSpace *= 1024;
- }
- else
- UseMsg();
- }
-#endif
-#ifdef RLIMIT_NOFILE
- else if ( strcmp( argv[i], "-lf") == 0)
- {
- if(++i < argc)
- limitNoFile = atoi(argv[i]);
- else
- UseMsg();
- }
-#endif
-#ifdef RLIMIT_STACK
- else if ( strcmp( argv[i], "-ls") == 0)
- {
- if(++i < argc)
- {
- limitStackSpace = atoi(argv[i]);
- if (limitStackSpace > 0)
- limitStackSpace *= 1024;
- }
- else
- UseMsg();
- }
-#endif
- else if ( strcmp ( argv[i], "-nolock") == 0)
- {
-#if !defined(WIN32) && !defined(__CYGWIN__)
- if (getuid() != 0)
- ErrorF("Warning: the -nolock option can only be used by root\n");
- else
-#endif
- nolock = TRUE;
- }
- else if ( strcmp( argv[i], "-nolisten") == 0)
- {
- if(++i < argc) {
- if (_XSERVTransNoListen(argv[i]))
- FatalError ("Failed to disable listen for %s transport",
- argv[i]);
- } else
- UseMsg();
- }
- else if ( strcmp( argv[i], "-noreset") == 0)
- {
- dispatchExceptionAtReset = 0;
- }
- else if ( strcmp( argv[i], "-reset") == 0)
- {
- dispatchExceptionAtReset = DE_RESET;
- }
- else if ( strcmp( argv[i], "-p") == 0)
- {
- if(++i < argc)
- defaultScreenSaverInterval = ((CARD32)atoi(argv[i])) *
- MILLI_PER_MIN;
- else
- UseMsg();
- }
- else if (strcmp(argv[i], "-pogo") == 0)
- {
- dispatchException = DE_TERMINATE;
- }
- else if ( strcmp( argv[i], "-pn") == 0)
- PartialNetwork = TRUE;
- else if ( strcmp( argv[i], "-nopn") == 0)
- PartialNetwork = FALSE;
- else if ( strcmp( argv[i], "r") == 0)
- defaultKeyboardControl.autoRepeat = TRUE;
- else if ( strcmp( argv[i], "-r") == 0)
- defaultKeyboardControl.autoRepeat = FALSE;
- else if ( strcmp( argv[i], "-retro") == 0)
- party_like_its_1989 = TRUE;
- else if ( strcmp( argv[i], "-s") == 0)
- {
- if(++i < argc)
- defaultScreenSaverTime = ((CARD32)atoi(argv[i])) *
- MILLI_PER_MIN;
- else
- UseMsg();
- }
- else if ( strcmp( argv[i], "-t") == 0)
- {
- if(++i < argc)
- defaultPointerControl.threshold = atoi(argv[i]);
- else
- UseMsg();
- }
- else if ( strcmp( argv[i], "-terminate") == 0)
- {
- dispatchExceptionAtReset = DE_TERMINATE;
- }
- else if ( strcmp( argv[i], "-to") == 0)
- {
- if(++i < argc)
- TimeOutValue = ((CARD32)atoi(argv[i])) * MILLI_PER_SECOND;
- else
- UseMsg();
- }
- else if ( strcmp( argv[i], "-tst") == 0)
- {
- noTestExtensions = TRUE;
- }
- else if ( strcmp( argv[i], "v") == 0)
- defaultScreenSaverBlanking = PreferBlanking;
- else if ( strcmp( argv[i], "-v") == 0)
- defaultScreenSaverBlanking = DontPreferBlanking;
- else if ( strcmp( argv[i], "-wm") == 0)
- defaultBackingStore = WhenMapped;
- else if ( strcmp( argv[i], "-wr") == 0)
- whiteRoot = TRUE;
- else if ( strcmp( argv[i], "-background") == 0) {
- if(++i < argc) {
- if (!strcmp ( argv[i], "none"))
- bgNoneRoot = TRUE;
- else
- UseMsg();
- }
- }
- else if ( strcmp( argv[i], "-maxbigreqsize") == 0) {
- if(++i < argc) {
- long reqSizeArg = atol(argv[i]);
-
- /* Request size > 128MB does not make much sense... */
- if( reqSizeArg > 0L && reqSizeArg < 128L ) {
- maxBigRequestSize = (reqSizeArg * 1048576L) - 1L;
- }
- else
- {
- UseMsg();
- }
- }
- else
- {
- UseMsg();
- }
- }
-#ifdef PANORAMIX
- else if ( strcmp( argv[i], "+xinerama") == 0){
- noPanoramiXExtension = FALSE;
- }
- else if ( strcmp( argv[i], "-xinerama") == 0){
- noPanoramiXExtension = TRUE;
- }
- else if ( strcmp( argv[i], "-disablexineramaextension") == 0){
- PanoramiXExtensionDisabledHack = TRUE;
- }
-#endif
- else if ( strcmp( argv[i], "-I") == 0)
- {
- /* ignore all remaining arguments */
- break;
- }
- else if (strncmp (argv[i], "tty", 3) == 0)
- {
- /* init supplies us with this useless information */
- }
-#ifdef XDMCP
- else if ((skip = XdmcpOptions(argc, argv, i)) != i)
- {
- i = skip - 1;
- }
-#endif
- else if ( strcmp( argv[i], "-dumbSched") == 0)
- {
- SmartScheduleDisable = TRUE;
- }
- else if ( strcmp( argv[i], "-schedInterval") == 0)
- {
- if (++i < argc)
- {
- SmartScheduleInterval = atoi(argv[i]);
- SmartScheduleSlice = SmartScheduleInterval;
- }
- else
- UseMsg();
- }
- else if ( strcmp( argv[i], "-schedMax") == 0)
- {
- if (++i < argc)
- {
- SmartScheduleMaxSlice = atoi(argv[i]);
- }
- else
- UseMsg();
- }
- else if ( strcmp( argv[i], "-render" ) == 0)
- {
- if (++i < argc)
- {
- int policy = PictureParseCmapPolicy (argv[i]);
-
- if (policy != PictureCmapPolicyInvalid)
- PictureCmapPolicy = policy;
- else
- UseMsg ();
- }
- else
- UseMsg ();
- }
- else if ( strcmp( argv[i], "-sigstop") == 0)
- {
- RunFromSigStopParent = TRUE;
- }
- else if ( strcmp( argv[i], "+extension") == 0)
- {
- if (++i < argc)
- {
- if (!EnableDisableExtension(argv[i], TRUE))
- EnableDisableExtensionError(argv[i], TRUE);
- }
- else
- UseMsg();
- }
- else if ( strcmp( argv[i], "-extension") == 0)
- {
- if (++i < argc)
- {
- if (!EnableDisableExtension(argv[i], FALSE))
- EnableDisableExtensionError(argv[i], FALSE);
- }
- else
- UseMsg();
- }
- else
- {
- ErrorF("Unrecognized option: %s\n", argv[i]);
- UseMsg();
- FatalError("Unrecognized option: %s\n", argv[i]);
- }
- }
-}
-
-/* Implement a simple-minded font authorization scheme. The authorization
- name is "hp-hostname-1", the contents are simply the host name. */
-int
-set_font_authorizations(char **authorizations, int *authlen, pointer client)
-{
-#define AUTHORIZATION_NAME "hp-hostname-1"
-#if defined(TCPCONN) || defined(STREAMSCONN)
- static char *result = NULL;
- static char *p = NULL;
-
- if (p == NULL)
- {
- char hname[1024], *hnameptr;
- unsigned int len;
-#if defined(IPv6) && defined(AF_INET6)
- struct addrinfo hints, *ai = NULL;
-#else
- struct hostent *host;
-#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
- _Xgethostbynameparams hparams;
-#endif
-#endif
-
- gethostname(hname, 1024);
-#if defined(IPv6) && defined(AF_INET6)
- memset(&hints, 0, sizeof(hints));
- hints.ai_flags = AI_CANONNAME;
- if (getaddrinfo(hname, NULL, &hints, &ai) == 0) {
- hnameptr = ai->ai_canonname;
- } else {
- hnameptr = hname;
- }
-#else
- host = _XGethostbyname(hname, hparams);
- if (host == NULL)
- hnameptr = hname;
- else
- hnameptr = host->h_name;
-#endif
-
- len = strlen(hnameptr) + 1;
- result = malloc(len + sizeof(AUTHORIZATION_NAME) + 4);
-
- p = result;
- *p++ = sizeof(AUTHORIZATION_NAME) >> 8;
- *p++ = sizeof(AUTHORIZATION_NAME) & 0xff;
- *p++ = (len) >> 8;
- *p++ = (len & 0xff);
-
- memmove(p, AUTHORIZATION_NAME, sizeof(AUTHORIZATION_NAME));
- p += sizeof(AUTHORIZATION_NAME);
- memmove(p, hnameptr, len);
- p += len;
-#if defined(IPv6) && defined(AF_INET6)
- if (ai) {
- freeaddrinfo(ai);
- }
-#endif
- }
- *authlen = p - result;
- *authorizations = result;
- return 1;
-#else /* TCPCONN */
- return 0;
-#endif /* TCPCONN */
-}
-
-void *
-Xalloc(unsigned long amount)
-{
- /*
- * Xalloc used to return NULL when large amount of memory is requested. In
- * order to catch the buggy callers this warning has been added, slated to
- * removal by anyone who touches this code (or just looks at it) in 2011.
- *
- * -- Mikhail Gusarov
- */
- if ((long)amount <= 0)
- ErrorF("Warning: Xalloc: "
- "requesting unpleasantly large amount of memory: %lu bytes.\n",
- amount);
-
- return malloc(amount);
-}
-
-void *
-XNFalloc(unsigned long amount)
-{
- void *ptr = malloc(amount);
- if (!ptr)
- FatalError("Out of memory");
- return ptr;
-}
-
-void *
-Xcalloc(unsigned long amount)
-{
- return calloc(1, amount);
-}
-
-void *
-XNFcalloc(unsigned long amount)
-{
- void *ret = calloc(1, amount);
- if (!ret)
- FatalError("XNFcalloc: Out of memory");
- return ret;
-}
-
-void *
-Xrealloc(void *ptr, unsigned long amount)
-{
- /*
- * Xrealloc used to return NULL when large amount of memory is requested. In
- * order to catch the buggy callers this warning has been added, slated to
- * removal by anyone who touches this code (or just looks at it) in 2011.
- *
- * -- Mikhail Gusarov
- */
- if ((long)amount <= 0)
- ErrorF("Warning: Xrealloc: "
- "requesting unpleasantly large amount of memory: %lu bytes.\n",
- amount);
-
- return realloc(ptr, amount);
-}
-
-void *
-XNFrealloc(void *ptr, unsigned long amount)
-{
- void *ret = realloc(ptr, amount);
- if (!ret)
- FatalError("XNFrealloc: Out of memory");
- return ret;
-}
-
-void
-Xfree(void *ptr)
-{
- free(ptr);
-}
-
-
-char *
-Xstrdup(const char *s)
-{
- if (s == NULL)
- return NULL;
- return strdup(s);
-}
-
-char *
-XNFstrdup(const char *s)
-{
- char *ret;
-
- if (s == NULL)
- return NULL;
-
- ret = strdup(s);
- if (!ret)
- FatalError("XNFstrdup: Out of memory");
- return ret;
-}
-
-void
-SmartScheduleStopTimer (void)
-{
- struct itimerval timer;
-
- if (SmartScheduleDisable)
- return;
- timer.it_interval.tv_sec = 0;
- timer.it_interval.tv_usec = 0;
- timer.it_value.tv_sec = 0;
- timer.it_value.tv_usec = 0;
- (void) setitimer (ITIMER_REAL, &timer, 0);
-}
-
-void
-SmartScheduleStartTimer (void)
-{
- struct itimerval timer;
-
- if (SmartScheduleDisable)
- return;
- timer.it_interval.tv_sec = 0;
- timer.it_interval.tv_usec = SmartScheduleInterval * 1000;
- timer.it_value.tv_sec = 0;
- timer.it_value.tv_usec = SmartScheduleInterval * 1000;
- setitimer (ITIMER_REAL, &timer, 0);
-}
-
-static void
-SmartScheduleTimer (int sig)
-{
- SmartScheduleTime += SmartScheduleInterval;
-}
-
-void
-SmartScheduleInit (void)
-{
- struct sigaction act;
-
- if (SmartScheduleDisable)
- return;
-
- memset((char *) &act, 0, sizeof(struct sigaction));
-
- /* Set up the timer signal function */
- act.sa_handler = SmartScheduleTimer;
- sigemptyset (&act.sa_mask);
- sigaddset (&act.sa_mask, SIGALRM);
- if (sigaction (SIGALRM, &act, 0) < 0)
- {
- perror ("sigaction for smart scheduler");
- SmartScheduleDisable = TRUE;
- }
-}
-
-#ifdef SIG_BLOCK
-static sigset_t PreviousSignalMask;
-static int BlockedSignalCount;
-#endif
-
-void
-OsBlockSignals (void)
-{
-#ifdef SIG_BLOCK
- if (BlockedSignalCount++ == 0)
- {
- sigset_t set;
-
- sigemptyset (&set);
- sigaddset (&set, SIGALRM);
- sigaddset (&set, SIGVTALRM);
-#ifdef SIGWINCH
- sigaddset (&set, SIGWINCH);
-#endif
-#ifdef SIGIO
- sigaddset (&set, SIGIO);
-#endif
- sigaddset (&set, SIGTSTP);
- sigaddset (&set, SIGTTIN);
- sigaddset (&set, SIGTTOU);
- sigaddset (&set, SIGCHLD);
- sigprocmask (SIG_BLOCK, &set, &PreviousSignalMask);
- }
-#endif
-}
-
-void
-OsReleaseSignals (void)
-{
-#ifdef SIG_BLOCK
- if (--BlockedSignalCount == 0)
- {
- sigprocmask (SIG_SETMASK, &PreviousSignalMask, 0);
- }
-#endif
-}
-
-/*
- * Pending signals may interfere with core dumping. Provide a
- * mechanism to block signals when aborting.
- */
-
-void
-OsAbort (void)
-{
-#ifndef __APPLE__
- OsBlockSignals();
-#endif
- abort();
-}
-
-#if !defined(WIN32)
-/*
- * "safer" versions of system(3), popen(3) and pclose(3) which give up
- * all privs before running a command.
- *
- * This is based on the code in FreeBSD 2.2 libc.
- *
- * XXX It'd be good to redirect stderr so that it ends up in the log file
- * as well. As it is now, xkbcomp messages don't end up in the log file.
- */
-
-int
-System(char *command)
-{
- int pid, p;
- void (*csig)(int);
- int status;
-
- if (!command)
- return 1;
-
- csig = signal(SIGCHLD, SIG_DFL);
- if (csig == SIG_ERR) {
- perror("signal");
- return -1;
- }
- DebugF("System: `%s'\n", command);
-
- switch (pid = fork()) {
- case -1: /* error */
- p = -1;
- case 0: /* child */
- if (setgid(getgid()) == -1)
- _exit(127);
- if (setuid(getuid()) == -1)
- _exit(127);
- execl("/bin/sh", "sh", "-c", command, (char *)NULL);
- _exit(127);
- default: /* parent */
- do {
- p = waitpid(pid, &status, 0);
- } while (p == -1 && errno == EINTR);
-
- }
-
- if (signal(SIGCHLD, csig) == SIG_ERR) {
- perror("signal");
- return -1;
- }
-
- return p == -1 ? -1 : status;
-}
-
-static struct pid {
- struct pid *next;
- FILE *fp;
- int pid;
-} *pidlist;
-
-OsSigHandlerPtr old_alarm = NULL; /* XXX horrible awful hack */
-
-pointer
-Popen(char *command, char *type)
-{
- struct pid *cur;
- FILE *iop;
- int pdes[2], pid;
-
- if (command == NULL || type == NULL)
- return NULL;
-
- if ((*type != 'r' && *type != 'w') || type[1])
- return NULL;
-
- if ((cur = malloc(sizeof(struct pid))) == NULL)
- return NULL;
-
- if (pipe(pdes) < 0) {
- free(cur);
- return NULL;
- }
-
- /* Ignore the smart scheduler while this is going on */
- old_alarm = OsSignal(SIGALRM, SIG_IGN);
- if (old_alarm == SIG_ERR) {
- close(pdes[0]);
- close(pdes[1]);
- free(cur);
- perror("signal");
- return NULL;
- }
-
- switch (pid = fork()) {
- case -1: /* error */
- close(pdes[0]);
- close(pdes[1]);
- free(cur);
- if (OsSignal(SIGALRM, old_alarm) == SIG_ERR)
- perror("signal");
- return NULL;
- case 0: /* child */
- if (setgid(getgid()) == -1)
- _exit(127);
- if (setuid(getuid()) == -1)
- _exit(127);
- if (*type == 'r') {
- if (pdes[1] != 1) {
- /* stdout */
- dup2(pdes[1], 1);
- close(pdes[1]);
- }
- close(pdes[0]);
- } else {
- if (pdes[0] != 0) {
- /* stdin */
- dup2(pdes[0], 0);
- close(pdes[0]);
- }
- close(pdes[1]);
- }
- execl("/bin/sh", "sh", "-c", command, (char *)NULL);
- _exit(127);
- }
-
- /* Avoid EINTR during stdio calls */
- OsBlockSignals ();
-
- /* parent */
- if (*type == 'r') {
- iop = fdopen(pdes[0], type);
- close(pdes[1]);
- } else {
- iop = fdopen(pdes[1], type);
- close(pdes[0]);
- }
-
- cur->fp = iop;
- cur->pid = pid;
- cur->next = pidlist;
- pidlist = cur;
-
- DebugF("Popen: `%s', fp = %p\n", command, iop);
-
- return iop;
-}
-
-/* fopen that drops privileges */
-pointer
-Fopen(char *file, char *type)
-{
- FILE *iop;
-#ifndef HAS_SAVED_IDS_AND_SETEUID
- struct pid *cur;
- int pdes[2], pid;
-
- if (file == NULL || type == NULL)
- return NULL;
-
- if ((*type != 'r' && *type != 'w') || type[1])
- return NULL;
-
- if ((cur = malloc(sizeof(struct pid))) == NULL)
- return NULL;
-
- if (pipe(pdes) < 0) {
- free(cur);
- return NULL;
- }
-
- switch (pid = fork()) {
- case -1: /* error */
- close(pdes[0]);
- close(pdes[1]);
- free(cur);
- return NULL;
- case 0: /* child */
- if (setgid(getgid()) == -1)
- _exit(127);
- if (setuid(getuid()) == -1)
- _exit(127);
- if (*type == 'r') {
- if (pdes[1] != 1) {
- /* stdout */
- dup2(pdes[1], 1);
- close(pdes[1]);
- }
- close(pdes[0]);
- } else {
- if (pdes[0] != 0) {
- /* stdin */
- dup2(pdes[0], 0);
- close(pdes[0]);
- }
- close(pdes[1]);
- }
- execl("/bin/cat", "cat", file, (char *)NULL);
- _exit(127);
- }
-
- /* Avoid EINTR during stdio calls */
- OsBlockSignals ();
-
- /* parent */
- if (*type == 'r') {
- iop = fdopen(pdes[0], type);
- close(pdes[1]);
- } else {
- iop = fdopen(pdes[1], type);
- close(pdes[0]);
- }
-
- cur->fp = iop;
- cur->pid = pid;
- cur->next = pidlist;
- pidlist = cur;
-
- DebugF("Fopen(%s), fp = %p\n", file, iop);
-
- return iop;
-#else
- int ruid, euid;
-
- ruid = getuid();
- euid = geteuid();
-
- if (seteuid(ruid) == -1) {
- return NULL;
- }
- iop = fopen(file, type);
-
- if (seteuid(euid) == -1) {
- fclose(iop);
- return NULL;
- }
- return iop;
-#endif /* HAS_SAVED_IDS_AND_SETEUID */
-}
-
-int
-Pclose(pointer iop)
-{
- struct pid *cur, *last;
- int pstat;
- int pid;
-
- DebugF("Pclose: fp = %p\n", iop);
- fclose(iop);
-
- for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next)
- if (cur->fp == iop)
- break;
- if (cur == NULL)
- return -1;
-
- do {
- pid = waitpid(cur->pid, &pstat, 0);
- } while (pid == -1 && errno == EINTR);
-
- if (last == NULL)
- pidlist = cur->next;
- else
- last->next = cur->next;
- free(cur);
-
- /* allow EINTR again */
- OsReleaseSignals ();
-
- if (old_alarm && OsSignal(SIGALRM, old_alarm) == SIG_ERR) {
- perror("signal");
- return -1;
- }
-
- return pid == -1 ? -1 : pstat;
-}
-
-int
-Fclose(pointer iop)
-{
-#ifdef HAS_SAVED_IDS_AND_SETEUID
- return fclose(iop);
-#else
- return Pclose(iop);
-#endif
-}
-
-#endif /* !WIN32 */
-
-
-/*
- * CheckUserParameters: check for long command line arguments and long
- * environment variables. By default, these checks are only done when
- * the server's euid != ruid. In 3.3.x, these checks were done in an
- * external wrapper utility.
- */
-
-/* Consider LD* variables insecure? */
-#ifndef REMOVE_ENV_LD
-#define REMOVE_ENV_LD 1
-#endif
-
-/* Remove long environment variables? */
-#ifndef REMOVE_LONG_ENV
-#define REMOVE_LONG_ENV 1
-#endif
-
-/*
- * Disallow stdout or stderr as pipes? It's possible to block the X server
- * when piping stdout+stderr to a pipe.
- *
- * Don't enable this because it looks like it's going to cause problems.
- */
-#ifndef NO_OUTPUT_PIPES
-#define NO_OUTPUT_PIPES 0
-#endif
-
-
-/* Check args and env only if running setuid (euid == 0 && euid != uid) ? */
-#ifndef CHECK_EUID
-#ifndef WIN32
-#define CHECK_EUID 1
-#else
-#define CHECK_EUID 0
-#endif
-#endif
-
-/*
- * Maybe the locale can be faked to make isprint(3) report that everything
- * is printable? Avoid it by default.
- */
-#ifndef USE_ISPRINT
-#define USE_ISPRINT 0
-#endif
-
-#define MAX_ARG_LENGTH 128
-#define MAX_ENV_LENGTH 256
-#define MAX_ENV_PATH_LENGTH 2048 /* Limit for *PATH and TERMCAP */
-
-#if USE_ISPRINT
-#include <ctype.h>
-#define checkPrintable(c) isprint(c)
-#else
-#define checkPrintable(c) (((c) & 0x7f) >= 0x20 && ((c) & 0x7f) != 0x7f)
-#endif
-
-enum BadCode {
- NotBad = 0,
- UnsafeArg,
- ArgTooLong,
- UnprintableArg,
- EnvTooLong,
- OutputIsPipe,
- InternalError
-};
-
-#if defined(VENDORSUPPORT)
-#define BUGADDRESS VENDORSUPPORT
-#elif defined(BUILDERADDR)
-#define BUGADDRESS BUILDERADDR
-#else
-#define BUGADDRESS "xorg@freedesktop.org"
-#endif
-
-void
-CheckUserParameters(int argc, char **argv, char **envp)
-{
- enum BadCode bad = NotBad;
- int i = 0, j;
- char *a, *e = NULL;
-
-#if CHECK_EUID
- if (geteuid() == 0 && getuid() != geteuid())
-#endif
- {
- /* Check each argv[] */
- for (i = 1; i < argc; i++) {
- if (strcmp(argv[i], "-fp") == 0)
- {
- i++; /* continue with next argument. skip the length check */
- if (i >= argc)
- break;
- } else
- {
- if (strlen(argv[i]) > MAX_ARG_LENGTH) {
- bad = ArgTooLong;
- break;
- }
- }
- a = argv[i];
- while (*a) {
- if (checkPrintable(*a) == 0) {
- bad = UnprintableArg;
- break;
- }
- a++;
- }
- if (bad)
- break;
- }
- if (!bad) {
- /* Check each envp[] */
- for (i = 0; envp[i]; i++) {
-
- /* Check for bad environment variables and values */
-#if REMOVE_ENV_LD
- while (envp[i] && (strncmp(envp[i], "LD", 2) == 0)) {
- for (j = i; envp[j]; j++) {
- envp[j] = envp[j+1];
- }
- }
-#endif
- if (envp[i] && (strlen(envp[i]) > MAX_ENV_LENGTH)) {
-#if REMOVE_LONG_ENV
- for (j = i; envp[j]; j++) {
- envp[j] = envp[j+1];
- }
- i--;
-#else
- char *eq;
- int len;
-
- eq = strchr(envp[i], '=');
- if (!eq)
- continue;
- len = eq - envp[i];
- e = malloc(len + 1);
- if (!e) {
- bad = InternalError;
- break;
- }
- strncpy(e, envp[i], len);
- e[len] = 0;
- if (len >= 4 &&
- (strcmp(e + len - 4, "PATH") == 0 ||
- strcmp(e, "TERMCAP") == 0)) {
- if (strlen(envp[i]) > MAX_ENV_PATH_LENGTH) {
- bad = EnvTooLong;
- break;
- } else {
- free(e);
- }
- } else {
- bad = EnvTooLong;
- break;
- }
-#endif
- }
- }
- }
-#if NO_OUTPUT_PIPES
- if (!bad) {
- struct stat buf;
-
- if (fstat(fileno(stdout), &buf) == 0 && S_ISFIFO(buf.st_mode))
- bad = OutputIsPipe;
- if (fstat(fileno(stderr), &buf) == 0 && S_ISFIFO(buf.st_mode))
- bad = OutputIsPipe;
- }
-#endif
- }
- switch (bad) {
- case NotBad:
- return;
- case UnsafeArg:
- ErrorF("Command line argument number %d is unsafe\n", i);
- break;
- case ArgTooLong:
- ErrorF("Command line argument number %d is too long\n", i);
- break;
- case UnprintableArg:
- ErrorF("Command line argument number %d contains unprintable"
- " characters\n", i);
- break;
- case EnvTooLong:
- ErrorF("Environment variable `%s' is too long\n", e);
- break;
- case OutputIsPipe:
- ErrorF("Stdout and/or stderr is a pipe\n");
- break;
- case InternalError:
- ErrorF("Internal Error\n");
- break;
- default:
- ErrorF("Unknown error\n");
- break;
- }
- FatalError("X server aborted because of unsafe environment\n");
-}
-
-/*
- * CheckUserAuthorization: check if the user is allowed to start the
- * X server. This usually means some sort of PAM checking, and it is
- * usually only done for setuid servers (uid != euid).
- */
-
-#ifdef USE_PAM
-#include <security/pam_appl.h>
-#include <security/pam_misc.h>
-#include <pwd.h>
-#endif /* USE_PAM */
-
-void
-CheckUserAuthorization(void)
-{
-#ifdef USE_PAM
- static struct pam_conv conv = {
- misc_conv,
- NULL
- };
-
- pam_handle_t *pamh = NULL;
- struct passwd *pw;
- int retval;
-
- if (getuid() != geteuid()) {
- pw = getpwuid(getuid());
- if (pw == NULL)
- FatalError("getpwuid() failed for uid %d\n", getuid());
-
- retval = pam_start("xserver", pw->pw_name, &conv, &pamh);
- if (retval != PAM_SUCCESS)
- FatalError("pam_start() failed.\n"
- "\tMissing or mangled PAM config file or module?\n");
-
- retval = pam_authenticate(pamh, 0);
- if (retval != PAM_SUCCESS) {
- pam_end(pamh, retval);
- FatalError("PAM authentication failed, cannot start X server.\n"
- "\tPerhaps you do not have console ownership?\n");
- }
-
- retval = pam_acct_mgmt(pamh, 0);
- if (retval != PAM_SUCCESS) {
- pam_end(pamh, retval);
- FatalError("PAM authentication failed, cannot start X server.\n"
- "\tPerhaps you do not have console ownership?\n");
- }
-
- /* this is not a session, so do not do session management */
- pam_end(pamh, PAM_SUCCESS);
- }
-#endif
-}
-
-/*
- * Tokenize a string into a NULL terminated array of strings. Always returns
- * an allocated array unless an error occurs.
- */
-char**
-xstrtokenize(const char *str, const char *separators)
-{
- char **list, **nlist;
- char *tok, *tmp;
- unsigned num = 0, n;
-
- if (!str)
- return NULL;
- list = calloc(1, sizeof(*list));
- if (!list)
- return NULL;
- tmp = strdup(str);
- if (!tmp)
- goto error;
- for (tok = strtok(tmp, separators); tok; tok = strtok(NULL, separators)) {
- nlist = realloc(list, (num + 2) * sizeof(*list));
- if (!nlist)
- goto error;
- list = nlist;
- list[num] = strdup(tok);
- if (!list[num])
- goto error;
- list[++num] = NULL;
- }
- free(tmp);
- return list;
-
-error:
- free(tmp);
- for (n = 0; n < num; n++)
- free(list[n]);
- free(list);
- return NULL;
-}
+/*
+
+Copyright 1987, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
+Copyright 1994 Quarterdeck Office Systems.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Digital and
+Quarterdeck not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+DIGITAL AND QUARTERDECK DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT
+OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
+OR PERFORMANCE OF THIS SOFTWARE.
+
+*/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifdef __CYGWIN__
+#include <stdlib.h>
+#include <signal.h>
+/*
+ Sigh... We really need a prototype for this to know it is stdcall,
+ but #include-ing <windows.h> here is not a good idea...
+*/
+__stdcall unsigned long GetTickCount(void);
+#endif
+
+#if defined(WIN32) && !defined(__CYGWIN__)
+#include <X11/Xwinsock.h>
+#endif
+#include <X11/Xos.h>
+#include <stdio.h>
+#include <time.h>
+#if !defined(WIN32) || !defined(__MINGW32__)
+#include <sys/time.h>
+#include <sys/resource.h>
+#endif
+#include "misc.h"
+#include <X11/X.h>
+#define XSERV_t
+#define TRANS_SERVER
+#define TRANS_REOPEN
+#include <X11/Xtrans/Xtrans.h>
+#include "input.h"
+#include "dixfont.h"
+#include "osdep.h"
+#include "extension.h"
+#ifdef X_POSIX_C_SOURCE
+#define _POSIX_C_SOURCE X_POSIX_C_SOURCE
+#include <signal.h>
+#undef _POSIX_C_SOURCE
+#else
+#if defined(_POSIX_SOURCE)
+#include <signal.h>
+#else
+#define _POSIX_SOURCE
+#include <signal.h>
+#undef _POSIX_SOURCE
+#endif
+#endif
+#ifndef WIN32
+#include <sys/wait.h>
+#endif
+#if !defined(SYSV) && !defined(WIN32)
+#include <sys/resource.h>
+#endif
+#include <sys/stat.h>
+#include <ctype.h> /* for isspace */
+#include <stdarg.h>
+
+#include <stdlib.h> /* for malloc() */
+
+#if defined(TCPCONN) || defined(STREAMSCONN)
+# ifndef WIN32
+# include <netdb.h>
+# endif
+#endif
+
+#include "opaque.h"
+
+#include "dixstruct.h"
+
+#include "xkbsrv.h"
+
+#include "picture.h"
+
+Bool noTestExtensions;
+#ifdef COMPOSITE
+Bool noCompositeExtension = FALSE;
+#endif
+
+#ifdef DAMAGE
+Bool noDamageExtension = FALSE;
+#endif
+#ifdef DBE
+Bool noDbeExtension = FALSE;
+#endif
+#ifdef DPMSExtension
+Bool noDPMSExtension = FALSE;
+#endif
+#ifdef GLXEXT
+Bool noGlxExtension = FALSE;
+Bool noGlxVisualInit = FALSE;
+#endif
+#ifdef SCREENSAVER
+Bool noScreenSaverExtension = FALSE;
+#endif
+#ifdef MITSHM
+Bool noMITShmExtension = FALSE;
+#endif
+#ifdef RANDR
+Bool noRRExtension = FALSE;
+#endif
+Bool noRenderExtension = FALSE;
+#ifdef XCSECURITY
+Bool noSecurityExtension = FALSE;
+#endif
+#ifdef RES
+Bool noResExtension = FALSE;
+#endif
+#ifdef XF86BIGFONT
+Bool noXFree86BigfontExtension = FALSE;
+#endif
+#ifdef XFreeXDGA
+Bool noXFree86DGAExtension = FALSE;
+#endif
+#ifdef XF86DRI
+Bool noXFree86DRIExtension = FALSE;
+#endif
+#ifdef XF86VIDMODE
+Bool noXFree86VidModeExtension = FALSE;
+#endif
+#ifdef XFIXES
+Bool noXFixesExtension = FALSE;
+#endif
+#ifdef PANORAMIX
+/* Xinerama is disabled by default unless enabled via +xinerama */
+Bool noPanoramiXExtension = TRUE;
+#endif
+#ifdef XSELINUX
+Bool noSELinuxExtension = FALSE;
+int selinuxEnforcingState = SELINUX_MODE_DEFAULT;
+#endif
+#ifdef XV
+Bool noXvExtension = FALSE;
+#endif
+#ifdef DRI2
+Bool noDRI2Extension = FALSE;
+#endif
+
+Bool noGEExtension = FALSE;
+
+#define X_INCLUDE_NETDB_H
+#include <X11/Xos_r.h>
+
+#include <errno.h>
+
+Bool CoreDump;
+
+#ifdef PANORAMIX
+Bool PanoramiXExtensionDisabledHack = FALSE;
+#endif
+
+int auditTrailLevel = 1;
+
+#ifdef _MSC_VER
+static HANDLE s_hSmartScheduleTimer = NULL;
+static HANDLE s_hSmartScheduleTimerQueue = NULL;
+#endif
+
+#if defined(SVR4) || defined(__linux__) || defined(CSRG_BASED)
+#define HAS_SAVED_IDS_AND_SETEUID
+#endif
+
+OsSigHandlerPtr
+OsSignal(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
+}
+
+/*
+ * 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"
+
+static Bool StillLocking = FALSE;
+static char szLockFile[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)
+{
+#if defined(WIN32) && !defined(__CYGWIN__)
+ char MutexName[100];
+ sprintf(MutexName, "Global\\VcXsrv_Mutex_%d\n", getpid());
+ if (!CreateMutex(NULL,TRUE,MutexName) || GetLastError()== ERROR_ALREADY_EXISTS)
+ {
+ FatalError("Server is already active for display %d\n", atoi(display));
+ }
+#else
+ char port[20];
+ char tmp[PATH_MAX], pid_str[12];
+ int lfd, i, haslock, l_pid, t;
+ char *tmppath = NULL;
+ int len;
+
+ 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(szLockFile))
+ FatalError("Display name `%s' is too long\n", port);
+ (void)sprintf(tmp, "%s" LOCK_TMP_PREFIX "%s" LOCK_SUFFIX, tmppath, port);
+ (void)sprintf(szLockFile, "%s" LOCK_PREFIX "%s" LOCK_SUFFIX, tmppath, port);
+
+ /*
+ * Create a temporary file containing our PID. Attempt three times
+ * to create the file.
+ */
+ StillLocking = TRUE;
+ i = 0;
+ do {
+ i++;
+ lfd = open(tmp, O_CREAT | O_EXCL | O_WRONLY, 0644);
+ if (lfd < 0)
+ sleep(2);
+ else
+ break;
+ } while (i < 3);
+ if (lfd < 0) {
+ unlink(tmp);
+ i = 0;
+ do {
+ i++;
+ lfd = open(tmp, O_CREAT | O_EXCL | O_WRONLY, 0644);
+ if (lfd < 0)
+ sleep(2);
+ else
+ break;
+ } while (i < 3);
+ }
+ if (lfd < 0)
+ FatalError("Could not create lock file in %s\n", tmp);
+ (void) sprintf(pid_str, "%10ld\n", (long)getpid());
+ (void) write(lfd, pid_str, 11);
+ (void) chmod(tmp, 0444);
+ (void) close(lfd);
+
+ /*
+ * OK. Now the tmp file exists. Try three times to move it in place
+ * for the lock.
+ */
+ i = 0;
+ haslock = 0;
+ while ((!haslock) && (i++ < 3)) {
+ haslock = (link(tmp,szLockFile) == 0);
+ if (haslock) {
+ /*
+ * We're done.
+ */
+ break;
+ }
+ else {
+ /*
+ * Read the pid from the existing file
+ */
+ lfd = open(szLockFile, O_RDONLY);
+ if (lfd < 0) {
+ unlink(tmp);
+ FatalError("Can't read lock file %s\n", szLockFile);
+ }
+ pid_str[0] = '\0';
+ if (read(lfd, pid_str, 11) != 11) {
+ /*
+ * Bogus lock file.
+ */
+ unlink(szLockFile);
+ 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(szLockFile);
+ 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",
+ szLockFile, "\tand start again.");
+ }
+ }
+ }
+ unlink(tmp);
+ if (!haslock)
+ FatalError("Could not create server lock file: %s\n", szLockFile);
+ StillLocking = FALSE;
+#endif
+}
+
+/*
+ * UnlockServer --
+ * Remove the server lock file.
+ */
+void
+UnlockServer(void)
+{
+ if (nolock) return;
+
+ if (!StillLocking){
+
+ (void) unlink(szLockFile);
+ }
+}
+
+/* Force connections to close on SIGHUP from init */
+
+void
+AutoResetServer (int sig)
+{
+ int olderrno = errno;
+
+ dispatchException |= DE_RESET;
+ isItTimeToYield = TRUE;
+ errno = olderrno;
+}
+
+/* Force connections to close and then exit on SIGTERM, SIGINT */
+
+void
+GiveUp(int sig)
+{
+ int olderrno = errno;
+
+ dispatchException |= DE_TERMINATE;
+ isItTimeToYield = TRUE;
+ errno = olderrno;
+}
+
+#if (defined WIN32 && defined __MINGW32__) || defined(__CYGWIN__)
+CARD32
+GetTimeInMillis (void)
+{
+ return GetTickCount ();
+}
+#else
+CARD32
+GetTimeInMillis(void)
+{
+ struct timeval tv;
+
+#ifdef MONOTONIC_CLOCK
+ struct timespec tp;
+ static clockid_t clockid;
+ if (!clockid) {
+#ifdef CLOCK_MONOTONIC_COARSE
+ if (clock_getres(CLOCK_MONOTONIC_COARSE, &tp) == 0 &&
+ (tp.tv_nsec / 1000) <= 1000 &&
+ clock_gettime(CLOCK_MONOTONIC_COARSE, &tp) == 0)
+ clockid = CLOCK_MONOTONIC_COARSE;
+ else
+#endif
+ if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
+ clockid = CLOCK_MONOTONIC;
+ else
+ clockid = ~0L;
+ }
+ if (clockid != ~0L && clock_gettime(clockid, &tp) == 0)
+ return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L);
+#endif
+
+ X_GETTIMEOFDAY(&tv);
+ return(tv.tv_sec * 1000) + (tv.tv_usec / 1000);
+}
+#endif
+
+void
+AdjustWaitForDelay (pointer waitTime, unsigned long newdelay)
+{
+ static struct timeval delay_val;
+ struct timeval **wt = (struct timeval **) waitTime;
+ unsigned long olddelay;
+
+ if (*wt == NULL)
+ {
+ delay_val.tv_sec = newdelay / 1000;
+ delay_val.tv_usec = 1000 * (newdelay % 1000);
+ *wt = &delay_val;
+ }
+ else
+ {
+ olddelay = (*wt)->tv_sec * 1000 + (*wt)->tv_usec / 1000;
+ if (newdelay < olddelay)
+ {
+ (*wt)->tv_sec = newdelay / 1000;
+ (*wt)->tv_usec = 1000 * (newdelay % 1000);
+ }
+ }
+}
+
+void UseMsg(void)
+{
+ ErrorF("Usage...\nVcxsrv [:<display>] [option]\n\n");
+ ErrorF(":display-number\n\tVcxsrv runs as the given display-number, which defaults to 0.\n");
+ ErrorF("\tTo run multiple instances, use unique display-numbers.\n\n");
+
+ ErrorF("-a # default pointer acceleration (factor)\n");
+ ErrorF("-ac disable access control restrictions\n");
+ ErrorF("-audit int set audit trail level\n");
+ ErrorF("-auth file select authorization file\n");
+ ErrorF("-br create root window with black background\n");
+ ErrorF("+bs enable any backing store support\n");
+ ErrorF("-bs disable any backing store support\n");
+ ErrorF("-cc int default color visual class\n");
+ ErrorF("-nocursor disable the cursor\n");
+ ErrorF("-core generate core dump on fatal error\n");
+#ifdef _MSC_VER
+ ErrorF("-dpi [auto|int] screen resolution set to native or this dpi\n");
+#else
+ ErrorF("-dpi int screen resolution in dots per inch\n");
+#endif
+#ifdef DPMSExtension
+ ErrorF("-dpms disables VESA DPMS monitor control\n");
+#endif
+ ErrorF("-deferglyphs [none|all|16] defer loading of [no|all|16-bit] glyphs\n");
+ ErrorF("-f # bell base (0-100)\n");
+ ErrorF("-fc string cursor font\n");
+ ErrorF("-fn string default font name\n");
+ ErrorF("-fp string default font path\n");
+ ErrorF("-help prints message with these options\n");
+ ErrorF("-I ignore all remaining arguments\n");
+#ifdef RLIMIT_DATA
+ ErrorF("-ld int limit data space to N Kb\n");
+#endif
+#ifdef RLIMIT_NOFILE
+ ErrorF("-lf int limit number of open files to N\n");
+#endif
+#ifdef RLIMIT_STACK
+ ErrorF("-ls int limit stack space to N Kb\n");
+#endif
+ ErrorF("-nolock disable the locking mechanism\n");
+ ErrorF("-nolisten string don't listen on protocol\n");
+ ErrorF("-noreset don't reset after last client exists\n");
+ ErrorF("-background [none] create root window with no background\n");
+ ErrorF("-reset reset after last client exists\n");
+ ErrorF("-pn accept failure to listen on all ports\n");
+ ErrorF("-nopn reject failure to listen on all ports\n");
+ ErrorF("-r turns off auto-repeat\n");
+ ErrorF("r turns on auto-repeat \n");
+ ErrorF("-render [default|mono|gray|color] set render color alloc policy\n");
+ ErrorF("-retro start with classic stipple\n");
+ ErrorF("-t # default pointer threshold (pixels/t)\n");
+ ErrorF("-terminate terminate at server reset\n");
+ ErrorF("-to # connection time out\n");
+ ErrorF("-tst disable testing extensions\n");
+ ErrorF("-wm WhenMapped default backing-store\n");
+ ErrorF("-wr create root window with white background\n");
+#ifdef PANORAMIX
+ ErrorF("+xinerama Enable XINERAMA extension\n");
+ ErrorF("-xinerama Disable XINERAMA extension\n");
+#endif
+ ErrorF("-dumbSched Disable smart scheduling, enable old behavior\n");
+ ErrorF("-schedInterval int Set scheduler interval in msec\n");
+ ErrorF("+extension name Enable extension\n");
+ ErrorF("-extension name Disable extension\n");
+#ifdef XDMCP
+ XdmcpUseMsg();
+#endif
+ XkbUseMsg();
+ ddxUseMsg();
+}
+
+/* This function performs a rudimentary sanity check
+ * on the display name passed in on the command-line,
+ * since this string is used to generate filenames.
+ * It is especially important that the display name
+ * not contain a "/" and not start with a "-".
+ * --kvajk
+ */
+static int
+VerifyDisplayName(const char *d)
+{
+ if ( d == (char *)0 ) return 0; /* null */
+ if ( *d == '\0' ) return 0; /* empty */
+ if ( *d == '-' ) return 0; /* could be confused for an option */
+ if ( *d == '.' ) return 0; /* must not equal "." or ".." */
+ if ( strchr(d, '/') != (char *)0 ) return 0; /* very important!!! */
+ return 1;
+}
+
+/*
+ * This function parses the command line. Handles device-independent fields
+ * and allows ddx to handle additional fields. It is not allowed to modify
+ * argc or any of the strings pointed to by argv.
+ */
+void
+ProcessCommandLine(int argc, char *argv[])
+{
+ int i, skip;
+
+ defaultKeyboardControl.autoRepeat = TRUE;
+
+#ifdef NO_PART_NET
+ PartialNetwork = FALSE;
+#else
+ PartialNetwork = TRUE;
+#endif
+
+ for ( i = 1; i < argc; i++ )
+ {
+ /* call ddx first, so it can peek/override if it wants */
+ if((skip = ddxProcessArgument(argc, argv, i)))
+ {
+ i += (skip - 1);
+ }
+ else if(argv[i][0] == ':')
+ {
+ /* initialize display */
+ display = argv[i];
+ display++;
+ if( ! VerifyDisplayName( display ) ) {
+ ErrorF("Bad display name: %s\n", display);
+ UseMsg();
+ FatalError("Bad display name, exiting: %s\n", display);
+ }
+ }
+ else if ( strcmp( argv[i], "-a") == 0)
+ {
+ if(++i < argc)
+ defaultPointerControl.num = atoi(argv[i]);
+ else
+ UseMsg();
+ }
+ else if ( strcmp( argv[i], "-ac") == 0)
+ {
+ defeatAccessControl = TRUE;
+ }
+ else if ( strcmp( argv[i], "-audit") == 0)
+ {
+ if(++i < argc)
+ auditTrailLevel = atoi(argv[i]);
+ else
+ UseMsg();
+ }
+ else if ( strcmp( argv[i], "-auth") == 0)
+ {
+ if(++i < argc)
+ InitAuthorization (argv[i]);
+ else
+ UseMsg();
+ }
+ else if ( strcmp( argv[i], "-br") == 0) ; /* default */
+ else if ( strcmp( argv[i], "+bs") == 0)
+ enableBackingStore = TRUE;
+ else if ( strcmp( argv[i], "-bs") == 0)
+ disableBackingStore = TRUE;
+ else if ( strcmp( argv[i], "-cc") == 0)
+ {
+ if(++i < argc)
+ defaultColorVisualClass = atoi(argv[i]);
+ else
+ UseMsg();
+ }
+ else if ( strcmp( argv[i], "-core") == 0)
+ {
+#if !defined(WIN32) || !defined(__MINGW32__)
+ struct rlimit core_limit;
+ getrlimit (RLIMIT_CORE, &core_limit);
+ core_limit.rlim_cur = core_limit.rlim_max;
+ setrlimit (RLIMIT_CORE, &core_limit);
+#endif
+ CoreDump = TRUE;
+ }
+ else if ( strcmp( argv[i], "-nocursor") == 0)
+ {
+ EnableCursor = FALSE;
+ }
+ else if ( strcmp( argv[i], "-dpi") == 0)
+ {
+ if(++i < argc)
+#ifdef _MSC_VER
+ {
+ if (strcmp(argv[i], "auto") == 0)
+ {
+ HDC hdc = GetDC(NULL);
+ if (hdc)
+ {
+ int dpiY = GetDeviceCaps(hdc, LOGPIXELSY);
+ monitorResolution = dpiY;
+ ReleaseDC(NULL, hdc);
+ }
+ }
+ else if (isdigit(*argv[i])) /* Naively prevent a crash if not numeric */
+ monitorResolution = atoi(argv[i]);
+ }
+#else
+ monitorResolution = atoi(argv[i]);
+#endif
+ else
+ UseMsg();
+ }
+#ifdef DPMSExtension
+ else if ( strcmp( argv[i], "dpms") == 0)
+ /* ignored for compatibility */ ;
+ else if ( strcmp( argv[i], "-dpms") == 0)
+ DPMSDisabledSwitch = TRUE;
+#endif
+ else if ( strcmp( argv[i], "-deferglyphs") == 0)
+ {
+ if(++i >= argc || !ParseGlyphCachingMode(argv[i]))
+ UseMsg();
+ }
+ else if ( strcmp( argv[i], "-f") == 0)
+ {
+ if(++i < argc)
+ defaultKeyboardControl.bell = atoi(argv[i]);
+ else
+ UseMsg();
+ }
+ else if ( strcmp( argv[i], "-fc") == 0)
+ {
+ if(++i < argc)
+ defaultCursorFont = argv[i];
+ else
+ UseMsg();
+ }
+ else if ( strcmp( argv[i], "-fn") == 0)
+ {
+ if(++i < argc)
+ defaultTextFont = argv[i];
+ else
+ UseMsg();
+ }
+ else if ( strcmp( argv[i], "-fp") == 0)
+ {
+ if(++i < argc)
+ {
+ defaultFontPath = argv[i];
+ }
+ else
+ UseMsg();
+ }
+ else if ( strcmp( argv[i], "-help") == 0)
+ {
+ UseMsg();
+ exit(0);
+ }
+ else if ( (skip=XkbProcessArguments(argc,argv,i))!=0 ) {
+ if (skip>0)
+ i+= skip-1;
+ else UseMsg();
+ }
+#ifdef RLIMIT_DATA
+ else if ( strcmp( argv[i], "-ld") == 0)
+ {
+ if(++i < argc)
+ {
+ limitDataSpace = atoi(argv[i]);
+ if (limitDataSpace > 0)
+ limitDataSpace *= 1024;
+ }
+ else
+ UseMsg();
+ }
+#endif
+#ifdef RLIMIT_NOFILE
+ else if ( strcmp( argv[i], "-lf") == 0)
+ {
+ if(++i < argc)
+ limitNoFile = atoi(argv[i]);
+ else
+ UseMsg();
+ }
+#endif
+#ifdef RLIMIT_STACK
+ else if ( strcmp( argv[i], "-ls") == 0)
+ {
+ if(++i < argc)
+ {
+ limitStackSpace = atoi(argv[i]);
+ if (limitStackSpace > 0)
+ limitStackSpace *= 1024;
+ }
+ else
+ UseMsg();
+ }
+#endif
+ else if ( strcmp ( argv[i], "-nolock") == 0)
+ {
+#if !defined(WIN32) && !defined(__CYGWIN__)
+ if (getuid() != 0)
+ ErrorF("Warning: the -nolock option can only be used by root\n");
+ else
+#endif
+ nolock = TRUE;
+ }
+ else if ( strcmp( argv[i], "-nolisten") == 0)
+ {
+ if(++i < argc) {
+ if (_XSERVTransNoListen(argv[i]))
+ FatalError ("Failed to disable listen for %s transport",
+ argv[i]);
+ } else
+ UseMsg();
+ }
+ else if ( strcmp( argv[i], "-noreset") == 0)
+ {
+ dispatchExceptionAtReset = 0;
+ }
+ else if ( strcmp( argv[i], "-reset") == 0)
+ {
+ dispatchExceptionAtReset = DE_RESET;
+ }
+ else if ( strcmp( argv[i], "-p") == 0)
+ {
+ if(++i < argc)
+ defaultScreenSaverInterval = ((CARD32)atoi(argv[i])) *
+ MILLI_PER_MIN;
+ else
+ UseMsg();
+ }
+ else if (strcmp(argv[i], "-pogo") == 0)
+ {
+ dispatchException = DE_TERMINATE;
+ }
+ else if ( strcmp( argv[i], "-pn") == 0)
+ PartialNetwork = TRUE;
+ else if ( strcmp( argv[i], "-nopn") == 0)
+ PartialNetwork = FALSE;
+ else if ( strcmp( argv[i], "r") == 0)
+ defaultKeyboardControl.autoRepeat = TRUE;
+ else if ( strcmp( argv[i], "-r") == 0)
+ defaultKeyboardControl.autoRepeat = FALSE;
+ else if ( strcmp( argv[i], "-retro") == 0)
+ party_like_its_1989 = TRUE;
+ else if ( strcmp( argv[i], "-s") == 0)
+ {
+ if(++i < argc)
+ defaultScreenSaverTime = ((CARD32)atoi(argv[i])) *
+ MILLI_PER_MIN;
+ else
+ UseMsg();
+ }
+ else if ( strcmp( argv[i], "-t") == 0)
+ {
+ if(++i < argc)
+ defaultPointerControl.threshold = atoi(argv[i]);
+ else
+ UseMsg();
+ }
+ else if ( strcmp( argv[i], "-terminate") == 0)
+ {
+ dispatchExceptionAtReset = DE_TERMINATE;
+ }
+ else if ( strcmp( argv[i], "-to") == 0)
+ {
+ if(++i < argc)
+ TimeOutValue = ((CARD32)atoi(argv[i])) * MILLI_PER_SECOND;
+ else
+ UseMsg();
+ }
+ else if ( strcmp( argv[i], "-tst") == 0)
+ {
+ noTestExtensions = TRUE;
+ }
+ else if ( strcmp( argv[i], "-wm") == 0)
+ defaultBackingStore = WhenMapped;
+ else if ( strcmp( argv[i], "-wr") == 0)
+ whiteRoot = TRUE;
+ else if ( strcmp( argv[i], "-background") == 0) {
+ if(++i < argc) {
+ if (!strcmp ( argv[i], "none"))
+ bgNoneRoot = TRUE;
+ else
+ UseMsg();
+ }
+ }
+ else if ( strcmp( argv[i], "-maxbigreqsize") == 0) {
+ if(++i < argc) {
+ long reqSizeArg = atol(argv[i]);
+
+ /* Request size > 128MB does not make much sense... */
+ if( reqSizeArg > 0L && reqSizeArg < 128L ) {
+ maxBigRequestSize = (reqSizeArg * 1048576L) - 1L;
+ }
+ else
+ {
+ UseMsg();
+ }
+ }
+ else
+ {
+ UseMsg();
+ }
+ }
+#ifdef PANORAMIX
+ else if ( strcmp( argv[i], "+xinerama") == 0){
+ noPanoramiXExtension = FALSE;
+ }
+ else if ( strcmp( argv[i], "-xinerama") == 0){
+ noPanoramiXExtension = TRUE;
+ }
+ else if ( strcmp( argv[i], "-disablexineramaextension") == 0){
+ PanoramiXExtensionDisabledHack = TRUE;
+ }
+#endif
+ else if ( strcmp( argv[i], "-I") == 0)
+ {
+ /* ignore all remaining arguments */
+ break;
+ }
+ else if (strncmp (argv[i], "tty", 3) == 0)
+ {
+ /* init supplies us with this useless information */
+ }
+#ifdef XDMCP
+ else if ((skip = XdmcpOptions(argc, argv, i)) != i)
+ {
+ i = skip - 1;
+ }
+#endif
+ else if ( strcmp( argv[i], "-dumbSched") == 0)
+ {
+ SmartScheduleDisable = TRUE;
+ }
+ else if ( strcmp( argv[i], "-schedInterval") == 0)
+ {
+ if (++i < argc)
+ {
+ SmartScheduleInterval = atoi(argv[i]);
+ SmartScheduleSlice = SmartScheduleInterval;
+ }
+ else
+ UseMsg();
+ }
+ else if ( strcmp( argv[i], "-schedMax") == 0)
+ {
+ if (++i < argc)
+ {
+ SmartScheduleMaxSlice = atoi(argv[i]);
+ }
+ else
+ UseMsg();
+ }
+ else if ( strcmp( argv[i], "-render" ) == 0)
+ {
+ if (++i < argc)
+ {
+ int policy = PictureParseCmapPolicy (argv[i]);
+
+ if (policy != PictureCmapPolicyInvalid)
+ PictureCmapPolicy = policy;
+ else
+ UseMsg ();
+ }
+ else
+ UseMsg ();
+ }
+ else if ( strcmp( argv[i], "+extension") == 0)
+ {
+ if (++i < argc)
+ {
+ if (!EnableDisableExtension(argv[i], TRUE))
+ EnableDisableExtensionError(argv[i], TRUE);
+ }
+ else
+ UseMsg();
+ }
+ else if ( strcmp( argv[i], "-extension") == 0)
+ {
+ if (++i < argc)
+ {
+ if (!EnableDisableExtension(argv[i], FALSE))
+ EnableDisableExtensionError(argv[i], FALSE);
+ }
+ else
+ UseMsg();
+ }
+ else
+ {
+ ErrorF("Unrecognized option: %s\n", argv[i]);
+ UseMsg();
+ FatalError("Unrecognized option: %s\n", argv[i]);
+ }
+ }
+}
+
+/* Implement a simple-minded font authorization scheme. The authorization
+ name is "hp-hostname-1", the contents are simply the host name. */
+int
+set_font_authorizations(char **authorizations, int *authlen, pointer client)
+{
+#define AUTHORIZATION_NAME "hp-hostname-1"
+#if defined(TCPCONN) || defined(STREAMSCONN)
+ static char *result = NULL;
+ static char *p = NULL;
+
+ if (p == NULL)
+ {
+ char hname[1024], *hnameptr;
+ unsigned int len;
+#if defined(IPv6) && defined(AF_INET6)
+ struct addrinfo hints, *ai = NULL;
+#else
+ struct hostent *host;
+#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
+ _Xgethostbynameparams hparams;
+#endif
+#endif
+
+ gethostname(hname, 1024);
+#if defined(IPv6) && defined(AF_INET6)
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_CANONNAME;
+ if (getaddrinfo(hname, NULL, &hints, &ai) == 0) {
+ hnameptr = ai->ai_canonname;
+ } else {
+ hnameptr = hname;
+ }
+#else
+ host = _XGethostbyname(hname, hparams);
+ if (host == NULL)
+ hnameptr = hname;
+ else
+ hnameptr = host->h_name;
+#endif
+
+ len = strlen(hnameptr) + 1;
+ result = malloc(len + sizeof(AUTHORIZATION_NAME) + 4);
+
+ p = result;
+ *p++ = sizeof(AUTHORIZATION_NAME) >> 8;
+ *p++ = sizeof(AUTHORIZATION_NAME) & 0xff;
+ *p++ = (len) >> 8;
+ *p++ = (len & 0xff);
+
+ memmove(p, AUTHORIZATION_NAME, sizeof(AUTHORIZATION_NAME));
+ p += sizeof(AUTHORIZATION_NAME);
+ memmove(p, hnameptr, len);
+ p += len;
+#if defined(IPv6) && defined(AF_INET6)
+ if (ai) {
+ freeaddrinfo(ai);
+ }
+#endif
+ }
+ *authlen = p - result;
+ *authorizations = result;
+ return 1;
+#else /* TCPCONN */
+ return 0;
+#endif /* TCPCONN */
+}
+
+void *
+Xalloc(unsigned long amount)
+{
+ /*
+ * Xalloc used to return NULL when large amount of memory is requested. In
+ * order to catch the buggy callers this warning has been added, slated to
+ * removal by anyone who touches this code (or just looks at it) in 2011.
+ *
+ * -- Mikhail Gusarov
+ */
+ if ((long)amount <= 0)
+ ErrorF("Warning: Xalloc: "
+ "requesting unpleasantly large amount of memory: %lu bytes.\n",
+ amount);
+
+ return malloc(amount);
+}
+
+void *
+XNFalloc(unsigned long amount)
+{
+ void *ptr = malloc(amount);
+ if (!ptr)
+ FatalError("Out of memory");
+ return ptr;
+}
+
+void *
+Xcalloc(unsigned long amount)
+{
+ return calloc(1, amount);
+}
+
+void *
+XNFcalloc(unsigned long amount)
+{
+ void *ret = calloc(1, amount);
+ if (!ret)
+ FatalError("XNFcalloc: Out of memory");
+ return ret;
+}
+
+void *
+Xrealloc(void *ptr, unsigned long amount)
+{
+ /*
+ * Xrealloc used to return NULL when large amount of memory is requested. In
+ * order to catch the buggy callers this warning has been added, slated to
+ * removal by anyone who touches this code (or just looks at it) in 2011.
+ *
+ * -- Mikhail Gusarov
+ */
+ if ((long)amount <= 0)
+ ErrorF("Warning: Xrealloc: "
+ "requesting unpleasantly large amount of memory: %lu bytes.\n",
+ amount);
+
+ return realloc(ptr, amount);
+}
+
+void *
+XNFrealloc(void *ptr, unsigned long amount)
+{
+ void *ret = realloc(ptr, amount);
+ if (!ret)
+ FatalError("XNFrealloc: Out of memory");
+ return ret;
+}
+
+void
+Xfree(void *ptr)
+{
+ free(ptr);
+}
+
+
+char *
+Xstrdup(const char *s)
+{
+ if (s == NULL)
+ return NULL;
+ return strdup(s);
+}
+
+char *
+XNFstrdup(const char *s)
+{
+ char *ret;
+
+ if (s == NULL)
+ return NULL;
+
+ ret = strdup(s);
+ if (!ret)
+ FatalError("XNFstrdup: Out of memory");
+ return ret;
+}
+
+void
+SmartScheduleStopTimer (void)
+{
+#ifdef _MSC_VER
+ if (SmartScheduleDisable)
+ return;
+ DeleteTimerQueueTimer(s_hSmartScheduleTimerQueue, s_hSmartScheduleTimer, NULL);
+ s_hSmartScheduleTimer=NULL;
+#else
+ 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
+}
+
+#ifdef _MSC_VER
+static VOID CALLBACK SmartScheduleTimer( PVOID lpParameter, BOOLEAN TimerOrWaitFired)
+#else
+static void SmartScheduleTimer (int sig)
+#endif
+{
+ SmartScheduleTime += SmartScheduleInterval;
+}
+
+
+void
+SmartScheduleStartTimer (void)
+{
+#ifdef _MSC_VER
+ if (SmartScheduleDisable)
+ return;
+
+ if (!CreateTimerQueueTimer( &s_hSmartScheduleTimer, s_hSmartScheduleTimerQueue, SmartScheduleTimer, NULL
+ , SmartScheduleInterval, SmartScheduleInterval, WT_EXECUTEONLYONCE|WT_EXECUTEINPERSISTENTTHREAD))
+ {
+ DWORD Error=GetLastError();
+ ErrorF("Error starting timer, smart scheduling disabled: 0x%x (%d)\n",Error,Error);
+ CloseHandle(s_hSmartScheduleTimer);
+ SmartScheduleDisable = TRUE;
+ return;
+ }
+#else
+ 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
+}
+
+void
+SmartScheduleInit (void)
+{
+#ifdef _MSC_VER
+ if (SmartScheduleDisable)
+ return;
+ s_hSmartScheduleTimerQueue = CreateTimerQueue();
+ if (!s_hSmartScheduleTimerQueue)
+ {
+ DWORD Error=GetLastError();
+ ErrorF("Error creating timer, smart scheduling disabled: 0x%x (%d)\n",Error,Error);
+ SmartScheduleDisable = TRUE;
+ }
+#else
+ struct sigaction act;
+
+ if (SmartScheduleDisable)
+ return;
+
+ memset((char *) &act, 0, sizeof(struct sigaction));
+
+ /* Set up the timer signal function */
+ act.sa_handler = SmartScheduleTimer;
+ sigemptyset (&act.sa_mask);
+ sigaddset (&act.sa_mask, SIGALRM);
+ if (sigaction (SIGALRM, &act, 0) < 0)
+ {
+ perror ("sigaction for smart scheduler");
+ SmartScheduleDisable = TRUE;
+ }
+#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);
+ sigaddset (&set, SIGALRM);
+ sigaddset (&set, SIGVTALRM);
+#ifdef SIGWINCH
+ sigaddset (&set, SIGWINCH);
+#endif
+#ifdef SIGIO
+ sigaddset (&set, SIGIO);
+#endif
+ sigaddset (&set, SIGTSTP);
+ sigaddset (&set, SIGTTIN);
+ sigaddset (&set, SIGTTOU);
+ sigaddset (&set, SIGCHLD);
+ sigprocmask (SIG_BLOCK, &set, &PreviousSignalMask);
+ }
+#endif
+}
+
+void
+OsReleaseSignals (void)
+{
+#ifdef SIG_BLOCK
+ if (--BlockedSignalCount == 0)
+ {
+ sigprocmask (SIG_SETMASK, &PreviousSignalMask, 0);
+ }
+#endif
+}
+
+/*
+ * Pending signals may interfere with core dumping. Provide a
+ * mechanism to block signals when aborting.
+ */
+
+void
+OsAbort (void)
+{
+#ifndef __APPLE__
+ OsBlockSignals();
+#endif
+ abort();
+}
+
+#if !defined(WIN32)
+/*
+ * "safer" versions of system(3), popen(3) and pclose(3) which give up
+ * all privs before running a command.
+ *
+ * This is based on the code in FreeBSD 2.2 libc.
+ *
+ * XXX It'd be good to redirect stderr so that it ends up in the log file
+ * as well. As it is now, xkbcomp messages don't end up in the log file.
+ */
+
+int
+System(char *command)
+{
+ int pid, p;
+ void (*csig)(int);
+ int status;
+
+ if (!command)
+ return 1;
+
+ csig = signal(SIGCHLD, SIG_DFL);
+ if (csig == SIG_ERR) {
+ perror("signal");
+ return -1;
+ }
+ DebugF("System: `%s'\n", command);
+
+ switch (pid = fork()) {
+ case -1: /* error */
+ p = -1;
+ case 0: /* child */
+ if (setgid(getgid()) == -1)
+ _exit(127);
+ if (setuid(getuid()) == -1)
+ _exit(127);
+ execl("/bin/sh", "sh", "-c", command, (char *)NULL);
+ _exit(127);
+ default: /* parent */
+ do {
+ p = waitpid(pid, &status, 0);
+ } while (p == -1 && errno == EINTR);
+
+ }
+
+ if (signal(SIGCHLD, csig) == SIG_ERR) {
+ perror("signal");
+ return -1;
+ }
+
+ return p == -1 ? -1 : status;
+}
+
+static struct pid {
+ struct pid *next;
+ FILE *fp;
+ int pid;
+} *pidlist;
+
+OsSigHandlerPtr old_alarm = NULL; /* XXX horrible awful hack */
+
+pointer
+Popen(char *command, char *type)
+{
+ struct pid *cur;
+ FILE *iop;
+ int pdes[2], pid;
+
+ if (command == NULL || type == NULL)
+ return NULL;
+
+ if ((*type != 'r' && *type != 'w') || type[1])
+ return NULL;
+
+ if ((cur = malloc(sizeof(struct pid))) == NULL)
+ return NULL;
+
+ if (pipe(pdes) < 0) {
+ free(cur);
+ return NULL;
+ }
+
+ /* Ignore the smart scheduler while this is going on */
+ old_alarm = OsSignal(SIGALRM, SIG_IGN);
+ if (old_alarm == SIG_ERR) {
+ close(pdes[0]);
+ close(pdes[1]);
+ free(cur);
+ perror("signal");
+ return NULL;
+ }
+
+ switch (pid = fork()) {
+ case -1: /* error */
+ close(pdes[0]);
+ close(pdes[1]);
+ free(cur);
+ if (OsSignal(SIGALRM, old_alarm) == SIG_ERR)
+ perror("signal");
+ return NULL;
+ case 0: /* child */
+ if (setgid(getgid()) == -1)
+ _exit(127);
+ if (setuid(getuid()) == -1)
+ _exit(127);
+ if (*type == 'r') {
+ if (pdes[1] != 1) {
+ /* stdout */
+ dup2(pdes[1], 1);
+ close(pdes[1]);
+ }
+ close(pdes[0]);
+ } else {
+ if (pdes[0] != 0) {
+ /* stdin */
+ dup2(pdes[0], 0);
+ close(pdes[0]);
+ }
+ close(pdes[1]);
+ }
+ execl("/bin/sh", "sh", "-c", command, (char *)NULL);
+ _exit(127);
+ }
+
+ /* Avoid EINTR during stdio calls */
+ OsBlockSignals ();
+
+ /* parent */
+ if (*type == 'r') {
+ iop = fdopen(pdes[0], type);
+ close(pdes[1]);
+ } else {
+ iop = fdopen(pdes[1], type);
+ close(pdes[0]);
+ }
+
+ cur->fp = iop;
+ cur->pid = pid;
+ cur->next = pidlist;
+ pidlist = cur;
+
+ DebugF("Popen: `%s', fp = %p\n", command, iop);
+
+ return iop;
+}
+
+/* fopen that drops privileges */
+pointer
+Fopen(char *file, char *type)
+{
+ FILE *iop;
+#ifndef HAS_SAVED_IDS_AND_SETEUID
+ struct pid *cur;
+ int pdes[2], pid;
+
+ if (file == NULL || type == NULL)
+ return NULL;
+
+ if ((*type != 'r' && *type != 'w') || type[1])
+ return NULL;
+
+ if ((cur = malloc(sizeof(struct pid))) == NULL)
+ return NULL;
+
+ if (pipe(pdes) < 0) {
+ free(cur);
+ return NULL;
+ }
+
+ switch (pid = fork()) {
+ case -1: /* error */
+ close(pdes[0]);
+ close(pdes[1]);
+ free(cur);
+ return NULL;
+ case 0: /* child */
+ if (setgid(getgid()) == -1)
+ _exit(127);
+ if (setuid(getuid()) == -1)
+ _exit(127);
+ if (*type == 'r') {
+ if (pdes[1] != 1) {
+ /* stdout */
+ dup2(pdes[1], 1);
+ close(pdes[1]);
+ }
+ close(pdes[0]);
+ } else {
+ if (pdes[0] != 0) {
+ /* stdin */
+ dup2(pdes[0], 0);
+ close(pdes[0]);
+ }
+ close(pdes[1]);
+ }
+ execl("/bin/cat", "cat", file, (char *)NULL);
+ _exit(127);
+ }
+
+ /* Avoid EINTR during stdio calls */
+ OsBlockSignals ();
+
+ /* parent */
+ if (*type == 'r') {
+ iop = fdopen(pdes[0], type);
+ close(pdes[1]);
+ } else {
+ iop = fdopen(pdes[1], type);
+ close(pdes[0]);
+ }
+
+ cur->fp = iop;
+ cur->pid = pid;
+ cur->next = pidlist;
+ pidlist = cur;
+
+ DebugF("Fopen(%s), fp = %p\n", file, iop);
+
+ return iop;
+#else
+ int ruid, euid;
+
+ ruid = getuid();
+ euid = geteuid();
+
+ if (seteuid(ruid) == -1) {
+ return NULL;
+ }
+ iop = fopen(file, type);
+
+ if (seteuid(euid) == -1) {
+ fclose(iop);
+ return NULL;
+ }
+ return iop;
+#endif /* HAS_SAVED_IDS_AND_SETEUID */
+}
+
+int
+Pclose(pointer iop)
+{
+ struct pid *cur, *last;
+ int pstat;
+ int pid;
+
+ DebugF("Pclose: fp = %p\n", iop);
+ fclose(iop);
+
+ for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next)
+ if (cur->fp == iop)
+ break;
+ if (cur == NULL)
+ return -1;
+
+ do {
+ pid = waitpid(cur->pid, &pstat, 0);
+ } while (pid == -1 && errno == EINTR);
+
+ if (last == NULL)
+ pidlist = cur->next;
+ else
+ last->next = cur->next;
+ free(cur);
+
+ /* allow EINTR again */
+ OsReleaseSignals ();
+
+ if (old_alarm && OsSignal(SIGALRM, old_alarm) == SIG_ERR) {
+ perror("signal");
+ return -1;
+ }
+
+ return pid == -1 ? -1 : pstat;
+}
+
+int
+Fclose(pointer iop)
+{
+#ifdef HAS_SAVED_IDS_AND_SETEUID
+ return fclose(iop);
+#else
+ return Pclose(iop);
+#endif
+}
+
+#endif /* !WIN32 */
+
+
+/*
+ * CheckUserParameters: check for long command line arguments and long
+ * environment variables. By default, these checks are only done when
+ * the server's euid != ruid. In 3.3.x, these checks were done in an
+ * external wrapper utility.
+ */
+
+/* Consider LD* variables insecure? */
+#ifndef _MSC_VER
+#ifndef REMOVE_ENV_LD
+#define REMOVE_ENV_LD 1
+#endif
+
+/* Remove long environment variables? */
+#ifndef REMOVE_LONG_ENV
+#define REMOVE_LONG_ENV 1
+#endif
+#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 2048
+#define MAX_ENV_PATH_LENGTH 2048 /* Limit for *PATH and TERMCAP */
+
+#if USE_ISPRINT
+#include <ctype.h>
+#define checkPrintable(c) isprint(c)
+#else
+#define checkPrintable(c) (((c) & 0x7f) >= 0x20 && ((c) & 0x7f) != 0x7f)
+#endif
+
+enum BadCode {
+ NotBad = 0,
+ UnsafeArg,
+ ArgTooLong,
+ UnprintableArg,
+ EnvTooLong,
+ OutputIsPipe,
+ InternalError
+};
+
+#if defined(VENDORSUPPORT)
+#define BUGADDRESS VENDORSUPPORT
+#elif defined(BUILDERADDR)
+#define BUGADDRESS BUILDERADDR
+#else
+#define BUGADDRESS "xorg@freedesktop.org"
+#endif
+
+void
+CheckUserParameters(int argc, char **argv, char **envp)
+{
+ enum BadCode bad = NotBad;
+ int i = 0, j;
+ char *a, *e = NULL;
+
+#if CHECK_EUID
+ if (geteuid() == 0 && getuid() != geteuid())
+#endif
+ {
+ /* Check each argv[] */
+ for (i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-fp") == 0)
+ {
+ i++; /* continue with next argument. skip the length check */
+ if (i >= argc)
+ break;
+ } else
+ {
+ if (strlen(argv[i]) > MAX_ARG_LENGTH) {
+ bad = ArgTooLong;
+ break;
+ }
+ }
+ a = argv[i];
+ while (*a) {
+ if (checkPrintable(*a) == 0) {
+ bad = UnprintableArg;
+ break;
+ }
+ a++;
+ }
+ if (bad)
+ break;
+ }
+ if (!bad) {
+ /* Check each envp[] */
+ for (i = 0; envp[i]; i++) {
+
+ /* Check for bad environment variables and values */
+#if REMOVE_ENV_LD
+ while (envp[i] && (strncmp(envp[i], "LD", 2) == 0)) {
+ for (j = i; envp[j]; j++) {
+ envp[j] = envp[j+1];
+ }
+ }
+#endif
+ if (envp[i] && (strlen(envp[i]) > MAX_ENV_LENGTH)) {
+#if REMOVE_LONG_ENV
+ for (j = i; envp[j]; j++) {
+ envp[j] = envp[j+1];
+ }
+ i--;
+#else
+ char *eq;
+ int len;
+
+ eq = strchr(envp[i], '=');
+ if (!eq)
+ continue;
+ len = eq - envp[i];
+ e = malloc(len + 1);
+ if (!e) {
+ bad = InternalError;
+ break;
+ }
+ strncpy(e, envp[i], len);
+ e[len] = 0;
+ if (len >= 4 &&
+ (strcmp(e + len - 4, "PATH") == 0 ||
+ strcmp(e, "TERMCAP") == 0)) {
+ if (strlen(envp[i]) > MAX_ENV_PATH_LENGTH) {
+ bad = EnvTooLong;
+ break;
+ } else {
+ free(e);
+ }
+ } else {
+ bad = EnvTooLong;
+ break;
+ }
+#endif
+ }
+ }
+ }
+#if NO_OUTPUT_PIPES
+ if (!bad) {
+ struct stat buf;
+
+ if (fstat(fileno(stdout), &buf) == 0 && S_ISFIFO(buf.st_mode))
+ bad = OutputIsPipe;
+ if (fstat(fileno(stderr), &buf) == 0 && S_ISFIFO(buf.st_mode))
+ bad = OutputIsPipe;
+ }
+#endif
+ }
+ switch (bad) {
+ case NotBad:
+ return;
+ case UnsafeArg:
+ ErrorF("Command line argument number %d is unsafe\n", i);
+ break;
+ case ArgTooLong:
+ ErrorF("Command line argument number %d is too long\n", i);
+ break;
+ case UnprintableArg:
+ ErrorF("Command line argument number %d contains unprintable"
+ " characters\n", i);
+ break;
+ case EnvTooLong:
+ ErrorF("Environment variable `%s' is too long\n", e);
+ break;
+ case OutputIsPipe:
+ ErrorF("Stdout and/or stderr is a pipe\n");
+ break;
+ case InternalError:
+ ErrorF("Internal Error\n");
+ break;
+ default:
+ ErrorF("Unknown error\n");
+ break;
+ }
+ FatalError("X server aborted because of unsafe environment\n");
+}
+
+/*
+ * CheckUserAuthorization: check if the user is allowed to start the
+ * X server. This usually means some sort of PAM checking, and it is
+ * usually only done for setuid servers (uid != euid).
+ */
+
+#ifdef USE_PAM
+#include <security/pam_appl.h>
+#include <security/pam_misc.h>
+#include <pwd.h>
+#endif /* USE_PAM */
+
+void
+CheckUserAuthorization(void)
+{
+#ifdef USE_PAM
+ static struct pam_conv conv = {
+ misc_conv,
+ NULL
+ };
+
+ pam_handle_t *pamh = NULL;
+ struct passwd *pw;
+ int retval;
+
+ if (getuid() != geteuid()) {
+ pw = getpwuid(getuid());
+ if (pw == NULL)
+ FatalError("getpwuid() failed for uid %d\n", getuid());
+
+ retval = pam_start("xserver", pw->pw_name, &conv, &pamh);
+ if (retval != PAM_SUCCESS)
+ FatalError("pam_start() failed.\n"
+ "\tMissing or mangled PAM config file or module?\n");
+
+ retval = pam_authenticate(pamh, 0);
+ if (retval != PAM_SUCCESS) {
+ pam_end(pamh, retval);
+ FatalError("PAM authentication failed, cannot start X server.\n"
+ "\tPerhaps you do not have console ownership?\n");
+ }
+
+ retval = pam_acct_mgmt(pamh, 0);
+ if (retval != PAM_SUCCESS) {
+ pam_end(pamh, retval);
+ FatalError("PAM authentication failed, cannot start X server.\n"
+ "\tPerhaps you do not have console ownership?\n");
+ }
+
+ /* this is not a session, so do not do session management */
+ pam_end(pamh, PAM_SUCCESS);
+ }
+#endif
+}
+
+/*
+ * Tokenize a string into a NULL terminated array of strings. Always returns
+ * an allocated array unless an error occurs.
+ */
+char**
+xstrtokenize(const char *str, const char *separators)
+{
+ char **list, **nlist;
+ char *tok, *tmp;
+ unsigned num = 0, n;
+
+ if (!str)
+ return NULL;
+ list = calloc(1, sizeof(*list));
+ if (!list)
+ return NULL;
+ tmp = strdup(str);
+ if (!tmp)
+ goto error;
+ for (tok = strtok(tmp, separators); tok; tok = strtok(NULL, separators)) {
+ nlist = realloc(list, (num + 2) * sizeof(*list));
+ if (!nlist)
+ goto error;
+ list = nlist;
+ list[num] = strdup(tok);
+ if (!list[num])
+ goto error;
+ list[++num] = NULL;
+ }
+ free(tmp);
+ return list;
+
+error:
+ free(tmp);
+ for (n = 0; n < num; n++)
+ free(list[n]);
+ free(list);
+ return NULL;
+}
diff --git a/xorg-server/os/xdmcp.c b/xorg-server/os/xdmcp.c
index 8da2cb05c..3958f06dc 100644
--- a/xorg-server/os/xdmcp.c
+++ b/xorg-server/os/xdmcp.c
@@ -62,6 +62,8 @@
static char *defaultDisplayClass = COMPILEDDISPLAYCLASS;
+extern void match_interface(u_long u_lQuery);
+
static int xdmcpSocket, sessionSocket;
static xdmcp_states state;
#if defined(IPv6) && defined(AF_INET6)
@@ -203,6 +205,11 @@ static void XdmcpWakeupHandler(
int /*i*/,
pointer /*LastSelectMask*/);
+#define XSERV_t
+#define TRANS_SERVER
+#define TRANS_REOPEN
+#include <X11/Xtrans/Xtrans.h>
+
/*
* Register the Manufacturer display ID
*/
@@ -587,6 +594,32 @@ XdmcpInit(void)
(pointer) 0);
timeOutRtx = 0;
DisplayNumber = (CARD16) atoi(display);
+ if (ConnectionTypes.length>1 && xdm_from==NULL)
+ {
+ unsigned i=0;
+ char ErrorMessage[1024];
+ sprintf(ErrorMessage,"Multiple ip-addresses detected:\n");
+ for (i=0; i<ConnectionTypes.length; i++)
+ {
+ int AddrLen=ConnectionAddresses.data[i].length;
+ if (AddrLen==4)
+ sprintf(ErrorMessage+strlen(ErrorMessage)," %d.%d.%d.%d\n",
+ ConnectionAddresses.data[i].data[0],
+ ConnectionAddresses.data[i].data[1],
+ ConnectionAddresses.data[i].data[2],
+ ConnectionAddresses.data[i].data[3]);
+ else
+ {
+ int j;
+ sprintf(ErrorMessage+strlen(ErrorMessage)," ");
+ for (j=0; j<AddrLen; j++)
+ sprintf(ErrorMessage+strlen(ErrorMessage),"%02x",ConnectionAddresses.data[i].data[j]);
+ sprintf(ErrorMessage+strlen(ErrorMessage),"\n");
+ }
+ }
+ sprintf(ErrorMessage+strlen(ErrorMessage),"Please specify the ip-address you want to use with -from\n");
+ FatalError(ErrorMessage);
+ }
get_xdmcp_sock();
send_packet();
}
@@ -661,8 +694,8 @@ XdmcpBlockHandler(
if (timeOutTime == 0)
return;
millisToGo = timeOutTime - GetTimeInMillis();
- if ((int) millisToGo < 0)
- millisToGo = 0;
+ if ((int) millisToGo <= 0)
+ millisToGo = 1;
AdjustWaitForDelay (wt, millisToGo);
}
@@ -706,18 +739,6 @@ XdmcpWakeupHandler(
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();
}
}
@@ -745,6 +766,37 @@ XdmcpSelectHost(
* selects the first host to respond with willing message.
*/
+#ifdef _MSC_VER
+void DisplayXdmcpHostsDialog(void);
+int XdmcpHostAddName(const char *HostName, int HostIndex);
+
+struct hostinfo
+{
+ struct sockaddr *from;
+ int fromlen;
+ ARRAY8 AuthenticationName;
+};
+static int g_NrHosts;
+static struct hostinfo *g_Hosts;
+
+void XdmcpHostSelected(int HostIdx)
+{
+ int i;
+
+ /* Connect to the selected host */
+ XdmcpSelectHost(g_Hosts[HostIdx].from, g_Hosts[HostIdx].fromlen, &g_Hosts[HostIdx].AuthenticationName);
+
+ for (i=0; i<g_NrHosts; i++)
+ {
+ free(g_Hosts[i].from);
+ free(g_Hosts[i].AuthenticationName.data);
+ }
+ free(g_Hosts);
+ g_Hosts=NULL;
+ g_NrHosts=0;
+}
+#endif
+
/*ARGSUSED*/
static void
XdmcpAddHost(
@@ -754,7 +806,35 @@ XdmcpAddHost(
ARRAY8Ptr hostname,
ARRAY8Ptr status)
{
- XdmcpSelectHost(from, fromlen, AuthenticationName);
+#ifdef _MSC_VER
+ char szHostName[100];
+ int HostIdx;
+
+ memcpy(szHostName,hostname->data,hostname->length);
+ szHostName[hostname->length]=0;
+
+ DisplayXdmcpHostsDialog(); /* Display the dialog if not already displayed */
+
+ HostIdx=XdmcpHostAddName(szHostName, g_NrHosts);
+ if (HostIdx==-1)
+ {
+ HostIdx=g_NrHosts;
+ g_NrHosts++;
+ g_Hosts=realloc(g_Hosts,g_NrHosts*sizeof(*g_Hosts));
+ g_Hosts[HostIdx].AuthenticationName.data=NULL;
+ g_Hosts[HostIdx].from=NULL;
+ }
+
+ g_Hosts[HostIdx].fromlen=fromlen;
+ g_Hosts[HostIdx].from=realloc(g_Hosts[HostIdx].from,g_Hosts[HostIdx].fromlen);
+ memcpy(g_Hosts[HostIdx].from,from,fromlen);
+
+ g_Hosts[HostIdx].AuthenticationName.length=AuthenticationName->length;
+ g_Hosts[HostIdx].AuthenticationName.data=realloc(g_Hosts[HostIdx].AuthenticationName.data,AuthenticationName->length);
+ memcpy(g_Hosts[HostIdx].AuthenticationName.data,AuthenticationName->data,AuthenticationName->length);
+#else
+ XdmcpSelectHost(from, fromlen, AuthenticationName);
+#endif
}
/*
@@ -1027,11 +1107,20 @@ get_xdmcp_sock(void)
sizeof(soopts)) < 0)
XdmcpWarning("UDP set broadcast socket-option failed");
#endif /* SO_BROADCAST */
- if (xdmcpSocket >= 0 && xdm_from != NULL) {
+ if (xdm_from)
+ {
+ if (xdmcpSocket >= 0 && SOCKADDR_FAMILY(FromAddress)==AF_INET) {
if (bind(xdmcpSocket, (struct sockaddr *)&FromAddress,
FromAddressLen) < 0) {
- FatalError("Xserver: failed to bind to -from address: %s\n", xdm_from);
+ FatalError("Xserver: failed to bind to -from address: %s error %d\n", xdm_from, WSAGetLastError());
}
+ }
+ else if (xdmcpSocket6 >= 0 && SOCKADDR_FAMILY(FromAddress)==AF_INET6) {
+ if (bind(xdmcpSocket6, (struct sockaddr *)&FromAddress,
+ FromAddressLen) < 0) {
+ FatalError("Xserver: failed to bind to -from address: %s error %d\n", xdm_from, WSAGetLastError());
+ }
+ }
}
#endif /* STREAMSCONN */
}
@@ -1095,15 +1184,15 @@ send_query_msg(void)
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;
+ int hopflag = mcl->hops;
socketfd = xdmcpSocket;
setsockopt(socketfd, IPPROTO_IP, IP_MULTICAST_TTL,
- &hopflag, sizeof(hopflag));
+ (char*)&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));
+ (char*)&hopflag6, sizeof(hopflag6));
} else {
continue;
}
@@ -1483,6 +1572,10 @@ get_addr_by_name(
char *pport = portstr;
int gaierr;
+#if defined(WIN32) && defined(TCPCONN)
+ _XSERVTransWSAStartup();
+#endif
+
memset(&hints, 0, sizeof(hints));
hints.ai_socktype = socktype;
@@ -1520,9 +1613,6 @@ get_addr_by_name(
#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
_Xgethostbynameparams hparams;
#endif
-#if defined(WIN32) && defined(TCPCONN)
- _XSERVTransWSAStartup();
-#endif
if (!(hep = _XGethostbyname(namestr, hparams)))
{
FatalError("Xserver: %s unknown host: %s\n", argtype, namestr);
@@ -1548,6 +1638,9 @@ get_manager_by_name(
int i)
{
+ PSOCKADDR_IN queryAddr = NULL;
+ u_long u_lqueryAddr = 0;
+
if ((i + 1) == argc)
{
FatalError("Xserver: missing %s host name in command line\n", argv[i]);
@@ -1559,6 +1652,9 @@ get_manager_by_name(
, &mgrAddr, &mgrAddrFirst
#endif
);
+ queryAddr = (PSOCKADDR_IN)&ManagerAddress;
+ u_lqueryAddr = queryAddr->sin_addr.S_un.S_addr;
+ match_interface(u_lqueryAddr);
}
diff --git a/xorg-server/os/xprintf.c b/xorg-server/os/xprintf.c
index 254b7374a..cc5a9b355 100644
--- a/xorg-server/os/xprintf.c
+++ b/xorg-server/os/xprintf.c
@@ -76,7 +76,9 @@
# ifdef __va_copy
# define va_copy __va_copy
# else
+# ifndef _MSC_VER
# error "no working va_copy was found"
+# endif
# endif
#endif
@@ -97,11 +99,16 @@ Xvasprintf(char **ret, const char * _X_RESTRICT_KYWD format, va_list va)
return vasprintf(ret, format, va);
#else
int size;
+
+#ifdef _MSC_VER
+ size = vsnprintf(NULL, 0, format, va);
+#else
va_list va2;
va_copy(va2, va);
size = vsnprintf(NULL, 0, format, va2);
va_end(va2);
+#endif
*ret = malloc(size + 1);
if (*ret == NULL)
diff --git a/xorg-server/os/xstrans.c b/xorg-server/os/xstrans.c
index c086e225b..dd75ab53e 100644
--- a/xorg-server/os/xstrans.c
+++ b/xorg-server/os/xstrans.c
@@ -5,4 +5,8 @@
#define TRANS_REOPEN
#define TRANS_SERVER
#define XSERV_t
+#ifndef TCPCONN
+#define TCPCONN
+#endif
+
#include <X11/Xtrans/transport.c>