-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
555 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
*.d | ||
*.o | ||
uinputchars |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
CC = gcc | ||
CFLAGS = -MMD -MP -Wall | ||
|
||
SRC=$(wildcard *.c) | ||
OBJ=$(SRC:.c=.o) | ||
DEP=$(SRC:.c=.d) | ||
|
||
uinputchars: $(OBJ) | ||
$(CC) $(LDFLAGS) -o $@ $^ | ||
|
||
-include $(DEP) | ||
|
||
.PHONY: clean | ||
clean: | ||
rm -f $(OBJ) $(DEP) uinputchars |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
This program reads a character string and translates it into virtual | ||
keystrokes that are entered into the system via /dev/uinput. | ||
|
||
The key difficulty (pun intended) is to map characters to keystrokes. | ||
These are the principal bits and pieces involved, along with | ||
highly-simplified descriptions: | ||
|
||
- Character Encoding: This defines the representation of a character | ||
by a numeric value (or a sequence of numeric values) in the input | ||
character string. On modern, western systems, a typical character | ||
encoding is UTF-8. | ||
|
||
- Kernel Keymap: Each key on the keyboard has an associated Keycode | ||
(or Event Code, defined as KEY_... macros in | ||
linux/input-event-codes.h). The Kernel Keymap maps a Keycode (or a | ||
combination of Keycodes, if modifier or compose keys are pressed) to | ||
an Action Code representing a character (or some other action, | ||
defined as K_... macros in linux/keyboard.h). This mapping is | ||
determined by the active keymap (as loaded by the loadkeys utility). | ||
|
||
- The mapping from Action Code to characters is quite complicated and | ||
can be traced in dumpkeys utility. It appears that for ISO-8859-1 | ||
characters (0..255), the lower byte of the Action Code equals the | ||
ISO-8859-1 (= UTF-8) character code. | ||
|
||
Thus, for ISO-8859-1 characters, this mapping is essentially the | ||
identity mapping. This is all this program implements so far; | ||
therefore, it is currently limited to ISO-8859-1 characters. | ||
|
||
Generally, the Action Code of a character appear to be closely | ||
related to their Unicode code point. | ||
|
||
To enter a character via /dev/uinput, a corresponding sequence of | ||
Keycodes is written to this device. This can be done via the | ||
following steps: | ||
|
||
1. Map the character to its corresponding Action Code. | ||
|
||
2. Map the Action Code to a corresponding (sequence of) Keycode(s) via | ||
an inverse keyboard mapping. | ||
|
||
3. Write the Keycode(s) to /dev/uinput. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,37 @@ | ||
# uinputchars | ||
A utility to type character strings into /dev/uinput | ||
A Linux utility to type character strings into `/dev/uinput` | ||
|
||
|
||
## Usage | ||
|
||
A typical use case is [entering | ||
passwords](https://github.com/clawoflight/puma). In contrast to | ||
classical password managers, uinputchars can type character strings | ||
into anything - Web forms, e-mail clients, Emacs - without any client | ||
support. In contrast to xdotool, it does not require X; it also works | ||
under Wayland or even on the console. | ||
|
||
Generally, uinputchars is run without arguments. | ||
|
||
Character strings are read from standard input. There is currently no | ||
option to pass them on the command line because this would make them | ||
appear in the process table. | ||
|
||
The current implementation only accepts ISO-8859-1 characters (encoded | ||
as specified by the locale). Depending on the kernel keymap in use, | ||
only a subset of them may be accessible. | ||
|
||
The uinputchars utility needs to retrieve the kernel keymap and to | ||
write into `/dev/uinput`; both will generally require root rights. It | ||
is recommended to configure this in `/etc/sudoers`. | ||
|
||
Applications receiving events from `/dev/uinput` must be given time to | ||
process them. This is achieved by brief sleeps that can be adjusted | ||
via command-line options. | ||
|
||
|
||
## Installation | ||
|
||
Under Linux, just run (GNU) <kbd>make</kbd>, and move or link the | ||
resulting executable to wherever you want. If this does not work, I | ||
welcome your patches. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/* Copyright 2019 Justus Piater */ | ||
/* This file is part of UINPUTCHARS. | ||
UINPUTCHARS is free software: you can redistribute it and/or modify | ||
it under the terms of the GNU General Public License as published by | ||
the Free Software Foundation, either version 3 of the License, or | ||
(at your option) any later version. | ||
UINPUTCHARS is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU General Public License for more details. | ||
You should have received a copy of the GNU General Public License | ||
along with UINPUTCHARS. If not, see <https://www.gnu.org/licenses/>. */ | ||
|
||
#ifndef INVKEYMAP_H | ||
#define INVKEYMAP_H | ||
|
||
typedef struct { | ||
unsigned char modifiers; | ||
unsigned char principal; | ||
} keyvent; | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
/* Copyright 2019 Justus Piater, with one exception documented below */ | ||
/* This file is part of UINPUTCHARS. | ||
UINPUTCHARS is free software: you can redistribute it and/or modify | ||
it under the terms of the GNU General Public License as published by | ||
the Free Software Foundation, either version 3 of the License, or | ||
(at your option) any later version. | ||
UINPUTCHARS is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU General Public License for more details. | ||
You should have received a copy of the GNU General Public License | ||
along with UINPUTCHARS. If not, see <https://www.gnu.org/licenses/>. */ | ||
|
||
/* Some documentation relevant to this code: | ||
man 4 console_ioctl | ||
*/ | ||
|
||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <stdint.h> | ||
#include <string.h> | ||
#include <errno.h> | ||
#include <unistd.h> | ||
#include <fcntl.h> | ||
#include <sys/ioctl.h> | ||
#include <linux/kd.h> | ||
#include <linux/keyboard.h> | ||
#include <linux/input-event-codes.h> | ||
|
||
#include "keymap.h" | ||
|
||
#define MAX_KEYVENTS 0x100 | ||
#define LINEFEED 0x0a | ||
|
||
|
||
/* The two functions is_a_console() and getfd() below evolved from | ||
code copied from kbd/src/getfd.c (GPL; Copyright (C) 1994-1999 | ||
Andries E. Brouwer) from http://kbd-project.org/. | ||
This reused GPL (v2 or later) code is one reason why all parts of | ||
UINPUTCHARS are released under the GPL. */ | ||
|
||
static int is_a_console(int fd) { | ||
char arg = 0; | ||
return (isatty(fd) && | ||
ioctl(fd, KDGKBTYPE, &arg) == 0 && | ||
((arg == KB_101) || (arg == KB_84)) ); | ||
} | ||
|
||
|
||
static int getfd() { | ||
static char *conspath[] = | ||
{ "/proc/self/fd/0", | ||
"/dev/tty", | ||
"/dev/tty0", | ||
"/dev/vc/0", | ||
"/dev/systty", | ||
"/dev/console", | ||
NULL }; | ||
|
||
for (int i = 0; conspath[i]; i++) { | ||
/* Permissions don't matter: */ | ||
int fd = open(conspath[i], O_RDWR); | ||
if (fd < 0) fd = open(conspath[i], O_WRONLY); | ||
if (fd < 0) fd = open(conspath[i], O_RDONLY); | ||
if (fd >= 0) { | ||
if (is_a_console(fd)) | ||
return fd; | ||
close(fd); | ||
} | ||
} | ||
|
||
for (int fd = 0; fd < 3; fd++) | ||
if (is_a_console(fd)) | ||
return fd; | ||
|
||
fprintf(stderr, | ||
"Couldn't get a file descriptor referring to the console\n"); | ||
return -1; | ||
} | ||
|
||
|
||
static void print_keyventry(unsigned int c, unsigned char modifiers, | ||
unsigned char principal) { | ||
printf("[%02x=%c %02x %3u]\n", c, c, modifiers, principal); | ||
} | ||
|
||
static void print_keyvent(const keyvent* invkeymap, unsigned char c) { | ||
print_keyventry(c, invkeymap[c].modifiers, invkeymap[c].principal); | ||
} | ||
|
||
|
||
void print_invkeymap(const keyvent* invkeymap) { | ||
for (int c = 0; c < MAX_KEYVENTS; c++) { | ||
if (invkeymap[c].principal) { | ||
printf("%02x ", c); | ||
print_keyvent(invkeymap, c); | ||
} | ||
} | ||
} | ||
|
||
|
||
static void get_keys(int fd, keyvent* invkeymap) { | ||
/* This loop was inspired by lk_kernel_keys() | ||
in kbd/src/libkeymap/kernel.c (GPL) from http://kbd-project.org/. */ | ||
for (int table = 0; table < MAX_NR_KEYMAPS; table++) { | ||
for (int index = 0; index < NR_KEYS; index++) { | ||
struct kbentry kbe; | ||
kbe.kb_table = table; | ||
kbe.kb_index = index; | ||
kbe.kb_value = 0; | ||
|
||
if (ioctl(fd, KDGKBENT, (unsigned long)&kbe)) | ||
fprintf(stderr, "KDGKBENT: %s: error at index %d in table %d\n", | ||
strerror(errno), index, table); | ||
|
||
if (!index && kbe.kb_value == K_NOSUCHMAP) | ||
break; | ||
|
||
if (KTYP(kbe.kb_value) == KT_LATIN || | ||
KTYP(kbe.kb_value) == KT_LETTER ) { | ||
int charvalue = KVAL(kbe.kb_value); | ||
if (!invkeymap[charvalue].principal) { | ||
/* Prefer lower-valued tables */ | ||
invkeymap[charvalue].modifiers = table; | ||
invkeymap[charvalue].principal = index; | ||
} | ||
} | ||
else if (kbe.kb_value == K_ENTER && | ||
!invkeymap[LINEFEED].principal) { | ||
invkeymap[LINEFEED].modifiers = table; | ||
invkeymap[LINEFEED].principal = index; | ||
} | ||
} | ||
} | ||
} | ||
|
||
|
||
keyvent* get_invkeymap() { | ||
int fd = getfd(); | ||
if (fd < 0) | ||
return NULL; | ||
|
||
keyvent* invkeymap = calloc(MAX_KEYVENTS, sizeof(*invkeymap)); | ||
if (!invkeymap) { | ||
perror("invkeymap"); | ||
return NULL; | ||
} | ||
|
||
get_keys(fd, invkeymap); | ||
close(fd); | ||
|
||
return invkeymap; | ||
} | ||
|
||
|
||
void release_invkeymap(keyvent* invkeymap) { | ||
free(invkeymap); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/* Copyright 2019 Justus Piater */ | ||
/* This file is part of UINPUTCHARS. | ||
UINPUTCHARS is free software: you can redistribute it and/or modify | ||
it under the terms of the GNU General Public License as published by | ||
the Free Software Foundation, either version 3 of the License, or | ||
(at your option) any later version. | ||
UINPUTCHARS is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU General Public License for more details. | ||
You should have received a copy of the GNU General Public License | ||
along with UINPUTCHARS. If not, see <https://www.gnu.org/licenses/>. */ | ||
|
||
#include "invkeymap.h" | ||
|
||
keyvent* get_invkeymap(void); | ||
void release_invkeymap(keyvent* invkeymap); | ||
void print_invkeymap(const keyvent* invkeymap); |
Oops, something went wrong.