]> git.scottworley.com Git - keystroke-timestamps/blob - keystroke-timestamps.c
Accept short options
[keystroke-timestamps] / keystroke-timestamps.c
1 #include <err.h>
2 #include <fcntl.h>
3 #include <glob.h>
4 #include <getopt.h>
5 #include <linux/input.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <sysexits.h>
9 #include <sys/select.h>
10 #include <unistd.h>
11
12 // This constant is defined in include/uapi/linux/input-event-codes.h
13 #ifndef EV_KEY
14 #define EV_KEY 0x01
15 #endif
16
17
18 int main (int argc, char **argv)
19 {
20 int print_usec = 0;
21 char* device = "/dev/input/by-path/*kbd*";
22 char* output = NULL;
23 struct option long_options[] = {
24 {"device", required_argument, 0, 'd' },
25 {"output", required_argument, 0, 'o' },
26 {"usec", no_argument, &print_usec, 1 },
27 {0, 0, 0, 0 },
28 };
29 while (1) {
30 int c = getopt_long(argc, argv, "d:o:", long_options, NULL);
31 if (c == -1) break;
32 if (c == 'd') {
33 device = optarg;
34 continue;
35 }
36 if (c == 'o') {
37 output = optarg;
38 continue;
39 }
40 if (c != 0) exit(EX_USAGE);
41 }
42
43 /* Open output file */
44 FILE *output_file;
45 if (output == NULL) {
46 output_file = stdout;
47 } else {
48 output_file = fopen(output, "a");
49 if (output_file == NULL) {
50 err(EX_CANTCREAT, "Could not open output file: %s", output);
51 }
52 }
53
54 /* Open device inputs */
55 fd_set all_inputs;
56 FD_ZERO(&all_inputs);
57 int maxfd = 0;
58 glob_t glob_result;
59 int glob_return = glob(device, GLOB_ERR | GLOB_NOSORT, NULL, &glob_result);
60 if (glob_return == GLOB_NOMATCH) {
61 errx(EX_NOINPUT, "Could not find keyboard event file(s): %s", device);
62 }
63 if (glob_return != 0) {
64 err(EX_NOINPUT, "Could not glob keyboard event file(s): %s", device);
65 }
66 for (unsigned i = 0; i < glob_result.gl_pathc; i++) {
67 int device_fd = open(glob_result.gl_pathv[i], O_RDONLY);
68 if (device_fd < 0) {
69 err(EX_NOINPUT, "Could not open keyboard event file: %s", glob_result.gl_pathv[i]);
70 }
71 if (device_fd > maxfd) {
72 maxfd = device_fd;
73 }
74 FD_SET(device_fd, &all_inputs);
75 }
76 globfree(&glob_result);
77
78 /* Report keystroke timestamps */
79 struct input_event i;
80 while (1) {
81 fd_set ready_inputs = all_inputs;
82 if (select(maxfd+1, &ready_inputs, NULL, NULL, NULL) < 1) {
83 err(EX_IOERR, "select");
84 }
85 for (int fd=0; fd <= maxfd; fd++) {
86 if (FD_ISSET(fd, &ready_inputs)) {
87 int read_return = read(fd, &i, sizeof(i));
88 if (read_return == -1) {
89 err(EX_IOERR, "read");
90 }
91 if (read_return != sizeof(i)) {
92 errx(EX_IOERR, "Unexpected EOF");
93 }
94 if (i.type == EV_KEY && i.value == 1) {
95 if (print_usec) {
96 fprintf(output_file, "%ld.%06ld\n", i.time.tv_sec, i.time.tv_usec);
97 } else {
98 fprintf(output_file, "%ld\n", i.time.tv_sec);
99 }
100 fflush(output_file);
101 }
102 }
103 }
104 }
105 return 0;
106 }