Last active
December 2, 2015 23:16
-
-
Save andr1972/b86b554c3617874be65a to your computer and use it in GitHub Desktop.
Setup information from X11 protocol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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