aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorverdant <i@glowisle.me>2026-05-17 19:15:38 +0800
committerverdant <i@glowisle.me>2026-05-17 19:15:38 +0800
commit35576743d13156dd0ccd9dbcbbd66b2cbca29c91 (patch)
tree27fa9e1f8c327202f995d411df59d611c7e6ba36
parent98d39fc8f00ca0331662ae26b3fca8ed20ab49e4 (diff)
downloadkl-35576743d13156dd0ccd9dbcbbd66b2cbca29c91.tar.gz
kl-35576743d13156dd0ccd9dbcbbd66b2cbca29c91.zip
Add config parser and route
-rw-r--r--config.c117
-rw-r--r--config.h36
-rw-r--r--main.c490
3 files changed, 437 insertions, 206 deletions
diff --git a/config.c b/config.c
new file mode 100644
index 0000000..2913a4e
--- /dev/null
+++ b/config.c
@@ -0,0 +1,117 @@
+#include <sys/types.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <limits.h>
+#include <pwd.h>
+#include <stdlib.h>
+
+#include "config.h"
+
+void fix_config_file_owner(const char *config_path) {
+ char *sudo_uid_str = getenv("SUDO_UID");
+ char *sudo_gid_str = getenv("SUDO_GID");
+
+ if (sudo_uid_str && sudo_gid_str) {
+ uid_t original_uid = atoi(sudo_uid_str);
+ gid_t original_gid = atoi(sudo_gid_str);
+
+ chown(config_path, original_uid, original_gid);
+ }
+}
+
+struct config* prepare_config_file() {
+ struct config* cfg = malloc(sizeof(struct config));
+ if (!cfg) {
+ return NULL;
+ }
+
+ char* sudo_user = getenv("SUDO_USER");
+ cfg->home = malloc(PATH_MAX);
+ if (!cfg->home) {
+ return NULL;
+ }
+
+ snprintf(cfg->home, PATH_MAX, "/home/%s", sudo_user);
+
+ cfg->config_file_path = malloc(strlen(cfg->home) + strlen("/.klrc"));
+
+ snprintf(cfg->config_file_path, PATH_MAX, "%s/.klrc", cfg->home);
+
+ if (access(cfg->config_file_path, F_OK) == -1) {
+ FILE* fp = fopen(cfg->config_file_path, "a");
+ if (!fp) {
+ return NULL;
+ }
+ fputs(CONFIG_FILE_COMMENT, fp);
+ fix_config_file_owner(cfg->config_file_path);
+ printf("%s\n", cfg->config_file_path);
+ fclose(fp);
+ }
+ return cfg;
+}
+
+struct config* parese_config(struct config* cfg) {
+ if (!cfg) {
+ return NULL;
+ }
+
+ FILE* fp = fopen(cfg->config_file_path, "r");
+ if (!fp) {
+ return NULL;
+ }
+
+
+ int line_count = 0;
+ char line[128];
+ char key[64] = {0};
+ char val[64] = {0};
+
+ while (fgets(line, sizeof(line), fp)) {
+ line_count++;
+ /* Skip comment and blank lines */
+ if (line[0] == '#' || line[0] == '\n' || line[0] == '\r') {
+ continue;
+ }
+
+ int count = sscanf(line, "%s = %s", key, val);
+ if (count != 2) {
+ printf("Error at %s:%d\n invalid token: %s", cfg->config_file_path, line_count, line);
+ return NULL;
+ }
+
+ if (CFG_COMPLETE(key, "device")) {
+ strncpy(cfg->device, val, sizeof(cfg->device) - 1);
+ cfg->device[sizeof(cfg->device) - 1] = '\0';
+ } else if (CFG_COMPLETE(key, "enable_time")) {
+ if (CFG_COMPLETE(val, "true")) {
+ cfg->enable_time = true;
+ } else {
+ cfg->enable_time = false;
+ }
+ } else if (CFG_COMPLETE(key, "enable_key_counter")) {
+ if (CFG_COMPLETE(val, "true")) {
+ cfg->enable_keys_counter = true;
+ } else {
+ cfg->enable_keys_counter = false;
+ }
+ }
+ }
+
+ fclose(fp);
+
+ return cfg;
+}
+
+struct config* config_init() {
+ struct config *cfg = prepare_config_file();
+ if (!cfg) {
+ return NULL;
+ }
+
+ if (parese_config(cfg) == NULL) {
+ return NULL;
+ }
+
+
+ return cfg;
+}
diff --git a/config.h b/config.h
new file mode 100644
index 0000000..2911c70
--- /dev/null
+++ b/config.h
@@ -0,0 +1,36 @@
+#ifndef KC_CONFIG_H
+#define KC_CONFIG_H
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define PROGRAM_NAME "kl"
+#define PROGRAM_FULL_NAME "Keyboard Listener (kl)"
+#define PROGRAM_VERSION "0.1.1"
+#define PROGRAM_AUTHORS "Verdant <im@verdant.ee>"
+
+#define CONFIG_FILE_COMMENT "# kl config file (v"PROGRAM_VERSION")\n" \
+ "#\n" \
+ "# Please see your README for details.\n" \
+ "#\n" \
+ "# This file was auto-generated because it was missing.\n" \
+
+#define CFG_COMPLETE(key, val) ((strcmp((key), (val)) == 0) && ((val)[0] != '\0'))
+
+struct config {
+ char* home;
+ char* config_file_path;
+ char device[256];
+ bool enable_time;
+ bool enable_keys_counter;
+};
+
+struct config* parese_config(struct config* cfg);
+
+struct config* prepare_config_file();
+
+struct config* config_init();
+
+
+#endif
diff --git a/main.c b/main.c
index 8faac24..7c7cd51 100644
--- a/main.c
+++ b/main.c
@@ -5,234 +5,312 @@
#include <termios.h>
#include <errno.h>
#include <stdbool.h>
+#include <sys/time.h>
+#include <time.h>
#include <string.h>
-
-#define PROGRAM_NAME "kl"
+#include "config.h"
static struct termios original_term;
-const char *key_names[256] = {0};
+const char * key_names[256] = {
+ 0
+};
+static int repeat_counters[256] = {
+ 1
+};
+static int current_repeat_key = 0;
+static int line_lock = -1;
-void init_key_names() {
- key_names[KEY_Q] = "Q";
- key_names[KEY_W] = "W";
- key_names[KEY_E] = "E";
- key_names[KEY_R] = "R";
- key_names[KEY_T] = "T";
- key_names[KEY_Y] = "Y";
- key_names[KEY_U] = "U";
- key_names[KEY_I] = "I";
- key_names[KEY_O] = "O";
- key_names[KEY_P] = "P";
- key_names[KEY_A] = "A";
- key_names[KEY_S] = "S";
- key_names[KEY_D] = "D";
- key_names[KEY_F] = "F";
- key_names[KEY_G] = "G";
- key_names[KEY_H] = "H";
- key_names[KEY_J] = "J";
- key_names[KEY_K] = "K";
- key_names[KEY_L] = "L";
- key_names[KEY_Z] = "Z";
- key_names[KEY_X] = "X";
- key_names[KEY_C] = "C";
- key_names[KEY_V] = "V";
- key_names[KEY_B] = "B";
- key_names[KEY_N] = "N";
- key_names[KEY_M] = "M";
-
- key_names[KEY_1] = "1";
- key_names[KEY_2] = "2";
- key_names[KEY_3] = "3";
- key_names[KEY_4] = "4";
- key_names[KEY_5] = "5";
- key_names[KEY_6] = "6";
- key_names[KEY_7] = "7";
- key_names[KEY_8] = "8";
- key_names[KEY_9] = "9";
- key_names[KEY_0] = "0";
-
- key_names[KEY_MINUS] = "-";
- key_names[KEY_EQUAL] = "=";
- key_names[KEY_LEFTBRACE] = "[";
- key_names[KEY_RIGHTBRACE] = "]";
- key_names[KEY_SEMICOLON] = ";";
- key_names[KEY_APOSTROPHE] = "'";
- key_names[KEY_GRAVE] = "`";
- key_names[KEY_BACKSLASH] = "\\";
- key_names[KEY_COMMA] = ",";
- key_names[KEY_DOT] = ".";
- key_names[KEY_SLASH] = "/";
- key_names[KEY_SPACE] = "<SPACE>";
-
- key_names[KEY_ESC] = "<ESC>";
- key_names[KEY_BACKSPACE] = "<BACKSPACE>";
- key_names[KEY_TAB] = "<TAB>";
- key_names[KEY_ENTER] = "<ENTER>";
- key_names[KEY_LEFTSHIFT] = "<L_SHIFT>";
- key_names[KEY_RIGHTSHIFT] = "<R_SHIFT>";
- key_names[KEY_LEFTCTRL] = "<L_CTRL>";
- key_names[KEY_RIGHTCTRL] = "<R_CTRL>";
- key_names[KEY_LEFTALT] = "<L_ALT>";
- key_names[KEY_RIGHTALT] = "<R_ALT>";
- key_names[KEY_LEFTMETA] = "<L_META>";
- key_names[KEY_RIGHTMETA] = "<R_META>";
- key_names[KEY_CAPSLOCK] = "<CAPSLOCK>";
- key_names[KEY_NUMLOCK] = "<NUMLOCK>";
- key_names[KEY_SCROLLLOCK] = "<SCROLLLOCK>";
-
- key_names[KEY_F1] = "<F1>";
- key_names[KEY_F2] = "<F2>";
- key_names[KEY_F3] = "<F3>";
- key_names[KEY_F4] = "<F4>";
- key_names[KEY_F5] = "<F5>";
- key_names[KEY_F6] = "<F6>";
- key_names[KEY_F7] = "<F7>";
- key_names[KEY_F8] = "<F8>";
- key_names[KEY_F9] = "<F9>";
- key_names[KEY_F10] = "<F10>";
- key_names[KEY_F11] = "<F11>";
- key_names[KEY_F12] = "<F12>";
- key_names[KEY_F13] = "<F13>";
- key_names[KEY_F14] = "<F14>";
- key_names[KEY_F15] = "<F15>";
- key_names[KEY_F16] = "<F16>";
- key_names[KEY_F17] = "<F17>";
- key_names[KEY_F18] = "<F18>";
- key_names[KEY_F19] = "<F19>";
- key_names[KEY_F20] = "<F20>";
- key_names[KEY_F21] = "<F21>";
- key_names[KEY_F22] = "<F22>";
- key_names[KEY_F23] = "<F23>";
- key_names[KEY_F24] = "<F24>";
-
- key_names[KEY_KP0] = "<KP0>";
- key_names[KEY_KP1] = "<KP1>";
- key_names[KEY_KP2] = "<KP2>";
- key_names[KEY_KP3] = "<KP3>";
- key_names[KEY_KP4] = "<KP4>";
- key_names[KEY_KP5] = "<KP5>";
- key_names[KEY_KP6] = "<KP6>";
- key_names[KEY_KP7] = "<KP7>";
- key_names[KEY_KP8] = "<KP8>";
- key_names[KEY_KP9] = "<KP9>";
- key_names[KEY_KPDOT] = "<KP.>";
- key_names[KEY_KPCOMMA] = "<KP,>";
- key_names[KEY_KPENTER] = "<KPENTER>";
- key_names[KEY_KPMINUS] = "<KP->";
- key_names[KEY_KPPLUS] = "<KP+>";
- key_names[KEY_KPSLASH] = "<KP/>";
- key_names[KEY_KPASTERISK] = "<KP*>";
- key_names[KEY_KPEQUAL] = "<KP=>";
-
- key_names[KEY_UP] = "<UP>";
- key_names[KEY_DOWN] = "<DOWN>";
- key_names[KEY_LEFT] = "<LEFT>";
- key_names[KEY_RIGHT] = "<RIGHT>";
- key_names[KEY_HOME] = "<HOME>";
- key_names[KEY_END] = "<END>";
- key_names[KEY_PAGEUP] = "<PAGEUP>";
- key_names[KEY_PAGEDOWN] = "<PAGEDOWN>";
- key_names[KEY_INSERT] = "<INSERT>";
- key_names[KEY_DELETE] = "<DELETE>";
-
- key_names[KEY_MUTE] = "<MUTE>";
- key_names[KEY_VOLUMEDOWN] = "<VOLUMEDOWN>";
- key_names[KEY_VOLUMEUP] = "<VOLUMEUP>";
- key_names[KEY_POWER] = "<POWER>";
- key_names[KEY_SLEEP] = "<SLEEP>";
- key_names[KEY_WAKEUP] = "<WAKEUP>";
- key_names[KEY_PLAY] = "<PLAY>";
- key_names[KEY_PAUSE] = "<PAUSE>";
- key_names[KEY_PLAYPAUSE] = "<PLAYPAUSE>";
- key_names[KEY_STOPCD] = "<STOP>";
- key_names[KEY_PREVIOUSSONG] = "<PREVIOUS>";
- key_names[KEY_NEXTSONG] = "<NEXT>";
- key_names[KEY_REWIND] = "<REWIND>";
- key_names[KEY_FASTFORWARD] = "<FASTFORWARD>";
- key_names[KEY_RECORD] = "<RECORD>";
- key_names[KEY_EJECTCD] = "<EJECT>";
-
- key_names[KEY_SYSRQ] = "<SYSRQ>";
- key_names[KEY_PAUSE] = "<PAUSE>";
- key_names[KEY_MENU] = "<MENU>";
- key_names[KEY_CALC] = "<CALC>";
- key_names[KEY_MAIL] = "<MAIL>";
- key_names[KEY_WWW] = "<WWW>";
- key_names[KEY_SEARCH] = "<SEARCH>";
- key_names[KEY_BACK] = "<BACK>";
- key_names[KEY_FORWARD] = "<FORWARD>";
- key_names[KEY_REFRESH] = "<REFRESH>";
- key_names[KEY_STOP] = "<STOP>";
- key_names[KEY_COPY] = "<COPY>";
- key_names[KEY_CUT] = "<CUT>";
- key_names[KEY_PASTE] = "<PASTE>";
- key_names[KEY_UNDO] = "<UNDO>";
- key_names[KEY_REDO] = "<REDO>";
- key_names[KEY_FIND] = "<FIND>";
- key_names[KEY_HELP] = "<HELP>";
- key_names[KEY_FILE] = "<FILE>";
- key_names[KEY_SAVE] = "<SAVE>";
- key_names[KEY_NEW] = "<NEW>";
- key_names[KEY_OPEN] = "<OPEN>";
- key_names[KEY_CLOSE] = "<CLOSE>";
- key_names[KEY_EXIT] = "<EXIT>";
- key_names[KEY_PRINT] = "<PRINT>";
- key_names[KEY_BRIGHTNESSDOWN] = "<BRIGHTNESSDOWN>";
- key_names[KEY_BRIGHTNESSUP] = "<BRIGHTNESSUP>";
- key_names[KEY_DISPLAY_OFF] = "<DISPLAYOFF>";
- key_names[KEY_MICMUTE] = "<MICMUTE>";
- key_names[KEY_WLAN] = "<WLAN>";
- key_names[KEY_BLUETOOTH] = "<BLUETOOTH>";
-}
+enum KEY_STATUS {
+ KEY_RELEASE = 0,
+ KEY_PRESS = 1,
+ KEY_REPEAT = 2
+};
void usage() {
- printf("Usage: %s <EVENT_FILE_PATH>.\n", PROGRAM_NAME);
+ printf("Usage: %s <EVENT_FILE_PATH>.\n", PROGRAM_NAME);
+}
+
+void version() {
+ printf("%s (v%s)\n", PROGRAM_FULL_NAME, PROGRAM_VERSION);
+ printf("%s\n", PROGRAM_AUTHORS);
+
+}
+
+void init_key_names() {
+ key_names[KEY_RESERVED] = "KEY_RESERVED";
+ key_names[KEY_Q] = "Q";
+ key_names[KEY_W] = "W";
+ key_names[KEY_E] = "E";
+ key_names[KEY_R] = "R";
+ key_names[KEY_T] = "T";
+ key_names[KEY_Y] = "Y";
+ key_names[KEY_U] = "U";
+ key_names[KEY_I] = "I";
+ key_names[KEY_O] = "O";
+ key_names[KEY_P] = "P";
+ key_names[KEY_A] = "A";
+ key_names[KEY_S] = "S";
+ key_names[KEY_D] = "D";
+ key_names[KEY_F] = "F";
+ key_names[KEY_G] = "G";
+ key_names[KEY_H] = "H";
+ key_names[KEY_J] = "J";
+ key_names[KEY_K] = "K";
+ key_names[KEY_L] = "L";
+ key_names[KEY_Z] = "Z";
+ key_names[KEY_X] = "X";
+ key_names[KEY_C] = "C";
+ key_names[KEY_V] = "V";
+ key_names[KEY_B] = "B";
+ key_names[KEY_N] = "N";
+ key_names[KEY_M] = "M";
+
+ key_names[KEY_1] = "1";
+ key_names[KEY_2] = "2";
+ key_names[KEY_3] = "3";
+ key_names[KEY_4] = "4";
+ key_names[KEY_5] = "5";
+ key_names[KEY_6] = "6";
+ key_names[KEY_7] = "7";
+ key_names[KEY_8] = "8";
+ key_names[KEY_9] = "9";
+ key_names[KEY_0] = "0";
+
+ key_names[KEY_MINUS] = "-";
+ key_names[KEY_EQUAL] = "=";
+ key_names[KEY_LEFTBRACE] = "[";
+ key_names[KEY_RIGHTBRACE] = "]";
+ key_names[KEY_SEMICOLON] = ";";
+ key_names[KEY_APOSTROPHE] = "'";
+ key_names[KEY_GRAVE] = "`";
+ key_names[KEY_BACKSLASH] = "\\";
+ key_names[KEY_COMMA] = ",";
+ key_names[KEY_DOT] = ".";
+ key_names[KEY_SLASH] = "/";
+ key_names[KEY_SPACE] = "<SPACE>";
+
+ key_names[KEY_ESC] = "<ESC>";
+ key_names[KEY_BACKSPACE] = "<BACKSPACE>";
+ key_names[KEY_TAB] = "<TAB>";
+ key_names[KEY_ENTER] = "<ENTER>";
+ key_names[KEY_LEFTSHIFT] = "<L_SHIFT>";
+ key_names[KEY_RIGHTSHIFT] = "<R_SHIFT>";
+ key_names[KEY_LEFTCTRL] = "<L_CTRL>";
+ key_names[KEY_RIGHTCTRL] = "<R_CTRL>";
+ key_names[KEY_LEFTALT] = "<L_ALT>";
+ key_names[KEY_RIGHTALT] = "<R_ALT>";
+ key_names[KEY_LEFTMETA] = "<L_META>";
+ key_names[KEY_RIGHTMETA] = "<R_META>";
+ key_names[KEY_CAPSLOCK] = "<CAPSLOCK>";
+ key_names[KEY_NUMLOCK] = "<NUMLOCK>";
+ key_names[KEY_SCROLLLOCK] = "<SCROLLLOCK>";
+
+ key_names[KEY_F1] = "<F1>";
+ key_names[KEY_F2] = "<F2>";
+ key_names[KEY_F3] = "<F3>";
+ key_names[KEY_F4] = "<F4>";
+ key_names[KEY_F5] = "<F5>";
+ key_names[KEY_F6] = "<F6>";
+ key_names[KEY_F7] = "<F7>";
+ key_names[KEY_F8] = "<F8>";
+ key_names[KEY_F9] = "<F9>";
+ key_names[KEY_F10] = "<F10>";
+ key_names[KEY_F11] = "<F11>";
+ key_names[KEY_F12] = "<F12>";
+ key_names[KEY_F13] = "<F13>";
+ key_names[KEY_F14] = "<F14>";
+ key_names[KEY_F15] = "<F15>";
+ key_names[KEY_F16] = "<F16>";
+ key_names[KEY_F17] = "<F17>";
+ key_names[KEY_F18] = "<F18>";
+ key_names[KEY_F19] = "<F19>";
+ key_names[KEY_F20] = "<F20>";
+ key_names[KEY_F21] = "<F21>";
+ key_names[KEY_F22] = "<F22>";
+ key_names[KEY_F23] = "<F23>";
+ key_names[KEY_F24] = "<F24>";
+
+ key_names[KEY_KP0] = "<KP0>";
+ key_names[KEY_KP1] = "<KP1>";
+ key_names[KEY_KP2] = "<KP2>";
+ key_names[KEY_KP3] = "<KP3>";
+ key_names[KEY_KP4] = "<KP4>";
+ key_names[KEY_KP5] = "<KP5>";
+ key_names[KEY_KP6] = "<KP6>";
+ key_names[KEY_KP7] = "<KP7>";
+ key_names[KEY_KP8] = "<KP8>";
+ key_names[KEY_KP9] = "<KP9>";
+ key_names[KEY_KPDOT] = "<KP.>";
+ key_names[KEY_KPCOMMA] = "<KP,>";
+ key_names[KEY_KPENTER] = "<KPENTER>";
+ key_names[KEY_KPMINUS] = "<KP->";
+ key_names[KEY_KPPLUS] = "<KP+>";
+ key_names[KEY_KPSLASH] = "<KP/>";
+ key_names[KEY_KPASTERISK] = "<KP*>";
+ key_names[KEY_KPEQUAL] = "<KP=>";
+
+ key_names[KEY_UP] = "<UP>";
+ key_names[KEY_DOWN] = "<DOWN>";
+ key_names[KEY_LEFT] = "<LEFT>";
+ key_names[KEY_RIGHT] = "<RIGHT>";
+ key_names[KEY_HOME] = "<HOME>";
+ key_names[KEY_END] = "<END>";
+ key_names[KEY_PAGEUP] = "<PAGEUP>";
+ key_names[KEY_PAGEDOWN] = "<PAGEDOWN>";
+ key_names[KEY_INSERT] = "<INSERT>";
+ key_names[KEY_DELETE] = "<DELETE>";
+
+ key_names[KEY_MUTE] = "<MUTE>";
+ key_names[KEY_VOLUMEDOWN] = "<VOLUMEDOWN>";
+ key_names[KEY_VOLUMEUP] = "<VOLUMEUP>";
+ key_names[KEY_POWER] = "<POWER>";
+ key_names[KEY_SLEEP] = "<SLEEP>";
+ key_names[KEY_WAKEUP] = "<WAKEUP>";
+ key_names[KEY_PLAY] = "<PLAY>";
+ key_names[KEY_PAUSE] = "<PAUSE>";
+ key_names[KEY_PLAYPAUSE] = "<PLAYPAUSE>";
+ key_names[KEY_STOPCD] = "<STOP>";
+ key_names[KEY_PREVIOUSSONG] = "<PREVIOUS>";
+ key_names[KEY_NEXTSONG] = "<NEXT>";
+ key_names[KEY_REWIND] = "<REWIND>";
+ key_names[KEY_FASTFORWARD] = "<FASTFORWARD>";
+ key_names[KEY_RECORD] = "<RECORD>";
+ key_names[KEY_EJECTCD] = "<EJECT>";
+
+ key_names[KEY_SYSRQ] = "<SYSRQ>";
+ key_names[KEY_PAUSE] = "<PAUSE>";
+ key_names[KEY_MENU] = "<MENU>";
+ key_names[KEY_CALC] = "<CALC>";
+ key_names[KEY_MAIL] = "<MAIL>";
+ key_names[KEY_WWW] = "<WWW>";
+ key_names[KEY_SEARCH] = "<SEARCH>";
+ key_names[KEY_BACK] = "<BACK>";
+ key_names[KEY_FORWARD] = "<FORWARD>";
+ key_names[KEY_REFRESH] = "<REFRESH>";
+ key_names[KEY_STOP] = "<STOP>";
+ key_names[KEY_COPY] = "<COPY>";
+ key_names[KEY_CUT] = "<CUT>";
+ key_names[KEY_PASTE] = "<PASTE>";
+ key_names[KEY_UNDO] = "<UNDO>";
+ key_names[KEY_REDO] = "<REDO>";
+ key_names[KEY_FIND] = "<FIND>";
+ key_names[KEY_HELP] = "<HELP>";
+ key_names[KEY_FILE] = "<FILE>";
+ key_names[KEY_SAVE] = "<SAVE>";
+ key_names[KEY_NEW] = "<NEW>";
+ key_names[KEY_OPEN] = "<OPEN>";
+ key_names[KEY_CLOSE] = "<CLOSE>";
+ key_names[KEY_EXIT] = "<EXIT>";
+ key_names[KEY_PRINT] = "<PRINT>";
+ key_names[KEY_BRIGHTNESSDOWN] = "<BRIGHTNESSDOWN>";
+ key_names[KEY_BRIGHTNESSUP] = "<BRIGHTNESSUP>";
+ key_names[KEY_DISPLAY_OFF] = "<DISPLAYOFF>";
+ key_names[KEY_MICMUTE] = "<MICMUTE>";
+ key_names[KEY_WLAN] = "<WLAN>";
+ key_names[KEY_BLUETOOTH] = "<BLUETOOTH>";
}
void disable_term_echo() {
- struct termios new_setting, init_setting;
- tcgetattr(0, &init_setting);
- new_setting = init_setting;
+ struct termios new_setting, init_setting;
+ tcgetattr(0, & original_term);
+ new_setting = original_term;
- new_setting.c_lflag&=~ECHO;
- tcsetattr(0, TCSANOW, &new_setting);
+ new_setting.c_lflag &= ~ECHO;
+ tcsetattr(0, TCSANOW, & new_setting);
}
void enable_term_echo() {
- tcsetattr(0, TCSANOW, &original_term);
+ tcsetattr(0, TCSANOW, & original_term);
+}
+
+void print_pure(struct input_event * ie) {
+ if (repeat_counters[ie -> code] != 1) {
+ printf("%-15s x%-13d\r", key_names[ie -> code], repeat_counters[ie -> code]);
+ } else {
+ printf("\r%s", key_names[ie -> code]);
+ }
+
+ fflush(stdout);
}
-int main(int argc, char** argv) {
- if (argc != 2 || strcmp(argv[1], "--help") == 0) {
- usage();
- return -1;
- }
+void print_with_time(struct input_event * ie) {
+ struct tm * tm_info;
+ char time_buf[64];
+ time_t sec = (time_t) ie -> input_event_sec;
+ tm_info = localtime( & sec);
+ strftime(time_buf, sizeof(time_buf), "%F %T", tm_info);
+
+ if (repeat_counters[ie -> code] != 1) {
+ printf("%s.%06ld: %s x%d\n", time_buf, (long) ie -> time.tv_usec, key_names[ie -> code], repeat_counters[ie -> code]);
+ } else {
+ printf("%s.%06ld: %s\n", time_buf, (long) ie -> time.tv_usec, key_names[ie -> code]);
+
+ }
+
+ return;
+}
+
+int main(int argc, char ** argv) {
+ if (argv[1] != NULL && (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0)) {
+ usage();
+ return -1;
+ } else if (argv[1] != NULL && (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-v")) == 0) {
+ version();
+ return -1;
+ }
+
+ setvbuf(stdout, NULL, _IONBF, 0);
+ disable_term_echo();
+
+ struct config * cfg = config_init();
+ if (!cfg) {
+ return -1;
+ }
+
+ printf("Device: %s\n", cfg -> device);
+
+ struct input_event ie;
+ int fd = open(cfg -> device, O_RDONLY);
+
+ if (fd == -1 && errno == EACCES) {
+ printf("Permission denied: please run %s with sudo.\n", PROGRAM_NAME);
+ return -1;
+ }
+
+ if (fd == -1 && errno == ENOENT) {
+ printf("No such file or directory: %s\n", cfg -> device);
+ return -1;
- disable_term_echo();
+ }
- struct input_event ie;
- int fd = open(argv[1], O_RDONLY);
+ init_key_names();
- if (fd == -1 && errno == EACCES) {
- printf("Permission denied: please run %s with sudo.\n", PROGRAM_NAME);
- return -1;
- }
+ void( * fp)(struct input_event * ie) = (cfg -> enable_time == true) ? print_with_time : print_pure;
- init_key_names();
+ while (1) {
+ read(fd, & ie, sizeof(ie));
+ if (ie.type == EV_KEY) {
- while (1) {
- read(fd, &ie, sizeof(ie));
+ if (ie.value == KEY_PRESS) {
+ if (line_lock != -1 && line_lock != ie.code && !cfg -> enable_time) printf("\n");
+ repeat_counters[ie.code] = 1;
+ line_lock = ie.code;
+ fp( & ie);
+ }
- if (ie.type == EV_KEY && ie.value == 2) {
- continue;
- }
+ if (ie.value == KEY_REPEAT) {
+ line_lock = ie.code;
+ repeat_counters[ie.code]++;
+ fp( & ie);
+ }
- if (key_names[ie.code] != NULL && ie.value == 1) {
- printf("%s\n", key_names[ie.code]);
- }
+ if (ie.value == KEY_RELEASE) {
+ repeat_counters[ie.code] = 1;
+ }
+ }
- }
+ }
- enable_term_echo();
- return 0;
+ enable_term_echo();
+ return 0;
}