Advertisement
wyatt8740

X11 window hiding in C with libxcb

Jan 4th, 2016
282
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 10.86 KB | None | 0 0
  1. X11 window hiding in C with libxcb
  2. Don't edit the file window ID's are saved to, or you could mess up the unhide program.
  3.  
  4. hide.c:
  5.  
  6. /* hide.c:                                                                  *
  7.  * -------------------------------------------------------------------------*
  8.  * hides currently focused X11 window, for later unhiding with 'unhide.c'.  *
  9.  * Stores a list of window ID's, in order of hiding, in a 'stack' file in   *
  10.  * the user's home directory. This is mostly a 'security through obscurity' *
  11.  * thing - it provides no encryption, but anyone who looks in the file will *
  12.  * only see a lot of numbers. Most people are not likely, unless they've    *
  13.  * looked at this program (or the bash script I wrote ages ago that this    *
  14.  * descends from), to recognize that they are in fact X11 window ID's. Even *
  15.  * with this knowledge, linux/unix systems most often don't come with       *
  16.  * anything like 'xdotool' that can re-map unmapped windows (So, basically, *
  17.  * I guess you could use it as a 'boss key' with a keyboard shortcut).      *
  18.  *                                                                          *
  19.  * The 'hidden window' file is ~/hidden by default. You can edit that       *
  20.  * filename in the source code below.                                       *
  21.  *                                                                          *
  22.  * Compiling requires libxcb and it's development headers to be installed.  *
  23.  * on Debian/Ubuntu, this should install them:                              *
  24.  *   sudo apt-get install libxcb1-dev                                       *
  25.  *                                                                          *
  26.  * To compile, I usually do:                                                *
  27.  *   gcc -Wall hide.c -o hide -lxcb                                         *
  28.  *                                                                          *
  29.  * Questions? Comments? Concerns? If you can contact me, I will help you.   *
  30.  *--------------------------------------------------------------------------*/
  31. /*#define DEBUG*/
  32. #include <sys/types.h>
  33. #include <sys/stat.h>
  34. #include <fcntl.h>
  35. #include <stdio.h>
  36. #include <stdlib.h>
  37. #include <pwd.h>
  38. #include <string.h>
  39. #include <xcb/xcb.h>
  40. #include <xcb/xproto.h>
  41.  
  42. /* POSIX needed for getpwuid. If somehow you don't have POSIX,
  43.  * but do have X11, remove unistd.h and the getpwuid part below.
  44.  * Also, if I forget to remove it, remember that sleep() below is POSIX.
  45.  * Additionally, you'll have to do your own check for the file's existance
  46.  * later (because access() is POSIX too, IIRC). */
  47. #include <unistd.h>
  48.  
  49. /* set filename here. To change the path to something above your home dir,
  50.  * you'll have to go down a ways in the source to where I look for the HOME
  51.  * environment variable. THE FILENAME HERE MUST BEGIN WITH A SLASH OR YOU
  52.  * COULD GET STRANGE ERRORS. */
  53. char windowListFileName[]="/hidden";
  54.  
  55. int main(int argc, char *argv[]){
  56.     xcb_connection_t    *connection;
  57.  
  58.     /* Open X Server connection; use the DISPLAY variable as
  59.      * default display name. First NULL means to use DISPLAY
  60.      * variable, second NULL means you don't care which screen
  61.      * it's on  */
  62.     connection = xcb_connect (NULL,NULL);
  63.  
  64.     /* find input focus; this is the window to hide.
  65.      * Unfortunately, it doesn't return a window ID straight to me,
  66.      * so I have to use a struct (groan)*/
  67.     xcb_flush(connection);
  68.  
  69.     /*try to get stuff out of that god forsaken cookie*/
  70.     xcb_window_t windowID = xcb_get_input_focus_reply
  71.             (
  72.                 connection,
  73.                 xcb_get_input_focus (connection),
  74.                 NULL
  75.             )->focus;   /* get member 'focus' from the struct.
  76.                      * Struct is of the type xcb_window_t.*/
  77.  
  78.     const char *homedir;
  79.         if ((homedir = getenv("HOME")) == NULL) {
  80.                 homedir = getpwuid(getuid())->pw_dir;
  81.         }
  82.  
  83. /* This just prints the home dir and tells you how much space is allocated
  84.  * for it; since it's null-terminated you will have to add one byte. */
  85.  
  86. #ifdef DEBUG
  87.         printf("homedir: %s\narray size:%d\n",homedir,(int)strlen(homedir));
  88. #endif
  89.  
  90. /* set path variable length to homedir + length of file name + null
  91.  * termination (1). The file contains a list of hidden window ID's. */
  92.     char path[(int)strlen(homedir) + strlen(windowListFileName) + 1];
  93.  
  94. /* now that path is set to the size needed (and not a byte more than needed
  95.  * for null-termination Memory savings WOOOO), time to concatenate it all
  96.  * together and put it into the space we reserved. sprintf automatically
  97.  * null-terminates. (Can you tell I'm paranoid about that?) */
  98.     sprintf(path,"%s%s",homedir,windowListFileName);
  99.  
  100. /* get ready for the file! */
  101.     FILE *windowListFile;
  102.  
  103. /* if file doesn't exist */
  104.     if( access( path, F_OK ) == -1 ) {
  105.         /* file doesn't exist, so try to make a blank one. We don't want to
  106.          * erase existing files though, so only do it if it doesn't exist */
  107.         creat(path,0666);
  108.     }
  109.  
  110.     if( access( path, F_OK ) == -1 ) {
  111.         /* huh? still doesn't exist? dafuq? time to bail */
  112.         printf("Can't create window list file, check permissions.\n");
  113.         return -1;
  114.     }
  115.  
  116. /* if it exists, time to append data to it! re-opening time. */
  117.     windowListFile = fopen(path,"r+"); /* doesn't create a file if none exists,
  118.                                         * so checked first */
  119.  
  120. /* C89 (ANSI C) and K&R C require that you set your position in the file
  121.  * after using fopen(). So I'm seeking next. */
  122.  
  123. /*          Go to end of file. I'm using this similarly to '>>' in sh or bash
  124.  *      to concatenate to the end of a file.
  125.  *          The original 'xdotool/bash' implementation I made of this program
  126.  *      did use '>>', actually. */
  127.     fseek(windowListFile, 0, 2); /* I learned fseek() syntax from an older book.
  128.                   * 2 is equivalent to SEEK_END. (The book:
  129.                   * Programming in C, Revised Edition, Stephen
  130.                   * Kochan)*/
  131.  
  132.     /* Print window ID. Unnecessary when I finish coding. */
  133.     /* This doesn't send it to the file, of course. */
  134.     #ifdef DEBUG
  135.     printf("%d\n",windowID);
  136.     #endif
  137.  
  138.     /* the riskiest line of code in this entire project I think, because
  139.      * while it appears that all window ID's are 8 characters wide I'm
  140.      * not 100% sure and am assigning what I think is probably ample.
  141.      * if something fails, maybe check here.
  142.     */
  143.     char writeline[24];
  144.     sprintf(writeline,"%d\n",windowID);
  145.     fputs(writeline,windowListFile);
  146.     fclose(windowListFile);
  147.     /* unmap window (hide it) */
  148.     xcb_unmap_window (connection, windowID);
  149.     /* Make sure all commands are sent to X server.
  150.      * Never forget to flush! */
  151.     xcb_flush(connection);
  152.  
  153.     /* disconnect when done */
  154.     xcb_disconnect (connection);
  155.     /* Quit */
  156.     return 0;
  157. }
  158.  
  159. unhide.c:
  160.  
  161. /* remove the DEBUG definition to disable debug prints and stuff */
  162. #include <sys/types.h>
  163. #include <sys/stat.h>
  164. #include <fcntl.h>
  165. #include <stdio.h>
  166. #include <stdlib.h>
  167. #include <pwd.h>
  168. #include <string.h>
  169. #include <xcb/xcb.h>
  170. #include <xcb/xproto.h>
  171.  
  172. #include <unistd.h> /* POSIX */
  173.  
  174. /* set filename here. To change the path to something above your home dir,
  175.  * you'll have to go down a ways in the source to where I look for the HOME
  176.  * environment variable. THE FILENAME HERE MUST BEGIN WITH A SLASH OR YOU
  177.  * COULD GET STRANGE ERRORS. */
  178. char windowListFileName[]="/hidden";
  179. xcb_connection_t        *connection;
  180.  
  181. /* elevate_window() currently unused. Maybe later. */
  182. /* void elevate_window(xcb_window_t window)
  183. {
  184.     uint32_t stack_mode[1] = { XCB_STACK_MODE_ABOVE };
  185.     xcb_configure_window(connection, window, XCB_CONFIG_WINDOW_STACK_MODE, stack_mode);
  186. } */
  187.  
  188.  
  189. int main(int argc, char *argv[]){
  190.     /* connect to X server */
  191.     connection = xcb_connect (NULL,NULL);
  192.  
  193.     /* find path to file: */
  194.     const char *homedir;
  195.         if ((homedir = getenv("HOME")) == NULL) {
  196.                 homedir = getpwuid(getuid())->pw_dir;
  197.         }
  198.     #ifdef DEBUG
  199.         printf("homedir: %s\narray size:%d\n",homedir,(int)strlen(homedir));
  200.     #endif
  201.  
  202.     /* find total size of string*/
  203.     char path[(int)strlen(homedir) + strlen(windowListFileName) + 1];
  204.  
  205.     /* concatenate the string in space provided above */
  206.     sprintf(path,"%s%s",homedir,windowListFileName);
  207.  
  208.     /* if file doesn't exist */
  209.         if( access( path, F_OK ) == -1 ) {
  210.                 /* file doesn't exist, so try to make a blank one. We don't want to
  211.                  * erase existing files though, so only do it if it doesn't exist */
  212.                 printf("You don't have a list of hidden files. Run the hider first.\n");
  213.         return -1;
  214.         }
  215.     /* basing this entirely on the assumption all window ID's are 8 characters long and every line
  216.      * has a newline after it. Totally safe. Yeah. Definitely. It cuts off the last 9 bytes of
  217.      * the file with truncate().
  218. /* if it exists, time to append data to it! re-opening time. */
  219. /* get ready for the file! */
  220.     FILE *windowListFile;
  221.  /* doesn't create a file if none exists, so checked*/
  222. /* C89 (ANSI C) and K&R C require that you set your position in the file
  223.  * after using fopen(). So I'm seeking to end of file */
  224.         struct stat st;
  225.         stat (path, &st);
  226.         off_t FileSize = st.st_size;
  227.  
  228.     static const int max_len = 9 + 1; /* max length of line to read plus 1. */
  229.     char buff[max_len + 1];
  230.     xcb_window_t windowID;
  231. if (FileSize > 9){ /* 8 byte window ID's plus a newline is 9 bytes */
  232.  
  233.     if ((windowListFile = fopen(path, "r")) != NULL)  { /* open file */
  234.         fseek(windowListFile, -max_len, SEEK_END); /* EOF minus length needed */
  235.         fread(buff, max_len-1, 1, windowListFile); /* read forward from close to the end */
  236.         fclose(windowListFile); /* close file */
  237.         buff[max_len-1] = '\0'; /* null termination is very important for a boy's health */
  238.         char *last_newline = strrchr(buff, '\n'); /* find last newline */
  239.         char *last_line = last_newline+1; /* go to that line */
  240. #ifdef DEBUG
  241.         printf("[%s]\n", last_line); /* captured */
  242. #endif
  243.         windowID=atoi(last_line);
  244.         truncate(path, FileSize - 9);
  245.     }
  246. }
  247. else if (FileSize > 1) { /* if file is only one line do this special case */
  248.     windowListFile = fopen(path,"r");
  249.     char line1[9];
  250.     fread(line1,8,1,windowListFile);
  251.     fclose(windowListFile);
  252.     line1[8]='\0';
  253. #ifdef DEBUG
  254.     printf("only one line, contents %s\n",line1);
  255. #endif
  256.     windowID=atoi(line1);
  257.     truncate(path, 0); /* wipe file clean */
  258. }
  259. else { /* if the file doesn't have any window ID's,wipe any straggler bytes and quit without doing anything.
  260.     * Straggler bytes should only result from manual editing of the file, of course. But I'll admit my
  261.     * math's been pretty shitty for the 'unhide' part of the project. */
  262.     #ifdef DEBUG
  263.         printf("no window ID's in the file, quitting\n");
  264.     #endif
  265. /*  truncate(path, 0); */ /*unnecessary because if it's less than 1 byte it must be 0 */
  266.     return 0;
  267. }
  268.  
  269.     /* Last window ID found, now time to unhide */
  270.     xcb_map_window(connection, windowID);
  271.     xcb_flush(connection); /*NEVER FORGET TO FLUSH */
  272.  
  273.     /* disconnect when done */
  274.     xcb_disconnect (connection);
  275.     /* Quit */
  276.     return 0;
  277. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement