#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <getopt.h>
#include <fcntl.h>
#include <signal.h>
#include <termios.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <system_error>
#include <linux/kd.h>
#include <linux/keyboard.h>
#include "locale.h"
#include <utmp.h>
#include <array>
#include <sys/inotify.h>
#include "scopeguard.h"
std::array<int, 256> keycode_table = {
0, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23,
24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
54, 55,
56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
70, 71,
72, 73, 74, 75, 76, 77, 76, 79, 80, 81, 82, 83, 84, 85,
86, 87,
88, 89, 90, 91, 111, 221, 94, 95, 96, 211, 128, 127, 129, 208,
131, 126,
108, 109, 112, 111, 113, 181, 97, 98, 99, 100, 102, 103, 104, 105,
106, 107,
239, 160, 174, 176, 222, 157, 123, 110, 139, 134, 209, 210, 133, 115,
116, 117,
232, 133, 134, 135, 140, 248, 191, 192, 122, 188, 245, 158, 161, 193,
223, 227,
198, 199, 200, 147, 159, 151, 178, 201, 146, 203, 166, 236, 230, 235,
234, 233,
163, 204, 253, 153, 162, 144, 164, 177, 152, 190, 208, 129, 130, 231,
209, 210,
136, 220, 143, 246, 251, 137, 138, 182, 183, 184, 93, 184, 247, 132,
170, 219,
249, 205, 207, 149, 150, 154, 155, 167, 168, 169, 171, 172, 173, 165,
175, 179,
180, 0, 185, 186, 187, 118, 119, 120, 121, 229, 194, 195, 196, 197,
148, 202,
101, 212, 237, 214, 215, 216, 217, 218, 228, 142, 213, 240, 241, 242,
243, 244,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0
};
static int isConsole(int fd)
{
char arg = 0;
return (isatty(fd) && ioctl(fd, KDGKBTYPE, &arg) == 0 && ((arg == KB_101) || (arg == KB_84)));
}
static int openConsole(const char *path) {
if (!path) {
return - 1;
}
int fd = open(path, O_RDWR);
if (fd < 0)
fd = open(path, O_WRONLY);
if (fd < 0)
fd = open(path, O_RDONLY);
if (fd < 0)
return -1;
/*if (!isConsole(fd)) {
close(fd);
return -1;
}*/
return fd;
}
void read_utmp() {
int utmpfd = open("/var/run/utmp", O_RDONLY);
struct utmp ut;
while(read(utmpfd, &ut, sizeof(struct utmp)) == sizeof(struct utmp)) {
if (ut.ut_type == USER_PROCESS) {
printf("[%d] [%05d] [%-4.4s] [%-*.*s] [%-*.*s] [%-*.*s]\n",
ut.ut_type, ut.ut_pid, ut.ut_id, 8, UT_NAMESIZE, ut.ut_user,
12, UT_LINESIZE, ut.ut_line, 20, UT_HOSTSIZE, ut.ut_host);
}
}
close(utmpfd);
}
void listenTTY(const char *path) {
struct termios terminal_settings;
unsigned char buf[18]; /* divisible by 3 */
int i, n;
int fd = openConsole(path);
if (fd < 0) {
throw std::runtime_error("Couldn't get a file descriptor referring to the console");
}
__scope_guard {
close(fd);
};
char *m;
int oldkbmode;
if (ioctl(fd, KDGKBMODE, &oldkbmode)) {
throw std::system_error(errno, std::generic_category());
}
__scope_guard {
if (ioctl(fd, KDSKBMODE, oldkbmode)) {
//throw std::system_error(errno, std::generic_category());
}
};
switch (oldkbmode) {
case K_RAW:
m = "RAW";
break;
case K_XLATE:
m = "XLATE";
break;
case K_MEDIUMRAW:
m = "MEDIUMRAW";
break;
case K_UNICODE:
m = "UNICODE";
break;
default:
m = "?UNKNOWN?";
break;
}
printf("kb mode was %s\n", m);
if (oldkbmode != K_XLATE) {
printf("[ if you are trying this under X, it might not work\n"
"since the X server is also reading /dev/console ]\n");
}
printf("\n");
struct termios old;
bool recoverTermios = true;
if (tcgetattr(fd, &old) == -1) {
recoverTermios = false;
//kbd_warning(errno, "tcgetattr");
//warning?!
}
__scope_guard {
if (recoverTermios && tcsetattr(fd, 0, &old) == -1) {
//kbd_warning(errno, "tcsetattr");
//warning?!
}
};
if (tcgetattr(fd, &terminal_settings) == -1) {
//kbd_warning(errno, "tcgetattr");
//warning?!
}
terminal_settings.c_lflag &= ~(ICANON | ECHO | ISIG);
terminal_settings.c_iflag = 0;
terminal_settings.c_cc[VMIN] = sizeof(buf);
terminal_settings.c_cc[VTIME] = 1; /* 0.1 sec intercharacter timeout */
if (tcsetattr(fd, TCSAFLUSH, &terminal_settings) == -1) {
//kbd_warning(errno, "tcsetattr");
//warning?!
}
if (ioctl(fd, KDSKBMODE, K_RAW)) {
throw std::system_error(errno, std::generic_category());
}
/* show keycodes - 2.6 allows 3-byte reports */
for (;;) {
n = read(fd, buf, sizeof(buf));
i = 0;
while (i < n) {
int kc;
const char *s;
s = (buf[i] & 0x80) ? "release" : "press";
if (i + 2 < n && (buf[i] & 0x7f) == 0 && (buf[i + 1] & 0x80) != 0 && (buf[i + 2] & 0x80) != 0) {
kc = ((buf[i + 1] & 0x7f) << 7) |
(buf[i + 2] & 0x7f);
i += 3;
} else {
kc = (buf[i] & 0x7f);
i++;
}
printf("keycode %3d %s\n", keycode_table.at(kc), s);
}
}
}
int main(int argc, char *argv[])
{
// int fd = inotify_init();
//
// if ( fd < 0 ) {
// perror( "inotify_init" );
// }
read_utmp();
// int wd = inotify_add_watch( fd, "/var/run/", IN_MODIFY );
// for (;;) {
// /* Read events forever */
// inotify_event event;
// int numRead = read(fd, &event, sizeof(event));
// if (numRead <= 0) {
// continue;
// }
//
// if (event.len == 0) {
// continue;
// }
//
// if (strcmp(event.name, "utmp") != 0) {
// continue;
// }
//
// /* Process all of the events in buffer returned by read() */
// read_utmp();
// }
listenTTY("/dev/tty1");
return EXIT_SUCCESS;
}