Question

I'm trying to write my own program that connects to a local X server that does not use Xlib or XCB, using the X Window System Protocol documentation. After writing the connection data to the server socket I can't seem to read back the server's reply, as the read function blocks.

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>

int main()
{
  int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);

  struct sockaddr_un serv_addr;
  memset((void*)&serv_addr, 0, sizeof(serv_addr));
  serv_addr.sun_family = AF_UNIX;
  strcpy(serv_addr.sun_path, "/tmp/.X11-unix/X0");
  int servlen = 17 + sizeof(serv_addr.sun_family);

  int err = connect(sockfd, (struct sockaddr*)&serv_addr, servlen);

  printf("%d\n", err);

  struct
  {
    uint8_t en;
    uint8_t pad;
    uint16_t major;
    uint16_t minor;
    uint16_t name_len;
    uint16_t data_len;
    uint16_t pad2;
    uint8_t name[4];
    uint8_t data[4];
  } init;

  init.en = 'l';
  init.major = 11;
  init.minor = 0;
  init.name_len = 0;
  init.data_len = 0;

  err = write(sockfd, init, sizeof(init));

  printf("%d\n", err);

  uint8_t buf[5000];

  int n = read(sockfd, buf, 5000);

  return 0;
}

What is missing from my code? The connect and write functions return 0.

Was it helpful?

Solution

I suspect that your problem is with your write:

err = write(sockfd, init, sizeof(init));

The second parameter should be &init, passing just init will, effectively, unroll the structure and the computer will see something like this:

err = write(sockfd, init.en, init.pad, ..., sizeof(init));

Since write only looks at three arguments, it will be using one of the init members as the size of the buffer to write and that member is probably zero. The actual byte-level argument stack depends on the compiler and architecture so you can tease that our yourself, the important thing is that you're not feeding write what you want to.

Your compiler should have caught this, if it didn't then you need to crank up the warning options as high as they will go.

You'll probably want to build the data you send to the X server byte by byte anyway, that way you can make sure you get the byte order and offsets right. Sending &init will get you into trouble with the usual suspects (packing, alignment, and byte order).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top