xss

Screensaver utilities for the X Windowing System
git clone https://git.woozle.org/neale/xss.git

Neale Pickett  ·  2012-03-01

xkeygrab.c

  1/*
  2 * xkeygrab -- grab keyboard and mouse, writing typed lines to stdout
  3 * Copyright (C) 2008 Neale Pickett <neale@woozle.org> 
  4 *
  5 * This program is free software:  you can redistribute it and/or
  6 * modify it under the terms of the GNU General Public License as
  7 * published by the Free Software Foundation, either version 3 of the
  8 * License, or (at your option) any later version.
  9 *
 10 * This program is distributed in the hope that it will be useful, but
 11 * WITHOUT ANY WARRANTY; without even the implied warranty of
 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13 * General Public License for more details.
 14 *
 15 * You should have received a copy of the GNU General Public License
 16 * along with this program.  If not, see <http://www.gnu.org/licenses/>. 
 17 */
 18
 19#include <stdio.h>
 20#include <unistd.h>
 21#include <ctype.h>
 22#include <poll.h>
 23#include <X11/Xlib.h>
 24#include <X11/Xutil.h>
 25#include <X11/keysym.h>
 26
 27#include "obj.h"
 28
 29int
 30main(int argc, char *argv[])
 31{
 32    Display        *display = NULL;
 33
 34    if (argc != 1) {
 35        (void) fprintf(stderr, "Usage: %s\n", argv[0]);
 36        return 64;              /* EX_USAGE */
 37    }
 38
 39    try {
 40        Window          root;
 41        char            obuf[4096];
 42        int             obuflen = 0;
 43        struct pollfd   fds[2];
 44
 45        if (!(display = XOpenDisplay(NULL)))
 46            raise("cannot open display");
 47        root = DefaultRootWindow(display);
 48
 49        if (getenv("NOROOT")) {
 50            int             screen = DefaultScreen(display);
 51
 52            XSetWindowAttributes wa;
 53
 54            zero(wa);
 55
 56            wa.override_redirect = 1;
 57            wa.background_pixel = BlackPixel(display, screen);
 58            root = XCreateWindow(display, root,
 59                                 0, 0,
 60                                 50, 50, 0,
 61                                 CopyFromParent, CopyFromParent,
 62                                 CopyFromParent, CWBackPixel, &wa);
 63            XMapWindow(display, root);
 64        }
 65
 66
 67        fds[0].fd = STDOUT_FILENO;
 68        fds[0].events = 0;
 69        fds[1].fd = ConnectionNumber(display);
 70        fds[1].events = POLLIN;
 71        while (1) {
 72            int             tograb = 3;
 73            int             ret;
 74
 75            if (tograb) {
 76                if ((tograb & 1)
 77                    && (GrabSuccess ==
 78                        XGrabKeyboard(display, root, True, GrabModeAsync,
 79                                      GrabModeAsync, CurrentTime))) {
 80                    tograb |= 1;
 81                }
 82                if ((tograb & 2)
 83                    && (GrabSuccess ==
 84                        XGrabPointer(display, root, False,
 85                                     ButtonPressMask | ButtonReleaseMask |
 86                                     PointerMotionMask, GrabModeAsync,
 87                                     GrabModeAsync, None, None,
 88                                     CurrentTime))) {
 89                    tograb |= 2;
 90                }
 91            }
 92
 93            ret = poll(fds, 2, (tograb ? 100 : -1));
 94            if (-1 == ret)
 95                break;
 96
 97            if (fds[0].revents & POLLERR) {
 98                break;
 99            }
100            if (fds[1].revents & POLLIN) {
101                XEvent          event;
102
103                do {
104                    (void) XNextEvent(display, &event);
105                    if (KeyPress == event.type) {
106                        char            buf[32];
107                        KeySym          ksym;
108                        int             i;
109
110                        if (obuflen == sizeof(obuf))
111                            continue;
112                        i = XLookupString(&event.xkey, buf, sizeof(buf),
113                                          &ksym, NULL);
114                        switch (ksym) {
115                            case XK_Return:
116                                if (obuflen) {
117                                    (void) write(STDOUT_FILENO, obuf,
118                                                 obuflen);
119                                    (void) write(STDOUT_FILENO, "\n", 1);
120                                    obuflen = 0;
121                                }
122                                break;
123                            case XK_BackSpace:
124                                if (obuflen)
125                                    obuflen -= 1;
126                                break;
127                            default:
128                                if (1 == i) {
129                                    switch (buf[0]) {
130                                        case '\025':
131                                            obuflen = 0;
132                                            break;
133                                        case ' ' ... '~':
134                                            obuf[obuflen++] = buf[0];
135                                            break;
136                                    }
137                                }
138                                break;
139                        }
140                        if (obuflen == sizeof(obuf)) {
141                            (void) write(STDOUT_FILENO, obuf, obuflen);
142                            obuflen = 0;
143                        }
144                    }
145                } while (XPending(display));
146            }
147        }
148    }
149    while (0);
150
151    if (display) {
152        (void) XUngrabKeyboard(display, CurrentTime);
153        (void) XUngrabPointer(display, CurrentTime);
154        (void) XCloseDisplay(display);
155    }
156
157    except {
158        (void) fprintf(stderr, "Error: %s\n", exception);
159        return 69;              /* EX_UNAVAILABLE */
160    }
161
162    return 0;
163}