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  }