diff options
Diffstat (limited to 'xorg-server/os')
-rw-r--r-- | xorg-server/os/Makefile.am | 122 | ||||
-rw-r--r-- | xorg-server/os/WaitFor.c | 6 | ||||
-rw-r--r-- | xorg-server/os/access.c | 363 | ||||
-rw-r--r-- | xorg-server/os/auth.c | 12 | ||||
-rw-r--r-- | xorg-server/os/client.c | 618 | ||||
-rw-r--r-- | xorg-server/os/connection.c | 80 | ||||
-rw-r--r-- | xorg-server/os/io.c | 1 | ||||
-rw-r--r-- | xorg-server/os/log.c | 18 | ||||
-rw-r--r-- | xorg-server/os/makefile | 49 | ||||
-rw-r--r-- | xorg-server/os/oscolor.c | 4 | ||||
-rw-r--r-- | xorg-server/os/osinit.c | 5 | ||||
-rw-r--r-- | xorg-server/os/utils.c | 3682 | ||||
-rw-r--r-- | xorg-server/os/xdmcp.c | 142 | ||||
-rw-r--r-- | xorg-server/os/xprintf.c | 7 | ||||
-rw-r--r-- | xorg-server/os/xstrans.c | 4 |
15 files changed, 2817 insertions, 2296 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 4eb2c15c7..da195df39 100644 --- a/xorg-server/os/connection.c +++ b/xorg-server/os/connection.c @@ -67,6 +67,9 @@ SOFTWARE. #ifdef WIN32
#include <X11/Xwinsock.h>
+#ifdef _DEBUG
+#define DEBUG
+#endif
#endif
#include <X11/X.h>
#include <X11/Xproto.h>
@@ -111,6 +114,10 @@ SOFTWARE. #include "dixstruct.h"
#include "xace.h"
+#ifdef _MSC_VER
+typedef int pid_t;
+#endif
+
#define Pid_t pid_t
@@ -142,11 +149,13 @@ 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 Pid_t ParentProcess;
static Bool debug_conns = FALSE;
@@ -269,6 +278,23 @@ lookup_trans_conn (int fd) 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
@@ -400,16 +426,19 @@ CreateWellKnownSockets(void) {
ListenTransFds = malloc(ListenTransCount * sizeof (int));
- for (i = 0; i < ListenTransCount; i++)
+ for (i = ListenTransCount; i > 0; i--)
{
- int fd = _XSERVTransGetConnectionNumber (ListenTransConns[i]);
+ int fd = _XSERVTransGetConnectionNumber (ListenTransConns[i-1]);
- ListenTransFds[i] = fd;
+ ListenTransFds[i-1] = fd;
FD_SET (fd, &WellKnownConnections);
- if (!_XSERVTransIsLocal (ListenTransConns[i]))
+ if (!_XSERVTransIsLocal (ListenTransConns[i-1]))
{
- DefineSelf (fd);
+ 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);
}
}
}
@@ -969,14 +998,16 @@ CheckConnections(void) {
#ifndef WIN32
fd_mask mask;
+ int curoff;
#endif
fd_set tmask;
- int curclient, curoff;
+ int curclient;
int i;
struct timeval notime;
int r;
#ifdef WIN32
- fd_set savedAllClients;
+ fd_set savedAllSockets;
+ unsigned j;
#endif
notime.tv_sec = 0;
@@ -1002,19 +1033,24 @@ CheckConnections(void) }
}
#else
- XFD_COPYSET(&AllClients, &savedAllClients);
- for (i = 0; i < XFD_SETCOUNT(&savedAllClients); i++)
+ /* First test AllSockets and then AllClients are valid sockets */
+ XFD_COPYSET(&AllSockets, &savedAllSockets);
+ for (j=0; j<2; j++)
{
- curclient = XFD_FD(&savedAllClients, i);
- FD_ZERO(&tmask);
- FD_SET(curclient, &tmask);
- do {
- r = Select (curclient + 1, &tmask, NULL, NULL, ¬ime);
- } while (r < 0 && (errno == EINTR || errno == EAGAIN));
- if (r < 0)
- if (GetConnectionTranslation(curclient) > 0)
- CloseDownClient(clients[GetConnectionTranslation(curclient)]);
- }
+ 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, ¬ime);
+ } while (r == SOCKET_ERROR && (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEWOULDBLOCK));
+ if (r < 0)
+ if (GetConnectionTranslation(curclient) > 0)
+ CloseDownClient(clients[GetConnectionTranslation(curclient)]);
+ }
+ XFD_COPYSET(&AllClients, &savedAllSockets);
+ }
#endif
}
@@ -1032,6 +1068,10 @@ CloseDownConnection(ClientPtr client) 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
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> |