Use tab indentation.

This commit is contained in:
2026-04-11 22:36:14 +01:00
parent 6d4ffc24c1
commit f2fd81c9c7
2 changed files with 315 additions and 315 deletions

324
scan.c
View File

@@ -13,220 +13,220 @@
static int read_file_trim(const char *path, char *buf, size_t buf_size) static int read_file_trim(const char *path, char *buf, size_t buf_size)
{ {
FILE *f = fopen(path, "r"); FILE *f = fopen(path, "r");
if (!f) return -1; if (!f) return -1;
if (!fgets(buf, (int)buf_size, f)) { if (!fgets(buf, (int)buf_size, f)) {
fclose(f); fclose(f);
return -1; return -1;
} }
fclose(f); fclose(f);
// Trim trailing whitespace/newline // Trim trailing whitespace/newline
size_t len = strlen(buf); size_t len = strlen(buf);
while (len > 0 && (buf[len - 1] == '\n' || buf[len - 1] == '\r' || buf[len - 1] == ' ' || buf[len - 1] == '\t')) { while (len > 0 && (buf[len - 1] == '\n' || buf[len - 1] == '\r' || buf[len - 1] == ' ' || buf[len - 1] == '\t')) {
buf[--len] = '\0'; buf[--len] = '\0';
} }
return 0; return 0;
} }
// Find the sysfs name of the target USB device under /sys/bus/usb/devices // Find the sysfs name of the target USB device under /sys/bus/usb/devices
// (e.g. "1-2"), by matching idVendor/idProduct. // (e.g. "1-2"), by matching idVendor/idProduct.
static int find_usb_device_name(char *name_out, size_t name_out_size) static int find_usb_device_name(char *name_out, size_t name_out_size)
{ {
const char *base = "/sys/bus/usb/devices"; const char *base = "/sys/bus/usb/devices";
DIR *dir = opendir(base); DIR *dir = opendir(base);
if (!dir) { if (!dir) {
perror("opendir /sys/bus/usb/devices"); perror("opendir /sys/bus/usb/devices");
return -1; return -1;
} }
struct dirent *ent; struct dirent *ent;
int found = 0; int found = 0;
char path[512]; char path[512];
char vid[16]; char vid[16];
char pid[16]; char pid[16];
while ((ent = readdir(dir)) != NULL) { while ((ent = readdir(dir)) != NULL) {
if (ent->d_name[0] == '.') continue; if (ent->d_name[0] == '.') continue;
// Skip interface/function entries like "1-2:1.0" // Skip interface/function entries like "1-2:1.0"
if (strchr(ent->d_name, ':') != NULL) continue; if (strchr(ent->d_name, ':') != NULL) continue;
snprintf(path, sizeof(path), "%s/%s/idVendor", base, ent->d_name); snprintf(path, sizeof(path), "%s/%s/idVendor", base, ent->d_name);
if (read_file_trim(path, vid, sizeof(vid)) != 0) continue; if (read_file_trim(path, vid, sizeof(vid)) != 0) continue;
snprintf(path, sizeof(path), "%s/%s/idProduct", base, ent->d_name); snprintf(path, sizeof(path), "%s/%s/idProduct", base, ent->d_name);
if (read_file_trim(path, pid, sizeof(pid)) != 0) continue; if (read_file_trim(path, pid, sizeof(pid)) != 0) continue;
if (strcmp(vid, VENDOR_ID) == 0 && strcmp(pid, PRODUCT_ID) == 0) { if (strcmp(vid, VENDOR_ID) == 0 && strcmp(pid, PRODUCT_ID) == 0) {
strncpy(name_out, ent->d_name, name_out_size - 1); strncpy(name_out, ent->d_name, name_out_size - 1);
name_out[name_out_size - 1] = '\0'; name_out[name_out_size - 1] = '\0';
found = 1; found = 1;
break; break;
} }
} }
closedir(dir); closedir(dir);
if (!found) { if (!found) {
fprintf(stderr, "USB device %s:%s not found on this system.\n", VENDOR_ID, PRODUCT_ID); fprintf(stderr, "USB device %s:%s not found on this system.\n", VENDOR_ID, PRODUCT_ID);
return -1; return -1;
} }
return 0; return 0;
} }
static int write_sysfs(const char *path, const char *value) static int write_sysfs(const char *path, const char *value)
{ {
FILE *f = fopen(path, "w"); FILE *f = fopen(path, "w");
if (!f) { if (!f) {
fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno)); fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
return -1; return -1;
} }
if (fprintf(f, "%s", value) < 0) { if (fprintf(f, "%s", value) < 0) {
fprintf(stderr, "Failed to write to %s: %s\n", path, strerror(errno)); fprintf(stderr, "Failed to write to %s: %s\n", path, strerror(errno));
fclose(f); fclose(f);
return -1; return -1;
} }
fclose(f); fclose(f);
return 0; return 0;
} }
// Disable the reader by unbinding it from the generic USB driver. // Disable the reader by unbinding it from the generic USB driver.
static int disable_reader(const char *dev_name) static int disable_reader(const char *dev_name)
{ {
char buf[64]; char buf[64];
snprintf(buf, sizeof(buf), "%s\n", dev_name); snprintf(buf, sizeof(buf), "%s\n", dev_name);
printf("Disabling reader %s (USB %s:%s)\n", dev_name, VENDOR_ID, PRODUCT_ID); printf("Disabling reader %s (USB %s:%s)\n", dev_name, VENDOR_ID, PRODUCT_ID);
return write_sysfs("/sys/bus/usb/drivers/usb/unbind", buf); return write_sysfs("/sys/bus/usb/drivers/usb/unbind", buf);
} }
// Enable the reader by binding it back to the generic USB driver. // Enable the reader by binding it back to the generic USB driver.
static int enable_reader(const char *dev_name) static int enable_reader(const char *dev_name)
{ {
char buf[64]; char buf[64];
snprintf(buf, sizeof(buf), "%s\n", dev_name); snprintf(buf, sizeof(buf), "%s\n", dev_name);
printf("Enabling reader %s (USB %s:%s)\n", dev_name, VENDOR_ID, PRODUCT_ID); printf("Enabling reader %s (USB %s:%s)\n", dev_name, VENDOR_ID, PRODUCT_ID);
return write_sysfs("/sys/bus/usb/drivers/usb/bind", buf); return write_sysfs("/sys/bus/usb/drivers/usb/bind", buf);
} }
// Trigger a one-shot card scan via PC/SC. Assumes the reader is already // Trigger a one-shot card scan via PC/SC. Assumes the reader is already
// bound/enabled (use the "on" subcommand first). // bound/enabled (use the "on" subcommand first).
static int trigger_scan(void) static int trigger_scan(void)
{ {
SCARDCONTEXT ctx; SCARDCONTEXT ctx;
LONG rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &ctx); LONG rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &ctx);
if (rv != SCARD_S_SUCCESS) { if (rv != SCARD_S_SUCCESS) {
fprintf(stderr, "SCardEstablishContext failed: %s\n", pcsc_stringify_error(rv)); fprintf(stderr, "SCardEstablishContext failed: %s\n", pcsc_stringify_error(rv));
return -1; return -1;
} }
char readers[2048]; char readers[2048];
DWORD readersLen = sizeof(readers); DWORD readersLen = sizeof(readers);
rv = SCardListReaders(ctx, NULL, readers, &readersLen); rv = SCardListReaders(ctx, NULL, readers, &readersLen);
if (rv != SCARD_S_SUCCESS) { if (rv != SCARD_S_SUCCESS) {
fprintf(stderr, "SCardListReaders failed: %s\n", pcsc_stringify_error(rv)); fprintf(stderr, "SCardListReaders failed: %s\n", pcsc_stringify_error(rv));
SCardReleaseContext(ctx); SCardReleaseContext(ctx);
return -1; return -1;
} }
if (readersLen <= 1) { if (readersLen <= 1) {
fprintf(stderr, "No smartcard readers found via PC/SC.\n"); fprintf(stderr, "No smartcard readers found via PC/SC.\n");
SCardReleaseContext(ctx); SCardReleaseContext(ctx);
return -1; return -1;
} }
// readers is a multi-string: sequence of null-terminated strings // readers is a multi-string: sequence of null-terminated strings
// terminated by an extra null. Prefer a reader whose name contains // terminated by an extra null. Prefer a reader whose name contains
// "IC Reader", otherwise use the first. // "IC Reader", otherwise use the first.
const char *chosen = NULL; const char *chosen = NULL;
const char *p = readers; const char *p = readers;
while (*p != '\0') { while (*p != '\0') {
if (!chosen) { if (!chosen) {
chosen = p; chosen = p;
} }
if (strstr(p, "IC Reader") != NULL) { if (strstr(p, "IC Reader") != NULL) {
chosen = p; chosen = p;
break; break;
} }
p += strlen(p) + 1; p += strlen(p) + 1;
} }
if (!chosen) { if (!chosen) {
fprintf(stderr, "Unable to choose a reader from PC/SC list.\n"); fprintf(stderr, "Unable to choose a reader from PC/SC list.\n");
SCardReleaseContext(ctx); SCardReleaseContext(ctx);
return -1; return -1;
} }
printf("Using reader: %s\n", chosen); printf("Using reader: %s\n", chosen);
SCARDHANDLE card; SCARDHANDLE card;
DWORD activeProt; DWORD activeProt;
rv = SCardConnect(ctx, chosen, SCARD_SHARE_SHARED, rv = SCardConnect(ctx, chosen, SCARD_SHARE_SHARED,
SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1,
&card, &activeProt); &card, &activeProt);
if (rv != SCARD_S_SUCCESS) { if (rv != SCARD_S_SUCCESS) {
fprintf(stderr, "SCardConnect failed: %s\n", pcsc_stringify_error(rv)); fprintf(stderr, "SCardConnect failed: %s\n", pcsc_stringify_error(rv));
SCardReleaseContext(ctx); SCardReleaseContext(ctx);
return -1; return -1;
} }
// At this point the reader has powered/reset the card and read the ATR. // At this point the reader has powered/reset the card and read the ATR.
BYTE atr[64]; BYTE atr[64];
DWORD atrLen = sizeof(atr); DWORD atrLen = sizeof(atr);
DWORD state, prot; DWORD state, prot;
rv = SCardStatus(card, NULL, NULL, &state, &prot, atr, &atrLen); rv = SCardStatus(card, NULL, NULL, &state, &prot, atr, &atrLen);
if (rv == SCARD_S_SUCCESS) { if (rv == SCARD_S_SUCCESS) {
printf("ATR (%u bytes): ", atrLen); printf("ATR (%u bytes): ", atrLen);
for (DWORD i = 0; i < atrLen; i++) { for (DWORD i = 0; i < atrLen; i++) {
printf("%02X ", atr[i]); printf("%02X ", atr[i]);
} }
printf("\n"); printf("\n");
} else { } else {
fprintf(stderr, "SCardStatus failed: %s\n", pcsc_stringify_error(rv)); fprintf(stderr, "SCardStatus failed: %s\n", pcsc_stringify_error(rv));
} }
SCardDisconnect(card, SCARD_LEAVE_CARD); SCardDisconnect(card, SCARD_LEAVE_CARD);
SCardReleaseContext(ctx); SCardReleaseContext(ctx);
return 0; return 0;
} }
static void usage(const char *prog) static void usage(const char *prog)
{ {
fprintf(stderr, "Usage: %s on|off|scan\n", prog); fprintf(stderr, "Usage: %s on|off|scan\n", prog);
fprintf(stderr, " off : unbind the IC Reader so the system cannot use it.\n"); fprintf(stderr, " off : unbind the IC Reader so the system cannot use it.\n");
fprintf(stderr, " on : bind the IC Reader back so it works again.\n"); fprintf(stderr, " on : bind the IC Reader back so it works again.\n");
fprintf(stderr, " scan: perform a one-shot PC/SC card scan using the reader.\n"); fprintf(stderr, " scan: perform a one-shot PC/SC card scan using the reader.\n");
fprintf(stderr, "Note: on/off require root (write access to /sys/bus/usb/drivers/usb).\n"); fprintf(stderr, "Note: on/off require root (write access to /sys/bus/usb/drivers/usb).\n");
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
if (argc != 2) { if (argc != 2) {
usage(argv[0]); usage(argv[0]);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
char dev_name[64]; char dev_name[64];
if (find_usb_device_name(dev_name, sizeof(dev_name)) != 0) { if (find_usb_device_name(dev_name, sizeof(dev_name)) != 0) {
return EXIT_FAILURE; return EXIT_FAILURE;
} }
int rc; int rc;
if (strcmp(argv[1], "off") == 0) { if (strcmp(argv[1], "off") == 0) {
rc = disable_reader(dev_name); rc = disable_reader(dev_name);
} else if (strcmp(argv[1], "on") == 0) { } else if (strcmp(argv[1], "on") == 0) {
rc = enable_reader(dev_name); rc = enable_reader(dev_name);
} else if (strcmp(argv[1], "scan") == 0) { } else if (strcmp(argv[1], "scan") == 0) {
rc = trigger_scan(); rc = trigger_scan();
} else { } else {
usage(argv[0]); usage(argv[0]);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (rc != 0) { if (rc != 0) {
fprintf(stderr, "Operation failed. Are you running as root?\n"); fprintf(stderr, "Operation failed. Are you running as root?\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

306
scan2.c
View File

@@ -19,176 +19,176 @@ static unsigned long long last_time_standing = 0;
// Map a subset of key codes (digits and Enter) to characters. // Map a subset of key codes (digits and Enter) to characters.
static char keycode_to_char(unsigned short code) static char keycode_to_char(unsigned short code)
{ {
switch (code) { switch (code) {
case KEY_0: return '0'; case KEY_0: return '0';
case KEY_1: return '1'; case KEY_1: return '1';
case KEY_2: return '2'; case KEY_2: return '2';
case KEY_3: return '3'; case KEY_3: return '3';
case KEY_4: return '4'; case KEY_4: return '4';
case KEY_5: return '5'; case KEY_5: return '5';
case KEY_6: return '6'; case KEY_6: return '6';
case KEY_7: return '7'; case KEY_7: return '7';
case KEY_8: return '8'; case KEY_8: return '8';
case KEY_9: return '9'; case KEY_9: return '9';
default: return '\0'; default: return '\0';
} }
} }
// Thread that once per second prints how long it has been since // Thread that once per second prints how long it has been since
// last_time_standing was updated. // last_time_standing was updated.
static void *time_watcher_thread(void *arg) static void *time_watcher_thread(void *arg)
{ {
(void)arg; (void)arg;
for (;;) { for (;;) {
sleep(1); sleep(1);
unsigned long long now = (unsigned long long)time(NULL); unsigned long long now = (unsigned long long)time(NULL);
if (last_time_standing != 0) { if (last_time_standing != 0) {
unsigned long long delta = now - last_time_standing; unsigned long long delta = now - last_time_standing;
printf("Seconds since last_time_standing: %llu (interval=%llus)\n", printf("Seconds since last_time_standing: %llu (interval=%llus)\n",
delta, interval_seconds); delta, interval_seconds);
fflush(stdout); fflush(stdout);
// If we've exceeded the configured interval, lock the screen // If we've exceeded the configured interval, lock the screen
if (delta >= interval_seconds) { if (delta >= interval_seconds) {
// Use xinput to disable all keyboard-like devices until user stands again. // Use xinput to disable all keyboard-like devices until user stands again.
// This pipeline lists input devices, filters keyboards (excluding XTEST), // This pipeline lists input devices, filters keyboards (excluding XTEST),
// extracts their IDs, and disables each one. // extracts their IDs, and disables each one.
system("xinput --list --short | " system("xinput --list --short | "
"grep -i 'keyboard' | grep -v 'XTEST' | " "grep -i 'keyboard' | grep -v 'XTEST' | "
"sed -E 's/.*id=([0-9]+).*/\\1/' | " "sed -E 's/.*id=([0-9]+).*/\\1/' | "
"xargs -r -n1 xinput disable"); "xargs -r -n1 xinput disable");
system("i3lock -n -i /usr/local/share/lockscreens/standing_gopher.png"); system("i3lock -n -i /usr/local/share/lockscreens/standing_gopher.png");
} }
} }
} }
return NULL; return NULL;
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
// Replace with the specific event node for your keyboard // Replace with the specific event node for your keyboard
// Use 'lsusb' and 'cat /proc/bus/input/devices' to find the right one // Use 'lsusb' and 'cat /proc/bus/input/devices' to find the right one
const char *dev = "/dev/input/by-id/usb-IC_Reader_IC_Reader_08FF20171101-event-kbd"; const char *dev = "/dev/input/by-id/usb-IC_Reader_IC_Reader_08FF20171101-event-kbd";
struct input_event ev; struct input_event ev;
int fd; int fd;
// Optional: -i <interval>[s|m] to override interval_seconds // Optional: -i <interval>[s|m] to override interval_seconds
int opt; int opt;
while ((opt = getopt(argc, argv, "i:")) != -1) { while ((opt = getopt(argc, argv, "i:")) != -1) {
switch (opt) { switch (opt) {
case 'i': { case 'i': {
char *end = NULL; char *end = NULL;
unsigned long long v = strtoull(optarg, &end, 10); unsigned long long v = strtoull(optarg, &end, 10);
if (!optarg[0] || end == optarg || v == 0) { if (!optarg[0] || end == optarg || v == 0) {
fprintf(stderr, "Invalid interval '%s' for -i (must start with positive integer)\n", optarg); fprintf(stderr, "Invalid interval '%s' for -i (must start with positive integer)\n", optarg);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
char unit = 'm'; // default unit: minutes char unit = 'm'; // default unit: minutes
if (*end != '\0') { if (*end != '\0') {
// Allow a single unit character 's' or 'm' // Allow a single unit character 's' or 'm'
if (end[1] != '\0') { if (end[1] != '\0') {
fprintf(stderr, "Invalid interval suffix in '%s' (use optional 's' or 'm')\n", optarg); fprintf(stderr, "Invalid interval suffix in '%s' (use optional 's' or 'm')\n", optarg);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
unit = (char)tolower((unsigned char)*end); unit = (char)tolower((unsigned char)*end);
if (unit != 's' && unit != 'm') { if (unit != 's' && unit != 'm') {
fprintf(stderr, "Unknown interval unit '%c' in '%s' (use 's' or 'm')\n", *end, optarg); fprintf(stderr, "Unknown interval unit '%c' in '%s' (use 's' or 'm')\n", *end, optarg);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
} }
if (unit == 's') { if (unit == 's') {
interval_seconds = v; interval_seconds = v;
} else { // 'm' } else { // 'm'
interval_seconds = v * 60ULL; interval_seconds = v * 60ULL;
} }
break; break;
} }
default: default:
fprintf(stderr, "Usage: %s [-i interval{s|m}]\n", argv[0]); fprintf(stderr, "Usage: %s [-i interval{s|m}]\n", argv[0]);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
} }
fd = open(dev, O_RDONLY); fd = open(dev, O_RDONLY);
if (fd == -1) { if (fd == -1) {
perror("Cannot open device"); perror("Cannot open device");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
// Grab the device: This blocks all other apps from seeing these keystrokes // Grab the device: This blocks all other apps from seeing these keystrokes
if (ioctl(fd, EVIOCGRAB, 1) == -1) { if (ioctl(fd, EVIOCGRAB, 1) == -1) {
perror("Could not grab device"); perror("Could not grab device");
close(fd); close(fd);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
printf("Input blocked from %s. Press Ctrl+C in this terminal to stop.\n", dev); printf("Input blocked from %s. Press Ctrl+C in this terminal to stop.\n", dev);
// Buffer to accumulate the characters the reader "types" // Buffer to accumulate the characters the reader "types"
char buf_str[128]; char buf_str[128];
size_t buf_len = 0; size_t buf_len = 0;
// Initialize last_time_standing and start the watcher thread // Initialize last_time_standing and start the watcher thread
last_time_standing = (unsigned long long)time(NULL); last_time_standing = (unsigned long long)time(NULL);
pthread_t watcher; pthread_t watcher;
if (pthread_create(&watcher, NULL, time_watcher_thread, NULL) != 0) { if (pthread_create(&watcher, NULL, time_watcher_thread, NULL) != 0) {
perror("Failed to create watcher thread"); perror("Failed to create watcher thread");
ioctl(fd, EVIOCGRAB, 0); ioctl(fd, EVIOCGRAB, 0);
close(fd); close(fd);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
pthread_detach(watcher); pthread_detach(watcher);
// Continuous loop to capture events // Continuous loop to capture events
while (1) { while (1) {
ssize_t n = read(fd, &ev, sizeof(ev)); ssize_t n = read(fd, &ev, sizeof(ev));
if (n == (ssize_t)-1) { if (n == (ssize_t)-1) {
perror("Read error"); perror("Read error");
break; break;
} else if (n != sizeof(ev)) { } else if (n != sizeof(ev)) {
continue; continue;
} }
// Process only key events (type 1) // Process only key events (type 1)
if (ev.type == EV_KEY) { if (ev.type == EV_KEY) {
if (ev.value == 1) { // key press if (ev.value == 1) { // key press
if (ev.code == KEY_ENTER || ev.code == KEY_KPENTER) { if (ev.code == KEY_ENTER || ev.code == KEY_KPENTER) {
// End of the "typed" sequence: print the accumulated string // End of the "typed" sequence: print the accumulated string
if (buf_len > 0) { if (buf_len > 0) {
buf_str[buf_len] = '\0'; buf_str[buf_len] = '\0';
long long val = strtoll(buf_str, NULL, 10); long long val = strtoll(buf_str, NULL, 10);
// Get the SHA-256 hash of the value // Get the SHA-256 hash of the value
unsigned char hash[SHA256_DIGEST_LENGTH]; unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256((unsigned char*)buf_str, buf_len, hash); SHA256((unsigned char*)buf_str, buf_len, hash);
printf("SHA-256: "); printf("SHA-256: ");
unsigned long long hash_val = 0; unsigned long long hash_val = 0;
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
hash_val = (hash_val << 8) | hash[i]; hash_val = (hash_val << 8) | hash[i];
} }
printf(" (as number: %llu)", hash_val); printf(" (as number: %llu)", hash_val);
printf("\n"); printf("\n");
printf("Typed: %s (as number: %lld)\n", buf_str, val); printf("Typed: %s (as number: %lld)\n", buf_str, val);
buf_len = 0; buf_len = 0;
if (hash_val == 4798061567229363866L) { if (hash_val == 4798061567229363866L) {
last_time_standing = (unsigned long long)time(NULL); last_time_standing = (unsigned long long)time(NULL);
printf("Desk reminder timer reset at %llu seconds since epoch.\n", last_time_standing); printf("Desk reminder timer reset at %llu seconds since epoch.\n", last_time_standing);
system("pkill i3lock"); system("pkill i3lock");
system("xinput --list --short | " system("xinput --list --short | "
"grep -i 'keyboard' | grep -v 'XTEST' | " "grep -i 'keyboard' | grep -v 'XTEST' | "
"sed -E 's/.*id=([0-9]+).*/\\1/' | " "sed -E 's/.*id=([0-9]+).*/\\1/' | "
"xargs -r -n1 xinput enable"); "xargs -r -n1 xinput enable");
} }
} }
} else { } else {
char c = keycode_to_char(ev.code); char c = keycode_to_char(ev.code);
if (c != '\0' && buf_len + 1 < sizeof(buf_str)) if (c != '\0' && buf_len + 1 < sizeof(buf_str))
buf_str[buf_len++] = c; buf_str[buf_len++] = c;
} }
} }
} }
} }
// Release the grab before exiting // Release the grab before exiting
ioctl(fd, EVIOCGRAB, 0); ioctl(fd, EVIOCGRAB, 0);
close(fd); close(fd);
return 0; return 0;
} }