UNIXworkcode

/* * DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE * Version 2, December 2004 * * Copyright (C) 2017 Olaf Wintermann <olaf.wintermann@gmail.com> * * Everyone is permitted to copy and distribute verbatim or modified * copies of this license document, and changing it is allowed as long * as the name is changed. * * DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE * TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION * * 0. You just DO WHAT THE FUCK YOU WANT TO. */ #define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/socket.h> #include <sys/file.h> #include <netinet/in.h> #include <netdb.h> #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <inttypes.h> #include <unistd.h> #include <string.h> #include <stdbool.h> #include <pthread.h> #include <X11/Xlib.h> #include <X11/Xatom.h> uint32_t listenaddr = 0; short srvport = 9302; uint32_t *allowedaddr = NULL; size_t numallowedaddr = 0; int srvloop = 1; Display *dp; typedef struct Client { int fd; struct sockaddr_in addr; } Client; #define XPROP_MAX_LENGTH 4096/4 int get_desktop() { Atom curdesktop = XInternAtom(dp, "_NET_CURRENT_DESKTOP", False); Atom type; int format; unsigned long nitems; unsigned long size; unsigned long bytes_after; unsigned char *value; if(XGetWindowProperty(dp, DefaultRootWindow(dp), curdesktop, 0, XPROP_MAX_LENGTH, False, XA_CARDINAL, &type, &format, &nitems, &bytes_after, &value) != Success) { return 0; } int *desktop = (int*)value; return *desktop; } void switch_desktop(int desktop) { XEvent event; event.xclient.type = ClientMessage; event.xclient.serial = 0; event.xclient.send_event = True; event.xclient.message_type = XInternAtom(dp, "_NET_CURRENT_DESKTOP", False); event.xclient.window = DefaultRootWindow(dp); event.xclient.format = 32; event.xclient.data.l[0] = desktop; if(!XSendEvent(dp, DefaultRootWindow(dp), False, SubstructureRedirectMask | SubstructureNotifyMask, &event)) { fprintf(stderr, "XSendEvent failed\n"); } } int load_config() { // TODO return 0; } int create_server_socket(uint32_t addr, short port) { int ssock = -1; struct sockaddr_in servaddr; memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(addr); servaddr.sin_port = htons(port); if((ssock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); return -1; } int o = 1; setsockopt( ssock, SOL_SOCKET, SO_REUSEADDR, &o, sizeof(int)); if(bind(ssock, (struct sockaddr*)&servaddr, sizeof(servaddr))) { perror("bind"); return -1; } return ssock; } void* client_thread(void *data) { Client *client = data; FILE *stream = fdopen(client->fd, "r"); char *line = NULL; size_t len = 0; ssize_t n; while((n = getline(&line, &len, stream)) > 0) { if(line[n-1] == '\n') { line[n-1] = '\0'; } int desktop = get_desktop(); if(!strcmp(line, "up")) { printf("up\n"); switch_desktop(desktop - 1); } else if(!strcmp(line, "down")) { printf("down\n"); switch_desktop(desktop + 1); } else if(!strcmp(line, "left")) { printf("left\n"); switch_desktop(desktop - 1); } else if(!strcmp(line, "right")) { printf("right\n"); switch_desktop(desktop + 1); } else { int desktop = atoi(line); printf("desktop: %d\n", desktop); switch_desktop(desktop); } XFlush(dp); } fclose(stream); free(client); XFlush(dp); return NULL; } int main(int argc, char** argv) { if(load_config()) { fprintf(stderr, "Cannot load config\n"); return 1; } dp = XOpenDisplay(NULL); if(!dp) { fprintf(stderr, "Cannot open X Display\n"); return 1; } int ssock = create_server_socket(listenaddr, srvport); if(ssock < 0) { return 1; } if(listen(ssock, 16)) { perror("listen"); } while(srvloop) { struct sockaddr_in ca; socklen_t length = sizeof(ca); int clientfd; clientfd = accept( ssock, (struct sockaddr*)&ca, &length); if (clientfd == -1) { perror("accept"); break; } Client *client = malloc(sizeof(Client)); client->fd = clientfd; client->addr = ca; pthread_t t; if(pthread_create(&t, NULL, client_thread, client)) { perror("pthread_create"); close(clientfd); free(client); } pthread_detach(t); } close(ssock); return 0; }