autogen.sh | 13 +- configure.ac | 15 +- include/X11/extensions/XRes.h | 79 +++++++++++++ src/XRes.c | 238 +++++++++++++++++++++++++++++++++++++++--- 4 files changed, 322 insertions(+), 23 deletions(-)
New commits: commit 47f8ced17f5ef0a1f1539fd8837cd8f47aa0eb6e Author: Alan Coopersmith <[email protected]> Date: Sat Apr 13 10:34:22 2013 -0700 Use _XEatDataWords to avoid overflow of rep.length shifting rep.length is a CARD32, so rep.length << 2 could overflow in 32-bit builds Signed-off-by: Alan Coopersmith <[email protected]> diff --git a/configure.ac b/configure.ac index 5e3703b..b829cc1 100644 --- a/configure.ac +++ b/configure.ac @@ -50,6 +50,12 @@ XORG_CHECK_MALLOC_ZERO # Obtain compiler/linker options for depedencies PKG_CHECK_MODULES(XRES, [x11 >= 1.6] xext xextproto [resourceproto >= 1.2.0]) +# Check for _XEatDataWords function that may be patched into older Xlib release +SAVE_LIBS="$LIBS" +LIBS="$XRES_LIBS" +AC_CHECK_FUNCS([_XEatDataWords]) +LIBS="$SAVE_LIBS" + AC_CONFIG_FILES([Makefile src/Makefile man/Makefile commit 84b9156c7833dfd91c65d33542420ff4fe226948 Author: Adam Jackson <[email protected]> Date: Wed Oct 11 11:11:01 2017 -0400 libXRes 1.2.0 Signed-off-by: Adam Jackson <[email protected]> diff --git a/configure.ac b/configure.ac index b082de8..5e3703b 100644 --- a/configure.ac +++ b/configure.ac @@ -29,7 +29,7 @@ AC_PREREQ([2.60]) # digit in the version number to track changes which don't affect the # protocol, so XRes version l.n.m corresponds to protocol version l.n # -AC_INIT([libXres], [1.1.99.0], +AC_INIT([libXres], [1.2.0], [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], [libXres]) AC_CONFIG_SRCDIR([Makefile.am]) AC_CONFIG_HEADERS([config.h]) commit 1bc34457619c0d9b94ebd1cadac53366da20fbe3 Author: Mihail Konev <[email protected]> Date: Thu Jan 26 13:52:49 2017 +1000 autogen: add default patch prefix Signed-off-by: Mihail Konev <[email protected]> diff --git a/autogen.sh b/autogen.sh index 0006de8..86e51a2 100755 --- a/autogen.sh +++ b/autogen.sh @@ -9,6 +9,9 @@ cd "$srcdir" autoreconf -v --install || exit 1 cd "$ORIGDIR" || exit $? +git config --local --get format.subjectPrefix >/dev/null 2>&1 || + git config --local format.subjectPrefix "PATCH libXRes" + if test -z "$NOCONFIGURE"; then exec "$srcdir"/configure "$@" fi commit e5fbb99729d460eda477bf6e299728bc47542ccb Author: Emil Velikov <[email protected]> Date: Mon Mar 9 12:00:52 2015 +0000 autogen.sh: use quoted string variables Place quotes around the $srcdir, $ORIGDIR and $0 variables to prevent fall-outs, when they contain space. Signed-off-by: Emil Velikov <[email protected]> Reviewed-by: Peter Hutterer <[email protected]> Signed-off-by: Peter Hutterer <[email protected]> diff --git a/autogen.sh b/autogen.sh index fd9c59a..0006de8 100755 --- a/autogen.sh +++ b/autogen.sh @@ -1,14 +1,14 @@ #! /bin/sh -srcdir=`dirname $0` +srcdir=`dirname "$0"` test -z "$srcdir" && srcdir=. ORIGDIR=`pwd` -cd $srcdir +cd "$srcdir" autoreconf -v --install || exit 1 -cd $ORIGDIR || exit $? +cd "$ORIGDIR" || exit $? if test -z "$NOCONFIGURE"; then - exec $srcdir/configure "$@" + exec "$srcdir"/configure "$@" fi commit 16b2d184302d259a8481693285976045386fcc01 Author: Peter Hutterer <[email protected]> Date: Tue Jan 24 10:32:07 2017 +1000 autogen.sh: use exec instead of waiting for configure to finish Syncs the invocation of configure with the one from the server. Signed-off-by: Peter Hutterer <[email protected]> Reviewed-by: Emil Velikov <[email protected]> diff --git a/autogen.sh b/autogen.sh index fc34bd5..fd9c59a 100755 --- a/autogen.sh +++ b/autogen.sh @@ -10,5 +10,5 @@ autoreconf -v --install || exit 1 cd $ORIGDIR || exit $? if test -z "$NOCONFIGURE"; then - $srcdir/configure "$@" + exec $srcdir/configure "$@" fi commit ae0ddaa9c960aee1b7845da01270b00177f95f3d Author: Alan Coopersmith <[email protected]> Date: Fri Nov 22 23:22:36 2013 -0800 Remove fallback for _XEatDataWords, require libX11 1.6 for it _XEatDataWords was orignally introduced with the May 2013 security patches, and in order to ease the process of delivering those, fallback versions of _XEatDataWords were included in the X extension library patches so they could be applied to older versions that didn't have libX11 1.6 yet. Now that we're past that hurdle, we can drop the fallbacks and just require libX11 1.6 for building new versions of the extension libraries. Signed-off-by: Alan Coopersmith <[email protected]> diff --git a/configure.ac b/configure.ac index f68b689..b082de8 100644 --- a/configure.ac +++ b/configure.ac @@ -48,13 +48,7 @@ XORG_DEFAULT_OPTIONS XORG_CHECK_MALLOC_ZERO # Obtain compiler/linker options for depedencies -PKG_CHECK_MODULES(XRES, x11 xext xextproto [resourceproto >= 1.2.0]) - -# Check for _XEatDataWords function that may be patched into older Xlib release -SAVE_LIBS="$LIBS" -LIBS="$XRES_LIBS" -AC_CHECK_FUNCS([_XEatDataWords]) -LIBS="$SAVE_LIBS" +PKG_CHECK_MODULES(XRES, [x11 >= 1.6] xext xextproto [resourceproto >= 1.2.0]) AC_CONFIG_FILES([Makefile src/Makefile diff --git a/src/XRes.c b/src/XRes.c index 89fab82..2bee277 100644 --- a/src/XRes.c +++ b/src/XRes.c @@ -15,17 +15,6 @@ #include <assert.h> #include <limits.h> -#ifndef HAVE__XEATDATAWORDS -static inline void _XEatDataWords(Display *dpy, unsigned long n) -{ -# ifndef LONG64 - if (n >= (ULONG_MAX >> 2)) - _XIOError(dpy); -# endif - _XEatData (dpy, n << 2); -} -#endif - static XExtensionInfo _xres_ext_info_data; static XExtensionInfo *xres_ext_info = &_xres_ext_info_data; static const char *xres_extension_name = XRES_NAME; commit 0f5cfdc3136dd8ef43800bda64f9d39e6b23b2e9 Author: Julien Cristau <[email protected]> Date: Sun Jun 30 20:09:49 2013 +0200 Compute number of bytes correctly in XResQueryClientPixmapBytes 64-bit servers send the upper 32-bit in bytes_overflow. We were multiplying by 2^32 - 1 instead of 2^32 when putting things back together. Debian bug#621702 Reported-by: Kevin Ryde <[email protected]> Signed-off-by: Julien Cristau <[email protected]> Reviewed-by: Alan Coopersmith <[email protected]> diff --git a/src/XRes.c b/src/XRes.c index 51e905f..89fab82 100644 --- a/src/XRes.c +++ b/src/XRes.c @@ -240,7 +240,7 @@ Status XResQueryClientPixmapBytes ( } #ifdef LONG64 - *bytes = (rep.bytes_overflow * 4294967295) + rep.bytes; + *bytes = (rep.bytes_overflow * 4294967296UL) + rep.bytes; #else *bytes = rep.bytes_overflow ? 0xffffffff : rep.bytes; #endif commit f468184963e53feda848853c4aefd0197b2cc116 Author: Alan Coopersmith <[email protected]> Date: Fri Apr 12 23:36:13 2013 -0700 integer overflow in XResQueryClientResources() [CVE-2013-1988 2/2] The CARD32 rep.num_types needs to be bounds checked before multiplying by sizeof(XResType) to avoid integer overflow leading to underallocation and writing data from the network past the end of the allocated buffer. Reported-by: Ilja Van Sprundel <[email protected]> Signed-off-by: Alan Coopersmith <[email protected]> diff --git a/src/XRes.c b/src/XRes.c index c989985..51e905f 100644 --- a/src/XRes.c +++ b/src/XRes.c @@ -187,7 +187,12 @@ Status XResQueryClientResources ( } if(rep.num_types) { - if((typs = Xmalloc(sizeof(XResType) * rep.num_types))) { + if (rep.num_types < (INT_MAX / sizeof(XResType))) + typs = Xmalloc(sizeof(XResType) * rep.num_types); + else + typs = NULL; + + if (typs != NULL) { xXResType scratch; int i; commit b053d215b80e721f9afdc5794e4f3f4f2aee0141 Author: Alan Coopersmith <[email protected]> Date: Fri Apr 12 23:36:13 2013 -0700 integer overflow in XResQueryClients() [CVE-2013-1988 1/2] The CARD32 rep.num_clients needs to be bounds checked before multiplying by sizeof(XResClient) to avoid integer overflow leading to underallocation and writing data from the network past the end of the allocated buffer. Reported-by: Ilja Van Sprundel <[email protected]> Signed-off-by: Alan Coopersmith <[email protected]> diff --git a/src/XRes.c b/src/XRes.c index 1ab1db8..c989985 100644 --- a/src/XRes.c +++ b/src/XRes.c @@ -130,7 +130,12 @@ Status XResQueryClients ( } if(rep.num_clients) { - if((clnts = Xmalloc(sizeof(XResClient) * rep.num_clients))) { + if (rep.num_clients < (INT_MAX / sizeof(XResClient))) + clnts = Xmalloc(sizeof(XResClient) * rep.num_clients); + else + clnts = NULL; + + if (clnts != NULL) { xXResClient scratch; int i; commit 69457711050ac3a53859ef11790a7ac815cd7d94 Author: Alan Coopersmith <[email protected]> Date: Sat Apr 13 10:34:22 2013 -0700 Use _XEatDataWords to avoid overflow of rep.length shifting rep.length is a CARD32, so rep.length << 2 could overflow in 32-bit builds Signed-off-by: Alan Coopersmith <[email protected]> diff --git a/configure.ac b/configure.ac index 90205cc..f68b689 100644 --- a/configure.ac +++ b/configure.ac @@ -50,6 +50,12 @@ XORG_CHECK_MALLOC_ZERO # Obtain compiler/linker options for depedencies PKG_CHECK_MODULES(XRES, x11 xext xextproto [resourceproto >= 1.2.0]) +# Check for _XEatDataWords function that may be patched into older Xlib release +SAVE_LIBS="$LIBS" +LIBS="$XRES_LIBS" +AC_CHECK_FUNCS([_XEatDataWords]) +LIBS="$SAVE_LIBS" + AC_CONFIG_FILES([Makefile src/Makefile man/Makefile diff --git a/src/XRes.c b/src/XRes.c index 1744196..1ab1db8 100644 --- a/src/XRes.c +++ b/src/XRes.c @@ -13,6 +13,18 @@ #include <X11/extensions/XResproto.h> #include <X11/extensions/XRes.h> #include <assert.h> +#include <limits.h> + +#ifndef HAVE__XEATDATAWORDS +static inline void _XEatDataWords(Display *dpy, unsigned long n) +{ +# ifndef LONG64 + if (n >= (ULONG_MAX >> 2)) + _XIOError(dpy); +# endif + _XEatData (dpy, n << 2); +} +#endif static XExtensionInfo _xres_ext_info_data; static XExtensionInfo *xres_ext_info = &_xres_ext_info_data; @@ -131,7 +143,7 @@ Status XResQueryClients ( *num_clients = rep.num_clients; result = 1; } else { - _XEatData(dpy, rep.length << 2); + _XEatDataWords(dpy, rep.length); } } @@ -183,7 +195,7 @@ Status XResQueryClientResources ( *num_types = rep.num_types; result = 1; } else { - _XEatData(dpy, rep.length << 2); + _XEatDataWords(dpy, rep.length); } } commit 83e7693515369d57dcd11c2bb1f03563f51bc500 Author: Alan Coopersmith <[email protected]> Date: Fri Jan 18 23:06:20 2013 -0800 Replace deprecated Automake INCLUDES variable with AM_CPPFLAGS Excerpt https://lists.gnu.org/archive/html/automake/2012-12/msg00038.html - Support for the long-deprecated INCLUDES variable will be removed altogether in Automake 1.14. The AM_CPPFLAGS variable should be used instead. This variable was deprecated in Automake releases prior to 1.10, which is the current minimum level required to build X. Signed-off-by: Alan Coopersmith <[email protected]> diff --git a/src/Makefile.am b/src/Makefile.am index fd508da..bf66d68 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -10,7 +10,7 @@ AM_CFLAGS = \ $(XRES_CFLAGS) \ $(MALLOC_ZERO_CFLAGS) -INCLUDES = -I$(top_srcdir)/include +AM_CPPFLAGS = -I$(top_srcdir)/include libXRes_la_LDFLAGS = -version-number 1:0:0 -no-undefined commit d9324b7d07294bb18e4902596a1b8ee387188364 Author: Colin Walters <[email protected]> Date: Wed Jan 4 17:37:06 2012 -0500 autogen.sh: Implement GNOME Build API http://people.gnome.org/~walters/docs/build-api.txt Signed-off-by: Adam Jackson <[email protected]> diff --git a/autogen.sh b/autogen.sh index 904cd67..fc34bd5 100755 --- a/autogen.sh +++ b/autogen.sh @@ -9,4 +9,6 @@ cd $srcdir autoreconf -v --install || exit 1 cd $ORIGDIR || exit $? -$srcdir/configure --enable-maintainer-mode "$@" +if test -z "$NOCONFIGURE"; then + $srcdir/configure "$@" +fi commit 6d1f115422cde2bfca4b69caa395345f3ac454e7 Author: Adam Jackson <[email protected]> Date: Tue Jan 15 14:28:48 2013 -0500 configure: Remove AM_MAINTAINER_MODE Signed-off-by: Adam Jackson <[email protected]> diff --git a/configure.ac b/configure.ac index 0079857..90205cc 100644 --- a/configure.ac +++ b/configure.ac @@ -36,7 +36,6 @@ AC_CONFIG_HEADERS([config.h]) # Initialize Automake AM_INIT_AUTOMAKE([foreign dist-bzip2]) -AM_MAINTAINER_MODE # Initialize libtool AC_PROG_LIBTOOL commit f44f4e265ec3ab7ef87d6d7009ec079ba4c49336 Author: Alan Coopersmith <[email protected]> Date: Mon Apr 23 18:57:48 2012 -0700 Bump version to 1.1.99.0 to reflect addition of 1.2 API As noted in configure.ac comment, we try to keep library version based on the protocol version number, so since the protocol skipped to 1.2, we'll do that with the library as well for simplicity's sake. Sets resourceproto requirement to version 1.2.0 since there were no intermediate/snapshot versions between 1.1.2 & 1.2.0. Signed-off-by: Alan Coopersmith <[email protected]> diff --git a/configure.ac b/configure.ac index bc4e8a6..0079857 100644 --- a/configure.ac +++ b/configure.ac @@ -29,7 +29,7 @@ AC_PREREQ([2.60]) # digit in the version number to track changes which don't affect the # protocol, so XRes version l.n.m corresponds to protocol version l.n # -AC_INIT([libXres], [1.0.6], +AC_INIT([libXres], [1.1.99.0], [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], [libXres]) AC_CONFIG_SRCDIR([Makefile.am]) AC_CONFIG_HEADERS([config.h]) @@ -48,12 +48,8 @@ XORG_MACROS_VERSION(1.8) XORG_DEFAULT_OPTIONS XORG_CHECK_MALLOC_ZERO -# Check xres configuration, strip extra digits from package version to -# find the required protocol version -RES_VERSION=[`echo $VERSION | sed 's/^\([0-9][0-9]*\.[0-9][0-9]*\).*$/\1/'`] - # Obtain compiler/linker options for depedencies -PKG_CHECK_MODULES(XRES, x11 xext xextproto [resourceproto >= $RES_VERSION]) +PKG_CHECK_MODULES(XRES, x11 xext xextproto [resourceproto >= 1.2.0]) AC_CONFIG_FILES([Makefile src/Makefile commit 01fc6f81f0a2935741dd1114aa3fa267d8be9095 Author: Erkki Seppälä <[email protected]> Date: Wed Dec 15 13:48:09 2010 +0200 Implemented second part of XResource extension v1.2: XResQueryResourceBytes Signed-off-by: Erkki Seppälä <[email protected]> Reviewed-by: Rami Ylimäki <[email protected]> Reviewed-by: Tiago Vignatti <[email protected]> Signed-off-by: Alan Coopersmith <[email protected]> diff --git a/include/X11/extensions/XRes.h b/include/X11/extensions/XRes.h index b9759e3..1c81616 100644 --- a/include/X11/extensions/XRes.h +++ b/include/X11/extensions/XRes.h @@ -43,6 +43,24 @@ typedef struct { void *value; } XResClientIdValue; +typedef struct { + XID resource; + Atom type; +} XResResourceIdSpec; + +typedef struct { + XResResourceIdSpec spec; + long bytes; + long ref_count; + long use_count; +} XResResourceSizeSpec; + +typedef struct { + XResResourceSizeSpec size; + long num_cross_references; + XResResourceSizeSpec *cross_references; +} XResResourceSizeValue; + _XFUNCPROTOBEGIN /* v1.0 */ @@ -98,6 +116,20 @@ void XResClientIdsDestroy ( XResClientIdValue *client_ids ); +Status XResQueryResourceBytes ( + Display *dpy, + XID client, + long num_specs, + XResResourceIdSpec *resource_specs, /* in */ + long *num_sizes, /* out */ + XResResourceSizeValue **sizes /* out */ +); + +void XResResourceSizeValuesDestroy ( + long num_sizes, + XResResourceSizeValue *sizes +); + _XFUNCPROTOEND #endif /* _XRES_H */ diff --git a/src/XRes.c b/src/XRes.c index 0781666..1744196 100644 --- a/src/XRes.c +++ b/src/XRes.c @@ -237,7 +237,7 @@ static Bool ReadClientValues( int c; for (c = 0; c < num_ids; ++c) { XResClientIdValue* client = client_ids + c; - CARD32 value; + long int value; _XRead32 (dpy, &value, 4); client->spec.client = value; _XRead32 (dpy, &value, 4); @@ -344,3 +344,111 @@ pid_t XResGetClientPid( return (pid_t) -1; } } + +static Status ReadResourceSizeSpec( + Display *dpy, + XResResourceSizeSpec *size +) +{ + long int value; + _XRead32(dpy, &value, 4); + size->spec.resource = value; + _XRead32(dpy, &value, 4); + size->spec.type = value; + _XRead32(dpy, &value, 4); + size->bytes = value; + _XRead32(dpy, &value, 4); + size->ref_count = value; + _XRead32(dpy, &value, 4); + size->use_count = value; + return 0; +} + +static Status ReadResourceSizeValues( + Display *dpy, + long num_sizes, + XResResourceSizeValue *sizes) +{ + int c; + int d; + for (c = 0; c < num_sizes; ++c) { + long int num; + ReadResourceSizeSpec(dpy, &sizes[c].size); + _XRead32(dpy, &num, 4); + sizes[c].num_cross_references = num; + sizes[c].cross_references = num ? calloc(num, sizeof(*sizes[c].cross_references)) : NULL; + for (d = 0; d < num; ++d) { + ReadResourceSizeSpec(dpy, &sizes[c].cross_references[d]); + } + } + return Success; +} + +Status XResQueryResourceBytes ( + Display *dpy, + XID client, + long num_specs, + XResResourceIdSpec *resource_specs, /* in */ + long *num_sizes, /* out */ + XResResourceSizeValue **sizes /* out */ +) +{ + XExtDisplayInfo *info = find_display (dpy); + xXResQueryResourceBytesReq *req; + xXResQueryResourceBytesReply rep; + int c; + + *num_sizes = 0; + + XResCheckExtension (dpy, info, 0); + + LockDisplay (dpy); + GetReq (XResQueryResourceBytes, req); + req->reqType = info->codes->major_opcode; + req->XResReqType = X_XResQueryResourceBytes; + req->length += num_specs * 2; /* 2 longs per client id spec */ + req->client = client; + req->numSpecs = num_specs; + + for (c = 0; c < num_specs; ++c) { + Data32(dpy, &resource_specs[c].resource, 4); + Data32(dpy, &resource_specs[c].type, 4); + } + + *num_sizes = 0; + *sizes = NULL; + + if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) { + goto error; + } + + *sizes = calloc(rep.numSizes, sizeof(**sizes)); + *num_sizes = rep.numSizes; + + if (ReadResourceSizeValues(dpy, *num_sizes, *sizes) != Success) { + goto error; + } + + UnlockDisplay (dpy); + SyncHandle (); + return Success; + + error: + XResResourceSizeValuesDestroy(*num_sizes, *sizes); + + UnlockDisplay (dpy); + SyncHandle (); + return !Success; +} + +void XResResourceSizeValuesDestroy ( + long num_sizes, + XResResourceSizeValue *sizes +) +{ + int c; + for (c = 0; c < num_sizes; ++c) { + free(sizes[c].cross_references); + } + free(sizes); +} commit 0f38938a27df1f865dcdda35f4d2ef191092ba42 Author: Erkki Seppälä <[email protected]> Date: Mon Nov 29 12:43:51 2010 +0200 Implemented first part of XResource extension v1.2: XResQueryClientIds Signed-off-by: Erkki Seppälä <[email protected]> Reviewed-by: Rami Ylimäki <[email protected]> Reviewed-by: Tiago Vignatti <[email protected]> Signed-off-by: Alan Coopersmith <[email protected]> diff --git a/include/X11/extensions/XRes.h b/include/X11/extensions/XRes.h index ed4b2b8..b9759e3 100644 --- a/include/X11/extensions/XRes.h +++ b/include/X11/extensions/XRes.h @@ -7,6 +7,8 @@ #include <X11/Xfuncproto.h> +/* v1.0 */ + typedef struct { XID resource_base; XID resource_mask; @@ -17,8 +19,33 @@ typedef struct { unsigned int count; } XResType; +/* v1.2 */ + +typedef enum { + XRES_CLIENT_ID_XID, + XRES_CLIENT_ID_PID, + XRES_CLIENT_ID_NR +} XResClientIdType; + +typedef enum { + XRES_CLIENT_ID_XID_MASK = 1 << XRES_CLIENT_ID_XID, + XRES_CLIENT_ID_PID_MASK = 1 << XRES_CLIENT_ID_PID +} XResClientIdMask; + +typedef struct { + XID client; + unsigned int mask; +} XResClientIdSpec; + +typedef struct { + XResClientIdSpec spec; + long length; + void *value; +} XResClientIdValue; + _XFUNCPROTOBEGIN +/* v1.0 */ Bool XResQueryExtension ( Display *dpy, @@ -51,6 +78,26 @@ Status XResQueryClientPixmapBytes ( unsigned long *bytes ); +/* v1.2 */ + +Status XResQueryClientIds ( + Display *dpy, + long num_specs, + XResClientIdSpec *client_specs, /* in */ + long *num_ids, /* out */ + XResClientIdValue **client_ids /* out */ +); + +XResClientIdType XResGetClientIdType(XResClientIdValue* value); + +/* return -1 if no pid associated to the value */ +pid_t XResGetClientPid(XResClientIdValue* value); + +void XResClientIdsDestroy ( + long num_ids, + XResClientIdValue *client_ids +); + _XFUNCPROTOEND #endif /* _XRES_H */ diff --git a/src/XRes.c b/src/XRes.c index 6091c96..0781666 100644 --- a/src/XRes.c +++ b/src/XRes.c @@ -12,7 +12,7 @@ #include <X11/extensions/extutil.h> #include <X11/extensions/XResproto.h> #include <X11/extensions/XRes.h> - +#include <assert.h> static XExtensionInfo _xres_ext_info_data; static XExtensionInfo *xres_ext_info = &_xres_ext_info_data; @@ -228,3 +228,119 @@ Status XResQueryClientPixmapBytes ( return 1; } +static Bool ReadClientValues( + Display *dpy, + long num_ids, + XResClientIdValue *client_ids /* out */ +) +{ + int c; + for (c = 0; c < num_ids; ++c) { + XResClientIdValue* client = client_ids + c; + CARD32 value; + _XRead32 (dpy, &value, 4); + client->spec.client = value; + _XRead32 (dpy, &value, 4); + client->spec.mask = value; + _XRead32 (dpy, &value, 4); + client->length = value; + client->value = malloc(client->length); + _XRead32 (dpy, client->value, client->length); + } + return True; +} + +Status XResQueryClientIds ( + Display *dpy, + long num_specs, + XResClientIdSpec *client_specs, /* in */ + long *num_ids, /* out */ + XResClientIdValue **client_ids /* out */ +) +{ + XExtDisplayInfo *info = find_display (dpy); + xXResQueryClientIdsReq *req; + xXResQueryClientIdsReply rep; + int c; + + *num_ids = 0; + + XResCheckExtension (dpy, info, 0); + LockDisplay (dpy); + GetReq (XResQueryClientIds, req); + req->reqType = info->codes->major_opcode; + req->XResReqType = X_XResQueryClientIds; + req->length += num_specs * 2; /* 2 longs per client id spec */ + req->numSpecs = num_specs; + + for (c = 0; c < num_specs; ++c) { + Data32(dpy, &client_specs[c].client, 4); + Data32(dpy, &client_specs[c].mask, 4); + } + + if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) { + goto error; + } + + *client_ids = calloc(rep.numIds, sizeof(**client_ids)); + *num_ids = rep.numIds; + + if (!ReadClientValues(dpy, *num_ids, *client_ids)) { + goto error; + } + + UnlockDisplay (dpy); + SyncHandle (); + return Success; + + error: + XResClientIdsDestroy (*num_ids, *client_ids); + *client_ids = NULL; + + UnlockDisplay (dpy); + SyncHandle (); + return !Success; +} + +void XResClientIdsDestroy ( + long num_ids, + XResClientIdValue *client_ids +) +{ + int c; + for (c = 0; c < num_ids; ++c) { + free(client_ids[c].value); + } + free(client_ids); +} + +XResClientIdType XResGetClientIdType( + XResClientIdValue* value +) +{ + int bit; + XResClientIdType idType = 0; + Bool found = False; + for (bit = 0; bit < XRES_CLIENT_ID_NR; ++bit) { + if (value->spec.mask & (1 << bit)) { + assert(!found); + found = True; + idType = bit; + } + } + + assert(found); + + return idType; +} + +pid_t XResGetClientPid( + XResClientIdValue* value +) +{ + if (value->spec.mask & XRES_CLIENT_ID_PID_MASK && value->length >= 4) { + return (pid_t) * (CARD32*) value->value; + } else { + return (pid_t) -1; + } +}

