Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- X11 window hiding in C with libxcb
- Don't edit the file window ID's are saved to, or you could mess up the unhide program.
- hide.c:
- /* hide.c: *
- * -------------------------------------------------------------------------*
- * hides currently focused X11 window, for later unhiding with 'unhide.c'. *
- * Stores a list of window ID's, in order of hiding, in a 'stack' file in *
- * the user's home directory. This is mostly a 'security through obscurity' *
- * thing - it provides no encryption, but anyone who looks in the file will *
- * only see a lot of numbers. Most people are not likely, unless they've *
- * looked at this program (or the bash script I wrote ages ago that this *
- * descends from), to recognize that they are in fact X11 window ID's. Even *
- * with this knowledge, linux/unix systems most often don't come with *
- * anything like 'xdotool' that can re-map unmapped windows (So, basically, *
- * I guess you could use it as a 'boss key' with a keyboard shortcut). *
- * *
- * The 'hidden window' file is ~/hidden by default. You can edit that *
- * filename in the source code below. *
- * *
- * Compiling requires libxcb and it's development headers to be installed. *
- * on Debian/Ubuntu, this should install them: *
- * sudo apt-get install libxcb1-dev *
- * *
- * To compile, I usually do: *
- * gcc -Wall hide.c -o hide -lxcb *
- * *
- * Questions? Comments? Concerns? If you can contact me, I will help you. *
- *--------------------------------------------------------------------------*/
- /*#define DEBUG*/
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <pwd.h>
- #include <string.h>
- #include <xcb/xcb.h>
- #include <xcb/xproto.h>
- /* POSIX needed for getpwuid. If somehow you don't have POSIX,
- * but do have X11, remove unistd.h and the getpwuid part below.
- * Also, if I forget to remove it, remember that sleep() below is POSIX.
- * Additionally, you'll have to do your own check for the file's existance
- * later (because access() is POSIX too, IIRC). */
- #include <unistd.h>
- /* set filename here. To change the path to something above your home dir,
- * you'll have to go down a ways in the source to where I look for the HOME
- * environment variable. THE FILENAME HERE MUST BEGIN WITH A SLASH OR YOU
- * COULD GET STRANGE ERRORS. */
- char windowListFileName[]="/hidden";
- int main(int argc, char *argv[]){
- xcb_connection_t *connection;
- /* Open X Server connection; use the DISPLAY variable as
- * default display name. First NULL means to use DISPLAY
- * variable, second NULL means you don't care which screen
- * it's on */
- connection = xcb_connect (NULL,NULL);
- /* find input focus; this is the window to hide.
- * Unfortunately, it doesn't return a window ID straight to me,
- * so I have to use a struct (groan)*/
- xcb_flush(connection);
- /*try to get stuff out of that god forsaken cookie*/
- xcb_window_t windowID = xcb_get_input_focus_reply
- (
- connection,
- xcb_get_input_focus (connection),
- NULL
- )->focus; /* get member 'focus' from the struct.
- * Struct is of the type xcb_window_t.*/
- const char *homedir;
- if ((homedir = getenv("HOME")) == NULL) {
- homedir = getpwuid(getuid())->pw_dir;
- }
- /* This just prints the home dir and tells you how much space is allocated
- * for it; since it's null-terminated you will have to add one byte. */
- #ifdef DEBUG
- printf("homedir: %s\narray size:%d\n",homedir,(int)strlen(homedir));
- #endif
- /* set path variable length to homedir + length of file name + null
- * termination (1). The file contains a list of hidden window ID's. */
- char path[(int)strlen(homedir) + strlen(windowListFileName) + 1];
- /* now that path is set to the size needed (and not a byte more than needed
- * for null-termination Memory savings WOOOO), time to concatenate it all
- * together and put it into the space we reserved. sprintf automatically
- * null-terminates. (Can you tell I'm paranoid about that?) */
- sprintf(path,"%s%s",homedir,windowListFileName);
- /* get ready for the file! */
- FILE *windowListFile;
- /* if file doesn't exist */
- if( access( path, F_OK ) == -1 ) {
- /* file doesn't exist, so try to make a blank one. We don't want to
- * erase existing files though, so only do it if it doesn't exist */
- creat(path,0666);
- }
- if( access( path, F_OK ) == -1 ) {
- /* huh? still doesn't exist? dafuq? time to bail */
- printf("Can't create window list file, check permissions.\n");
- return -1;
- }
- /* if it exists, time to append data to it! re-opening time. */
- windowListFile = fopen(path,"r+"); /* doesn't create a file if none exists,
- * so checked first */
- /* C89 (ANSI C) and K&R C require that you set your position in the file
- * after using fopen(). So I'm seeking next. */
- /* Go to end of file. I'm using this similarly to '>>' in sh or bash
- * to concatenate to the end of a file.
- * The original 'xdotool/bash' implementation I made of this program
- * did use '>>', actually. */
- fseek(windowListFile, 0, 2); /* I learned fseek() syntax from an older book.
- * 2 is equivalent to SEEK_END. (The book:
- * Programming in C, Revised Edition, Stephen
- * Kochan)*/
- /* Print window ID. Unnecessary when I finish coding. */
- /* This doesn't send it to the file, of course. */
- #ifdef DEBUG
- printf("%d\n",windowID);
- #endif
- /* the riskiest line of code in this entire project I think, because
- * while it appears that all window ID's are 8 characters wide I'm
- * not 100% sure and am assigning what I think is probably ample.
- * if something fails, maybe check here.
- */
- char writeline[24];
- sprintf(writeline,"%d\n",windowID);
- fputs(writeline,windowListFile);
- fclose(windowListFile);
- /* unmap window (hide it) */
- xcb_unmap_window (connection, windowID);
- /* Make sure all commands are sent to X server.
- * Never forget to flush! */
- xcb_flush(connection);
- /* disconnect when done */
- xcb_disconnect (connection);
- /* Quit */
- return 0;
- }
- unhide.c:
- /* remove the DEBUG definition to disable debug prints and stuff */
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <pwd.h>
- #include <string.h>
- #include <xcb/xcb.h>
- #include <xcb/xproto.h>
- #include <unistd.h> /* POSIX */
- /* set filename here. To change the path to something above your home dir,
- * you'll have to go down a ways in the source to where I look for the HOME
- * environment variable. THE FILENAME HERE MUST BEGIN WITH A SLASH OR YOU
- * COULD GET STRANGE ERRORS. */
- char windowListFileName[]="/hidden";
- xcb_connection_t *connection;
- /* elevate_window() currently unused. Maybe later. */
- /* void elevate_window(xcb_window_t window)
- {
- uint32_t stack_mode[1] = { XCB_STACK_MODE_ABOVE };
- xcb_configure_window(connection, window, XCB_CONFIG_WINDOW_STACK_MODE, stack_mode);
- } */
- int main(int argc, char *argv[]){
- /* connect to X server */
- connection = xcb_connect (NULL,NULL);
- /* find path to file: */
- const char *homedir;
- if ((homedir = getenv("HOME")) == NULL) {
- homedir = getpwuid(getuid())->pw_dir;
- }
- #ifdef DEBUG
- printf("homedir: %s\narray size:%d\n",homedir,(int)strlen(homedir));
- #endif
- /* find total size of string*/
- char path[(int)strlen(homedir) + strlen(windowListFileName) + 1];
- /* concatenate the string in space provided above */
- sprintf(path,"%s%s",homedir,windowListFileName);
- /* if file doesn't exist */
- if( access( path, F_OK ) == -1 ) {
- /* file doesn't exist, so try to make a blank one. We don't want to
- * erase existing files though, so only do it if it doesn't exist */
- printf("You don't have a list of hidden files. Run the hider first.\n");
- return -1;
- }
- /* basing this entirely on the assumption all window ID's are 8 characters long and every line
- * has a newline after it. Totally safe. Yeah. Definitely. It cuts off the last 9 bytes of
- * the file with truncate().
- /* if it exists, time to append data to it! re-opening time. */
- /* get ready for the file! */
- FILE *windowListFile;
- /* doesn't create a file if none exists, so checked*/
- /* C89 (ANSI C) and K&R C require that you set your position in the file
- * after using fopen(). So I'm seeking to end of file */
- struct stat st;
- stat (path, &st);
- off_t FileSize = st.st_size;
- static const int max_len = 9 + 1; /* max length of line to read plus 1. */
- char buff[max_len + 1];
- xcb_window_t windowID;
- if (FileSize > 9){ /* 8 byte window ID's plus a newline is 9 bytes */
- if ((windowListFile = fopen(path, "r")) != NULL) { /* open file */
- fseek(windowListFile, -max_len, SEEK_END); /* EOF minus length needed */
- fread(buff, max_len-1, 1, windowListFile); /* read forward from close to the end */
- fclose(windowListFile); /* close file */
- buff[max_len-1] = '\0'; /* null termination is very important for a boy's health */
- char *last_newline = strrchr(buff, '\n'); /* find last newline */
- char *last_line = last_newline+1; /* go to that line */
- #ifdef DEBUG
- printf("[%s]\n", last_line); /* captured */
- #endif
- windowID=atoi(last_line);
- truncate(path, FileSize - 9);
- }
- }
- else if (FileSize > 1) { /* if file is only one line do this special case */
- windowListFile = fopen(path,"r");
- char line1[9];
- fread(line1,8,1,windowListFile);
- fclose(windowListFile);
- line1[8]='\0';
- #ifdef DEBUG
- printf("only one line, contents %s\n",line1);
- #endif
- windowID=atoi(line1);
- truncate(path, 0); /* wipe file clean */
- }
- else { /* if the file doesn't have any window ID's,wipe any straggler bytes and quit without doing anything.
- * Straggler bytes should only result from manual editing of the file, of course. But I'll admit my
- * math's been pretty shitty for the 'unhide' part of the project. */
- #ifdef DEBUG
- printf("no window ID's in the file, quitting\n");
- #endif
- /* truncate(path, 0); */ /*unnecessary because if it's less than 1 byte it must be 0 */
- return 0;
- }
- /* Last window ID found, now time to unhide */
- xcb_map_window(connection, windowID);
- xcb_flush(connection); /*NEVER FORGET TO FLUSH */
- /* disconnect when done */
- xcb_disconnect (connection);
- /* Quit */
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement