Skip to content

Instantly share code, notes, and snippets.

@andr1972
Last active December 2, 2015 23:16
Show Gist options
  • Save andr1972/b86b554c3617874be65a to your computer and use it in GitHub Desktop.
Save andr1972/b86b554c3617874be65a to your computer and use it in GitHub Desktop.
Setup information from X11 protocol
#pragma once
typedef uint64_t CARD64;
typedef uint32_t CARD32;
typedef uint16_t CARD16;
typedef unsigned char CARD8;
typedef CARD8 BYTE;
typedef CARD8 BOOL;
//from X.h
typedef unsigned char KeyCode;
typedef CARD32 XID;
typedef XID Window;
typedef XID Drawable;
typedef XID Font;
typedef XID Pixmap;
typedef XID Cursor;
typedef XID Colormap;
typedef XID GContext;
typedef XID KeySym;
typedef CARD32 VisualID;
//analogously to Xproto.h from z x11proto-core_*.orig.tar.gz from http://x11proto-core.sourcearchive.com/downloads/7.0.24-1/
#pragma pack(push)
#pragma pack(1)
typedef struct {
CARD8 depth;
CARD8 bitsPerPixel;
CARD8 scanLinePad;
CARD8 pad1;
CARD32 pad2;
} yPixmapFormat;
typedef struct {
VisualID visualID;
CARD8 c_class;
CARD8 bitsPerRGB;
CARD16 colormapEntries;
CARD32 redMask,
greenMask,
blueMask;
CARD32 pad;
} yVisualType;
typedef struct {
CARD8 depth;
CARD8 pad1;
CARD16 nVisuals; /* number of xVisualType structures following */
CARD32 pad2;
//variable part
yVisualType *visuals;
} yDepth;
typedef struct {
Window windowId;
Colormap defaultColormap;
CARD32 whitePixel,
blackPixel;
CARD32 currentInputMask;
CARD16 pixWidth,
pixHeight;
CARD16 mmWidth,
mmHeight;
CARD16 minInstalledMaps,
maxInstalledMaps;
VisualID rootVisualID;
CARD8 backingStore;
BOOL saveUnders;
CARD8 rootDepth;
CARD8 nDepths; // number of xDepth structures following
//variable part
yDepth *depths; //allowed depths;
} yWindowRoot;
typedef struct {
CARD8 status; //Success
BYTE pad0;
CARD16 majorVersion, //protocol-major-version
minorVersion; //protocol-minor-version
CARD16 length; // 1/4 additional bytes in setup info
CARD32 release; //release-number
CARD32 ridBase, //resource-id-base
ridMask; //resource-id-mask
CARD32 motionBufferSize;
CARD16 vendorLen; // number of bytes in vendor string
CARD16 maxRequestSize;
CARD8 numRoots; // number of roots structs to follow
CARD8 numFormats; // number of pixmap formats
CARD8 imageByteOrder; // LSBFirst, MSBFirst
CARD8 bitmapBitOrder; // LeastSignificant, MostSign...
CARD8 bitmapScanlineUnit, // 8, 16, 32
bitmapScanlinePad; // 8, 16, 32
KeyCode minKeyCode, maxKeyCode;
CARD32 pad1;
//variable part
char *vendor;
yPixmapFormat *pixmapFormats;
yWindowRoot *roots;
} yConnSetup;
// Information received by the client if the connection is refused:
typedef struct {
CARD8 status; //Failed
CARD8 lenReason; //in bytes
CARD16 majorVersion, //protocol-major-version
minorVersion; //protocol-minor-version
CARD16 length; //length in 4-byte units of string Reason with pad
} yConnFailStub;
//Information received by the client if further authentication is required:
typedef struct {
CARD8 status; //Authenticate
CARD8 pad0;
CARD16 pad1,
pad2;
CARD16 length; //length in 4-byte units of string Reason with pad
} yConnAuthStub;
//Information received by the client if the connection is accepted:
typedef struct {
CARD8 status; //Success
CARD8 pad0;
CARD16 majorVersion, //protocol-major-version
minorVersion; //protocol-minor-version
CARD16 length; //length in 4-byte units of string Reason with pad
} yConnSuccessStub;
typedef struct {
CARD8 byteOrder; //l for little-endian, B for big-endian
BYTE pad0;
CARD16 majorVersion, //protocol major version
minorVersion; //protocol minor version
CARD16 lenAuthProto; // length authorization protocol
CARD16 lenAuthString; // length authorization string
CARD16 pad1;
} yConnClientStub;
#pragma pack(pop)
// size of constant part of structure
#define sizePixmapFormat sizeof(yPixmapFormat)
#define sizeVisualType sizeof(yVisualType)
#define sizeDepth sizeof(yDepth)-sizeof(yVisualType *)
#define sizeWindowRoot sizeof(yWindowRoot)-sizeof(yDepth *)
#define sizeConnSetup sizeof(yConnSetup)-sizeof(char*)-sizeof(yPixmapFormat*)-sizeof(yWindowRoot*)
#define PAD(E) (4 - (E % 4)) % 4
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include "setup.h"
//reply to CreateConnectionBlock() from dispatch.c from xorg-x11-server-source-*.rpm
//return: 0: ok; 1: too short buffer; 2:too long buffer
int ParseConnectionBlock(unsigned char* buf, size_t size, yConnSetup* setup)
{
setup->vendor = NULL;
setup->pixmapFormats = NULL;
setup->roots = NULL;
if (size < sizeConnSetup) return 1;
memcpy(setup, buf, sizeConnSetup);
size_t offset = sizeConnSetup;
int padlen = PAD(setup->vendorLen);
if (size < offset+setup->vendorLen+padlen) return 1;
setup->vendor = malloc(setup->vendorLen+1);
strncpy(setup->vendor, (char *)buf+offset, setup->vendorLen);
setup->vendor[setup->vendorLen] = 0;
offset += setup->vendorLen+padlen;
int i, j, k;
setup->pixmapFormats = calloc(setup->numFormats, sizeof(yPixmapFormat));
for (i=0; i<setup->numFormats; i++)
{
yPixmapFormat *outFormat = &setup->pixmapFormats[i];
if (size < offset+sizePixmapFormat) return 1;
memcpy(outFormat, buf+offset, sizePixmapFormat);
offset += sizePixmapFormat;
}
setup->roots = calloc(setup->numRoots, sizeof(yWindowRoot)); //zero memory: if return 1, pointer will be NULL
for (i=0; i<setup->numRoots; i++)
{
yWindowRoot *outRoot = &setup->roots[i];
if (size < offset+sizeWindowRoot) return 1;
memcpy(outRoot, buf+offset, sizeWindowRoot);
offset += sizeWindowRoot;
outRoot->depths = calloc(outRoot->nDepths, sizeof(yDepth));
for (j=0; j<outRoot->nDepths; j++)
{
yDepth *outDepth = &outRoot->depths[j];
if (size < offset+sizeDepth) return 1;
memcpy(outDepth, buf+offset, sizeDepth);
offset += sizeDepth;
if (outDepth->nVisuals)
{
outDepth->visuals = calloc(outDepth->nVisuals, sizeof(yVisualType));
for (k=0; k<outDepth->nVisuals; k++)
{
yVisualType *outVisual = &outDepth->visuals[k];
if (size < offset+sizeVisualType) return 1;
memcpy(outVisual, buf+offset, sizeVisualType);
offset += sizeVisualType;
}
}
}
}
assert(size >= offset);
if (size==offset)
return 0;
else
return 2;
}
void FreeSetupLists(yConnSetup *setup)
{
free(setup->vendor);
setup->vendor = NULL;
setup->vendorLen = 0;
int i, j;
free(setup->pixmapFormats);
setup->pixmapFormats = NULL;
setup->numFormats = 0;
for (i=0; i<setup->numRoots; i++)
{
yWindowRoot *outRoot = &setup->roots[i];
for (j=0; j<outRoot->nDepths; j++)
{
yDepth *outDepth = &outRoot->depths[j];
free(outDepth->visuals);
}
free(outRoot->depths);
}
free(setup->roots);
setup->roots = NULL;
setup->numRoots = 0;
}
/** Current protocol version */
#define X_PROTOCOL 11
/** Current minor version */
#define X_PROTOCOL_REVISION 0
#define ERROR_MSG_LEN 255
char error_msg[ERROR_MSG_LEN+1];
#define min(a,b) a<b?a:b
#define max(a,b) a>b?a:b
#define STATUS_FAILED 0
#define STATUS_SUCCESS 1
#define STATUS_AUTHENTICATE 2
static int blockingRead(const int fd, void *buf, const size_t len)
{
int done = 0;
while(done < len)
{
int ret = recv(fd, ((char *) buf) + done, len - done, 0);
if(ret > 0)
done += ret;
if(ret < 0 && errno == EAGAIN)
{
fd_set fds;
FD_ZERO(&fds);
FD_SET(fd, &fds);
errno = 0;
do {
ret = select(fd + 1, &fds, 0, 0, 0);
} while (ret == -1 && errno == EINTR);
}
if(ret <= 0)
return ret;
}
return len;
}
int main()
{
char* display_name = NULL;
display_name = getenv("DISPLAY");
/*
Display environment variable (command "echo $DISPLAY")
general format this variable is: hostname:D.S
hostname: computer where rund X server; empty hostname means localhost/unix
host/unix: the X server for this display is listening at UNIX domain socket /tmp/.X11-unix/XD (so it's only reachable from host)
hostname:D.S: the X server for this display is listening at TCP port 6000+D
D: number (usually 0) of display connected to computer
S: screen number, empty screen means 0
(see http://askubuntu.com/questions/432255/what-is-display-environment-variable)
*/
#ifdef __hpux
static const char unix_base[] = "/usr/spool/sockets/X11/";
#else
static const char unix_base[] = "/tmp/.X11-unix/X";
#endif
int fd;
const char *filename = "/tmp/.X11-unix/X0";
struct sockaddr_un addr;
strcpy(addr.sun_path, filename);
addr.sun_family = AF_UNIX;
#ifdef HAVE_SOCKADDR_SUN_LEN
addr.sun_len = SUN_LEN(&addr);
#endif
#ifdef SOCK_CLOEXEC
fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
if (fd == -1 && errno == EINVAL)
#endif
{
fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd >= 0)
fcntl(fd, F_SETFD, FD_CLOEXEC);
}
static const uint32_t endian = 0x01020304;
/* B = 0x42 = MSB first, l = 0x6c = LSB first */
yConnClientStub out;
if(htonl(endian) == endian)
out.byteOrder = 'B';
else
out.byteOrder = 'l';
out.pad0 = 0;
out.majorVersion = X_PROTOCOL;
out.minorVersion = X_PROTOCOL_REVISION;
out.lenAuthProto = 0;
out.lenAuthString = 0;
out.pad1 = 0;
connect(fd, (struct sockaddr *)&addr, sizeof(addr));
size_t n = send(fd, &out, 12, 0);
yConnSuccessStub stub;
n = blockingRead(fd, &stub, sizeof(stub));
switch (stub.status)
{
case STATUS_FAILED: break;
case STATUS_AUTHENTICATE: break;
case STATUS_SUCCESS:
{
unsigned char * buf;
size_t buflen = sizeof(stub)+4*stub.length;
buf = malloc(buflen);
memcpy(buf, &stub, sizeof(stub));
n = blockingRead(fd, buf+sizeof(stub), 4*stub.length);
yConnSetup setup;
int ret = ParseConnectionBlock(buf, buflen, &setup);
if (ret==0)
printf("SUCCESS!\n");
FreeSetupLists(&setup);
free(buf);
}
break;
}
close(fd);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment