aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile14
-rw-r--r--README12
-rw-r--r--res/stroke_buddy.service6
-rw-r--r--src/common.h24
-rw-r--r--src/config.h7
-rw-r--r--src/key_tracker.c41
-rw-r--r--src/key_tracker.h8
-rw-r--r--src/logger.h5
-rw-r--r--src/main.c40
-rw-r--r--src/report.c48
-rw-r--r--src/report.h8
11 files changed, 188 insertions, 25 deletions
diff --git a/Makefile b/Makefile
index 23b98d2..895b6e0 100644
--- a/Makefile
+++ b/Makefile
@@ -8,8 +8,20 @@ clean:
bin:
mkdir bin
-bin/stroke_buddy: src/main.c
+bin/stroke_buddy: src/main.c src/key_tracker.c src/report.c
${CC} $^ -o $@
run: all
bin/stroke_buddy
+
+install: all
+ cp -p bin/stroke_buddy ~/.local/bin/
+ cp -p res/stroke_buddy.service ~/.config/systemd/user/
+ ln -s ~/.config/systemd/user/stroke_buddy.service ~/.config/systemd/user/default.target.wants/stroke_buddy.service
+ mkdir -p ~/.local/stroke_buddy
+
+uninstall:
+ rm ~/.local/bin/stroke_buddy
+ rm ~/.config/systemd/user/stroke_buddy.service
+ rm ~/.config/systemd/user/default.target.wants/stroke_buddy.service
+# rm -rf ~/.local/stroke_buddy
diff --git a/README b/README
index 7ff63bb..a60272a 100644
--- a/README
+++ b/README
@@ -10,15 +10,17 @@
roadmap
-------
[ ] report generation
- ( ) number of keypresses
- ( ) work time vs idle time
+ (x) number of keypresses
+ (x) work time vs idle time
( ) per-key statistics
( ) per-keyboard statistics
-[ ] security
- ( ) drop privs
- ( ) where to store reports (/var dir?)
+ ( ) new report per day
+[x?] security
+ (n/a) drop privs (add user to input group)
+ (x) where to store reports (~~/var dir?~~ ~/.local/stroke_buddy)
[ ] respond to plug-n-play
[ ] sensible code organization
+[x] systemd user service
license
-------
diff --git a/res/stroke_buddy.service b/res/stroke_buddy.service
new file mode 100644
index 0000000..1dc8a06
--- /dev/null
+++ b/res/stroke_buddy.service
@@ -0,0 +1,6 @@
+[Unit]
+Description=unix philosophy keystroke tracker
+
+[Service]
+Type=exec
+ExecStart=/usr/bin/bash -c 'exec $HOME/.local/bin/stroke_buddy'
diff --git a/src/common.h b/src/common.h
new file mode 100644
index 0000000..6562643
--- /dev/null
+++ b/src/common.h
@@ -0,0 +1,24 @@
+#ifndef COMMON_H
+#define COMMON_H
+
+#include <sys/time.h>
+#include <stdint.h>
+
+#include "config.h"
+#include "logger.h"
+
+typedef struct {
+ double when;
+ int64_t what;
+} keypress_t;
+
+typedef struct {
+ keypress_t* keys;
+ unsigned int length;
+ unsigned int size;
+} keypresses_t;
+
+#define KEYPRESSES_START_SIZE 0x1000 // one page
+#define KEYPRESSES_ADDITIONAL_SIZE 0x1000 // one page
+
+#endif
diff --git a/src/config.h b/src/config.h
index d064cea..0635948 100644
--- a/src/config.h
+++ b/src/config.h
@@ -4,7 +4,10 @@
#define KEYBOARD_EVDEV "/dev/input/event0"
#define PERKEY_LEN 0x100
-#define LOG_LEVEL LOG_INSANEDEBUG
-#define REPORT_PATH "/tmp/report%d.log"
+#define LOG_FP stderr
+#define LOG_LEVEL LOG_INFO
+#define REPORT_PATH "/home/spv/.local/stroke_buddy/%d.log"
+
+#define IDLE_TIME 30
#endif
diff --git a/src/key_tracker.c b/src/key_tracker.c
new file mode 100644
index 0000000..205e29a
--- /dev/null
+++ b/src/key_tracker.c
@@ -0,0 +1,41 @@
+// key tracker
+
+#include <linux/input.h>
+#include <sys/time.h>
+#include <stdlib.h>
+
+#include "report.h"
+#include "common.h"
+
+keypresses_t keypresses;
+
+extern FILE* report_fp;
+
+void log_key(int key) {
+ struct timeval press_time;
+ keypress_t keypress;
+
+ gettimeofday(&press_time, NULL);
+
+ keypress.when = press_time.tv_sec + (press_time.tv_usec / 1000000.0);
+ keypress.what = key;
+
+ if (keypresses.keys == NULL) {
+ keypresses.keys = calloc(KEYPRESSES_START_SIZE, sizeof(keypress_t));
+ keypresses.length = 0;
+ keypresses.size = KEYPRESSES_START_SIZE;
+ }
+
+ if (keypresses.length >= keypresses.size) {
+ keypresses.keys = reallocarray(keypresses.keys, keypresses.size + KEYPRESSES_ADDITIONAL_SIZE, sizeof(keypress_t));
+ keypresses.size += KEYPRESSES_ADDITIONAL_SIZE;
+
+ gen_report(report_fp);
+ }
+
+ keypresses.keys[keypresses.length++] = keypress;
+
+ if (key == KEY_ENTER) {
+ gen_report(report_fp);
+ }
+}
diff --git a/src/key_tracker.h b/src/key_tracker.h
new file mode 100644
index 0000000..59b7716
--- /dev/null
+++ b/src/key_tracker.h
@@ -0,0 +1,8 @@
+#ifndef KEY_TRACKER_H
+#define KEY_TRACKER_H
+
+#include <linux/input.h>
+
+void log_key(int key);
+
+#endif
diff --git a/src/logger.h b/src/logger.h
index 4350cf1..99b7b04 100644
--- a/src/logger.h
+++ b/src/logger.h
@@ -10,12 +10,9 @@ enum log_levels {
LOG_INSANEDEBUG,
};
-#define LOGFP stderr
-#define LOGLEVEL
-
#define LOG(LEVEL, args...) do { \
if (LEVEL <= LOG_LEVEL) { \
- fprintf(LOGFP, args); \
+ fprintf(LOG_FP, args); \
} \
} while (0)
diff --git a/src/main.c b/src/main.c
index 3542f36..a9f14f5 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,13 +1,31 @@
#include <linux/input.h>
#include <sys/time.h>
+#include <signal.h>
+#include <stdlib.h>
#include <stdio.h>
+#include <errno.h>
+#include <string.h>
-#include "logger.h"
-#include "config.h"
+#include "common.h"
+
+#include "key_tracker.h"
+#include "report.h"
+
+FILE* report_fp;
+FILE* evdev_fp;
+
+void handler(int _) {
+ gen_report(report_fp);
+
+ fclose(report_fp);
+ fclose(evdev_fp);
+
+ exit(0);
+}
int main(int argc, char* argv[]) {
- FILE* evdev_fp = fopen(KEYBOARD_EVDEV, "r");
- FILE* report_fp = NULL;
+ evdev_fp = fopen(KEYBOARD_EVDEV, "r");
+ report_fp = NULL;
char* report_path = NULL;
@@ -25,19 +43,15 @@ int main(int argc, char* argv[]) {
report_fp = fopen(report_path, "w");
+ signal(SIGHUP, handler);
+ signal(SIGQUIT, handler);
+ signal(SIGTERM, handler);
+
do {
fread(&pressed_key, sizeof(pressed_key), 1, evdev_fp);
- gettimeofday(&press_time, NULL);
-
if (pressed_key.value == 1) {
- perkey_pressed[pressed_key.code < PERKEY_LEN ? pressed_key.code : PERKEY_LEN];
- keys_pressed++;
-
- LOG(LOG_DEBUG, "%d:", keys_pressed, pressed_key.type, pressed_key.code, pressed_key.value);
- rewind(report_fp);
- fprintf(report_fp, "%d\n", keys_pressed);
- fflush(report_fp);
+ log_key(pressed_key.code);
}
} while (1);
diff --git a/src/report.c b/src/report.c
new file mode 100644
index 0000000..060e98a
--- /dev/null
+++ b/src/report.c
@@ -0,0 +1,48 @@
+// report generator
+
+#include <stdio.h>
+
+#include "common.h"
+
+extern keypresses_t keypresses;
+
+static double work_time;
+static double idle_time;
+
+#define REPORT(t, s, v...) do { \
+ fprintf(report_fp, "%s: " t "\n", s, v); \
+} while (0)
+
+void gen_report(FILE* report_fp) {
+ LOG(LOG_DEBUG, "total keypresses: %d\n", keypresses.length);
+
+ rewind(report_fp);
+
+ work_time = 0;
+ idle_time = 0;
+
+ if (keypresses.length > 2) {
+ double last_press = keypresses.keys[0].when;
+
+ for (int i = 1; i < keypresses.length; i++) {
+ keypress_t* press = &keypresses.keys[i];
+
+ if (press->when < last_press + IDLE_TIME) {
+ work_time += press->when - last_press;
+ } else {
+ idle_time += press->when - last_press - IDLE_TIME;
+ }
+
+ last_press = press->when;
+
+ LOG(LOG_INSANEDEBUG, "%d %d %d\n", keypresses.keys[i].when, keypresses.length);
+ }
+ }
+
+ REPORT("%d", "total keypresses", keypresses.length);
+ REPORT("%.1fs", "work time", work_time);
+ REPORT("%.1f k/s", "avg keys/sec", keypresses.length / work_time);
+ REPORT("%.1fs", "idle time", idle_time);
+
+ fflush(report_fp);
+}
diff --git a/src/report.h b/src/report.h
new file mode 100644
index 0000000..d776718
--- /dev/null
+++ b/src/report.h
@@ -0,0 +1,8 @@
+#ifndef REPORT_H
+#define REPORT_H
+
+#include <stdio.h>
+
+void gen_report(FILE* fp);
+
+#endif