繁体   English   中英

在没有 X Window 的情况下用 C 语言在 GNU/Linux 中捕获击键

[英]Capturing keystrokes in GNU/Linux in C without X Window

如果我在一个应用程序中工作并且我从键盘上按下了一个键,我如何在没有 X Window 的情况下在 C 中、在 GNU/LINUX 下、在用户空间中捕获该键(或字符串),包括源应用程序的名称?

好吧,如果没有 X Window,这个问题会更加困难。

对于击键部分,您可以使用与此类似的代码,但您必须将设备作为您正在阅读的参数传递(键盘,通常是/dev/input/event0

#include <linux/input.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    int fd;
    if(argc < 2) {
        printf("usage: %s <device>\n", argv[0]);
        return 1;
    }

    fd = open(argv[1], O_RDONLY);
    struct input_event ev;

    while (1)
    {
        read(fd, &ev, sizeof(struct input_event));

        if(ev.type == 1)
            printf("key %i state %i\n", ev.code, ev.value);

        }
    }

学分不给我。 此代码取自 Ventriloctrl hack 以获取击键 - http://public.callutheran.edu/~abarker/ventriloctrl-0.4.tar.gz

您可以从 /dev/input 中的文件之一读取数据。 哪一个取决于您的系统。 它可能是 /dev/input/event0 或 /dev/input/by-path/platform-i8042-serio-0-event-kbd 或其他东西。 格式在内核头文件 input.h 中指定。 这是

struct input_event {
        struct timeval time;
        __u16 type;
        __u16 code;
        __s32 value;
};

你可以跑

od -tx2 FILENAME

然后输入一些东西看看会发生什么。

至于找出哪个应用程序收到了关键事件,我不确定。 您可以尝试检查哪个正在从主 tty 读取。

一种可能性:找到并查看“ sudosh ”的来源,即“sudo shell”(或它的替代品之一,因为它有一段时间没有修改;谷歌是你的朋友)。

它与伪 tty 混淆,并通过将信息记录到文件来跟踪所有输入和输出。

这对你来说是否足够精确可能更有争议。 它会记录所有应用程序的所有击键。 我也不确定它如何与 X11 一起工作 - 如果它与 X11 一起工作。

对于一个很好的例子,看看showkey的代码。

特别是,这是主循环。 它所做的就是获取终端,复制它,将复制的终端转为原始模式,直到给出“退出”或“中断”键序列,它才打印出给终端的键。

/*
 * showkey.c -- display cooked key sequences
 *
 * Invoke this (no arguments needed) to see keycap-to-keystrokes mappings.
 *
 * by Eric S. Raymond <esr@snark.thyrsus.com>, 1 Nov 88
 * - fix for little-endian machines (version 1.1), 21 Oct 1996.
 * - cleanup and modern packaging (version 1.2), 1 Aug 2002.
 * - changed to use termios (version 1.3), 26 Aug 2002.
 * See the RPM spec file changelog for more recent stuff.
 */
#include <stdio.h>
#include <termios.h>
#include <signal.h>
#include <string.h>
#include <stdbool.h>
static int signalled;

// ...

main()
{
    struct termios  cooked, raw;
    unsigned char   c;
    unsigned int    i, timeouts;
    char intrchar[32], quitchar[32];

    for (i = SIGHUP; i <= SIGIO; i++)
    (void) signal(c, catcher);

    // Get the state of the tty 
    (void) tcgetattr(0, &cooked);
    // Make a copy we can mess with
    (void) memcpy(&raw, &cooked, sizeof(struct termios));
    // Turn off echoing, linebuffering, and special-character processing,
    // but not the SIGINT or SIGQUIT keys.
    raw.c_lflag &=~ (ICANON | ECHO);
    // Ship the raw control blts
    (void) tcsetattr(0, TCSANOW, &raw);

    (void) printf("Type any key to see the sequence it sends.\n");
    visualize(raw.c_cc[VINTR], intrchar);
    visualize(raw.c_cc[VQUIT], quitchar);
    (void) printf("Terminate with your shell interrupt %s or quit %s character.\n",
          intrchar, quitchar);
    signalled = 0;
    while (!signalled)
    {
    char cbuf[32];

    read(0, &c, 1);
    visualize(c, cbuf);
    (void)fputs(cbuf, stdout);
    (void) fflush(stdout);
    }

    (void) printf("\nBye...\n");
    // Restore the cooked state
    (void) tcsetattr(0, TCSANOW, &cooked);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM