💾 Archived View for 050821.xyz › gemlog › simple-keyboard-logger.gmi captured on 2022-04-28 at 17:15:20. Gemini links have been rewritten to link to archived content
-=-=-=-=-=-=-
Several days ago, I've noticed /dev/input/event* files. I thought it might be a way to
capture keyboard events.
The document for this kinda file is located in the Linux Kernel. The path is:
Documentation/input/input.rst
In the document, a data structure for events was introduced, which I will show it below:
struct input_event { struct timeval time; unsigned short type; unsigned short code; unsigned int value; };
So, in this struct, time is for the timestamp, code is for the event code. We probably
not gonna use the timestamp. The event value can be used to identify whether the key's
pressed or released. The code indicates the keys you're pressing, which can be found
in 'include/uapi/linux/input-event-codes.h'.
And that's all the knowledge we'll use in the code. So, let's jump into it.
struct input_event *event = malloc(sizeof(struct input_event)); FILE *event_stream = fopen(argv[1], "r");
First, we allocated some memory for the event, and later we'll read to it. And we also
created a stream for reading events from the device.
while(1) { fread(event, sizeof(struct input_event), 1, event_stream); puts("Key event!"); }
We've read the event to that memory. Now, we could access the event!
For event->type, 1 is for keyboard event.
For event->value, 1 is for pressing, 0 is for releasing.
For event->code, it's defined in 'input-event-codes.h'.
In the input-event-codes.h, the key names were definely in macros:
#define KEY_RESERVED 0 #define KEY_ESC 1 #define KEY_1 2 #define KEY_2 3 ...
Apparently, we can't use it directly. But because it's continuous,
we can convet it to a string array using the python script below:
source = open("origin_event_code.h", 'r') output = open("event_code.c", 'w') index = 0 output.write("char event_code[][32] = {\n") rlines = source.readlines() for l in rlines: if not l.startswith("#define"): continue parts = l.strip().split() output.write("\t\"<" + parts[1].replace("KEY_", "") + ">\"") if l == rlines[-1]: output.write("\n") else: output.write(",\n") source.close() output.write("};") output.close()
It will generate something like this:
char event_code[][32] = { "<RESERVED>", "<ESC>", "<1>", "<2>", "<3>" // ... }
We can get the key name using this expression 'event_code[event->code]'.
Now you can do whatever you want, e.g. write it to stdout or a file.
And here's the source code:
You're required to provide the input event device. And you can easily
find it in '/dev/input/by-id'.