UNIXworkcode

1 /* 2 * DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 3 * Version 2, December 2004 4 * 5 * Copyright (C) 2017 Olaf Wintermann <olaf.wintermann@gmail.com> 6 * 7 * Everyone is permitted to copy and distribute verbatim or modified 8 * copies of this license document, and changing it is allowed as long 9 * as the name is changed. 10 * 11 * DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 12 * TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 13 * 14 * 0. You just DO WHAT THE FUCK YOU WANT TO. 15 */ 16 17 #define _GNU_SOURCE 18 #include <stdio.h> 19 #include <stdlib.h> 20 #include <fcntl.h> 21 #include <sys/types.h> 22 #include <sys/ipc.h> 23 #include <sys/socket.h> 24 #include <sys/file.h> 25 #include <netinet/in.h> 26 #include <netdb.h> 27 #include <stdio.h> 28 #include <stdlib.h> 29 #include <fcntl.h> 30 #include <inttypes.h> 31 #include <unistd.h> 32 #include <string.h> 33 #include <stdbool.h> 34 #include <pthread.h> 35 36 #include <X11/Xlib.h> 37 #include <X11/Xatom.h> 38 39 uint32_t listenaddr = 0; 40 short srvport = 9302; 41 uint32_t *allowedaddr = NULL; 42 size_t numallowedaddr = 0; 43 44 int srvloop = 1; 45 46 Display *dp; 47 48 typedef struct Client { 49 int fd; 50 struct sockaddr_in addr; 51 } Client; 52 53 #define XPROP_MAX_LENGTH 4096/4 54 int get_desktop() { 55 Atom curdesktop = XInternAtom(dp, "_NET_CURRENT_DESKTOP", False); 56 Atom type; 57 int format; 58 unsigned long nitems; 59 unsigned long size; 60 unsigned long bytes_after; 61 unsigned char *value; 62 if(XGetWindowProperty(dp, DefaultRootWindow(dp), curdesktop, 0, XPROP_MAX_LENGTH, False, XA_CARDINAL, &type, &format, &nitems, &bytes_after, &value) != Success) { 63 return 0; 64 } 65 66 int *desktop = (int*)value; 67 return *desktop; 68 } 69 70 void switch_desktop(int desktop) { 71 XEvent event; 72 event.xclient.type = ClientMessage; 73 event.xclient.serial = 0; 74 event.xclient.send_event = True; 75 event.xclient.message_type = XInternAtom(dp, "_NET_CURRENT_DESKTOP", False); 76 event.xclient.window = DefaultRootWindow(dp); 77 event.xclient.format = 32; 78 event.xclient.data.l[0] = desktop; 79 80 if(!XSendEvent(dp, DefaultRootWindow(dp), False, SubstructureRedirectMask | SubstructureNotifyMask, &event)) { 81 fprintf(stderr, "XSendEvent failed\n"); 82 } 83 } 84 85 86 int load_config() { 87 // TODO 88 89 return 0; 90 } 91 92 int create_server_socket(uint32_t addr, short port) { 93 int ssock = -1; 94 95 struct sockaddr_in servaddr; 96 memset(&servaddr, 0, sizeof(servaddr)); 97 servaddr.sin_family = AF_INET; 98 servaddr.sin_addr.s_addr = htonl(addr); 99 servaddr.sin_port = htons(port); 100 101 if((ssock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { 102 perror("socket"); 103 return -1; 104 } 105 106 int o = 1; 107 setsockopt( 108 ssock, 109 SOL_SOCKET, SO_REUSEADDR, 110 &o, 111 sizeof(int)); 112 113 if(bind(ssock, (struct sockaddr*)&servaddr, sizeof(servaddr))) { 114 perror("bind"); 115 return -1; 116 } 117 118 return ssock; 119 } 120 121 void* client_thread(void *data) { 122 Client *client = data; 123 124 FILE *stream = fdopen(client->fd, "r"); 125 char *line = NULL; 126 size_t len = 0; 127 128 ssize_t n; 129 while((n = getline(&line, &len, stream)) > 0) { 130 if(line[n-1] == '\n') { 131 line[n-1] = '\0'; 132 } 133 int desktop = get_desktop(); 134 135 if(!strcmp(line, "up")) { 136 printf("up\n"); 137 switch_desktop(desktop - 1); 138 } else if(!strcmp(line, "down")) { 139 printf("down\n"); 140 switch_desktop(desktop + 1); 141 } else if(!strcmp(line, "left")) { 142 printf("left\n"); 143 switch_desktop(desktop - 1); 144 } else if(!strcmp(line, "right")) { 145 printf("right\n"); 146 switch_desktop(desktop + 1); 147 } else { 148 int desktop = atoi(line); 149 printf("desktop: %d\n", desktop); 150 switch_desktop(desktop); 151 } 152 153 XFlush(dp); 154 } 155 156 fclose(stream); 157 free(client); 158 159 XFlush(dp); 160 161 return NULL; 162 } 163 164 int main(int argc, char** argv) { 165 if(load_config()) { 166 fprintf(stderr, "Cannot load config\n"); 167 return 1; 168 } 169 dp = XOpenDisplay(NULL); 170 if(!dp) { 171 fprintf(stderr, "Cannot open X Display\n"); 172 return 1; 173 } 174 175 int ssock = create_server_socket(listenaddr, srvport); 176 if(ssock < 0) { 177 return 1; 178 } 179 if(listen(ssock, 16)) { 180 perror("listen"); 181 } 182 183 while(srvloop) { 184 struct sockaddr_in ca; 185 socklen_t length = sizeof(ca); 186 int clientfd; 187 188 clientfd = accept( 189 ssock, 190 (struct sockaddr*)&ca, 191 &length); 192 if (clientfd == -1) { 193 perror("accept"); 194 break; 195 } 196 197 Client *client = malloc(sizeof(Client)); 198 client->fd = clientfd; 199 client->addr = ca; 200 201 pthread_t t; 202 if(pthread_create(&t, NULL, client_thread, client)) { 203 perror("pthread_create"); 204 close(clientfd); 205 free(client); 206 } 207 pthread_detach(t); 208 } 209 210 close(ssock); 211 return 0; 212 } 213