Use tab indentation.
This commit is contained in:
322
scan.c
322
scan.c
@@ -13,220 +13,220 @@
|
||||
|
||||
static int read_file_trim(const char *path, char *buf, size_t buf_size)
|
||||
{
|
||||
FILE *f = fopen(path, "r");
|
||||
if (!f) return -1;
|
||||
FILE *f = fopen(path, "r");
|
||||
if (!f) return -1;
|
||||
|
||||
if (!fgets(buf, (int)buf_size, f)) {
|
||||
fclose(f);
|
||||
return -1;
|
||||
}
|
||||
fclose(f);
|
||||
if (!fgets(buf, (int)buf_size, f)) {
|
||||
fclose(f);
|
||||
return -1;
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
// Trim trailing whitespace/newline
|
||||
size_t len = strlen(buf);
|
||||
while (len > 0 && (buf[len - 1] == '\n' || buf[len - 1] == '\r' || buf[len - 1] == ' ' || buf[len - 1] == '\t')) {
|
||||
buf[--len] = '\0';
|
||||
}
|
||||
return 0;
|
||||
// Trim trailing whitespace/newline
|
||||
size_t len = strlen(buf);
|
||||
while (len > 0 && (buf[len - 1] == '\n' || buf[len - 1] == '\r' || buf[len - 1] == ' ' || buf[len - 1] == '\t')) {
|
||||
buf[--len] = '\0';
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Find the sysfs name of the target USB device under /sys/bus/usb/devices
|
||||
// (e.g. "1-2"), by matching idVendor/idProduct.
|
||||
static int find_usb_device_name(char *name_out, size_t name_out_size)
|
||||
{
|
||||
const char *base = "/sys/bus/usb/devices";
|
||||
DIR *dir = opendir(base);
|
||||
if (!dir) {
|
||||
perror("opendir /sys/bus/usb/devices");
|
||||
return -1;
|
||||
}
|
||||
const char *base = "/sys/bus/usb/devices";
|
||||
DIR *dir = opendir(base);
|
||||
if (!dir) {
|
||||
perror("opendir /sys/bus/usb/devices");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct dirent *ent;
|
||||
int found = 0;
|
||||
char path[512];
|
||||
char vid[16];
|
||||
char pid[16];
|
||||
struct dirent *ent;
|
||||
int found = 0;
|
||||
char path[512];
|
||||
char vid[16];
|
||||
char pid[16];
|
||||
|
||||
while ((ent = readdir(dir)) != NULL) {
|
||||
if (ent->d_name[0] == '.') continue;
|
||||
while ((ent = readdir(dir)) != NULL) {
|
||||
if (ent->d_name[0] == '.') continue;
|
||||
|
||||
// Skip interface/function entries like "1-2:1.0"
|
||||
if (strchr(ent->d_name, ':') != NULL) continue;
|
||||
// Skip interface/function entries like "1-2:1.0"
|
||||
if (strchr(ent->d_name, ':') != NULL) continue;
|
||||
|
||||
snprintf(path, sizeof(path), "%s/%s/idVendor", base, ent->d_name);
|
||||
if (read_file_trim(path, vid, sizeof(vid)) != 0) continue;
|
||||
snprintf(path, sizeof(path), "%s/%s/idVendor", base, ent->d_name);
|
||||
if (read_file_trim(path, vid, sizeof(vid)) != 0) continue;
|
||||
|
||||
snprintf(path, sizeof(path), "%s/%s/idProduct", base, ent->d_name);
|
||||
if (read_file_trim(path, pid, sizeof(pid)) != 0) continue;
|
||||
snprintf(path, sizeof(path), "%s/%s/idProduct", base, ent->d_name);
|
||||
if (read_file_trim(path, pid, sizeof(pid)) != 0) continue;
|
||||
|
||||
if (strcmp(vid, VENDOR_ID) == 0 && strcmp(pid, PRODUCT_ID) == 0) {
|
||||
strncpy(name_out, ent->d_name, name_out_size - 1);
|
||||
name_out[name_out_size - 1] = '\0';
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (strcmp(vid, VENDOR_ID) == 0 && strcmp(pid, PRODUCT_ID) == 0) {
|
||||
strncpy(name_out, ent->d_name, name_out_size - 1);
|
||||
name_out[name_out_size - 1] = '\0';
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
if (!found) {
|
||||
fprintf(stderr, "USB device %s:%s not found on this system.\n", VENDOR_ID, PRODUCT_ID);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
closedir(dir);
|
||||
if (!found) {
|
||||
fprintf(stderr, "USB device %s:%s not found on this system.\n", VENDOR_ID, PRODUCT_ID);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int write_sysfs(const char *path, const char *value)
|
||||
{
|
||||
FILE *f = fopen(path, "w");
|
||||
if (!f) {
|
||||
fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (fprintf(f, "%s", value) < 0) {
|
||||
fprintf(stderr, "Failed to write to %s: %s\n", path, strerror(errno));
|
||||
fclose(f);
|
||||
return -1;
|
||||
}
|
||||
fclose(f);
|
||||
return 0;
|
||||
FILE *f = fopen(path, "w");
|
||||
if (!f) {
|
||||
fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (fprintf(f, "%s", value) < 0) {
|
||||
fprintf(stderr, "Failed to write to %s: %s\n", path, strerror(errno));
|
||||
fclose(f);
|
||||
return -1;
|
||||
}
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Disable the reader by unbinding it from the generic USB driver.
|
||||
static int disable_reader(const char *dev_name)
|
||||
{
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof(buf), "%s\n", dev_name);
|
||||
printf("Disabling reader %s (USB %s:%s)\n", dev_name, VENDOR_ID, PRODUCT_ID);
|
||||
return write_sysfs("/sys/bus/usb/drivers/usb/unbind", buf);
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof(buf), "%s\n", dev_name);
|
||||
printf("Disabling reader %s (USB %s:%s)\n", dev_name, VENDOR_ID, PRODUCT_ID);
|
||||
return write_sysfs("/sys/bus/usb/drivers/usb/unbind", buf);
|
||||
}
|
||||
|
||||
// Enable the reader by binding it back to the generic USB driver.
|
||||
static int enable_reader(const char *dev_name)
|
||||
{
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof(buf), "%s\n", dev_name);
|
||||
printf("Enabling reader %s (USB %s:%s)\n", dev_name, VENDOR_ID, PRODUCT_ID);
|
||||
return write_sysfs("/sys/bus/usb/drivers/usb/bind", buf);
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof(buf), "%s\n", dev_name);
|
||||
printf("Enabling reader %s (USB %s:%s)\n", dev_name, VENDOR_ID, PRODUCT_ID);
|
||||
return write_sysfs("/sys/bus/usb/drivers/usb/bind", buf);
|
||||
}
|
||||
|
||||
// Trigger a one-shot card scan via PC/SC. Assumes the reader is already
|
||||
// bound/enabled (use the "on" subcommand first).
|
||||
static int trigger_scan(void)
|
||||
{
|
||||
SCARDCONTEXT ctx;
|
||||
LONG rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &ctx);
|
||||
if (rv != SCARD_S_SUCCESS) {
|
||||
fprintf(stderr, "SCardEstablishContext failed: %s\n", pcsc_stringify_error(rv));
|
||||
return -1;
|
||||
}
|
||||
SCARDCONTEXT ctx;
|
||||
LONG rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &ctx);
|
||||
if (rv != SCARD_S_SUCCESS) {
|
||||
fprintf(stderr, "SCardEstablishContext failed: %s\n", pcsc_stringify_error(rv));
|
||||
return -1;
|
||||
}
|
||||
|
||||
char readers[2048];
|
||||
DWORD readersLen = sizeof(readers);
|
||||
rv = SCardListReaders(ctx, NULL, readers, &readersLen);
|
||||
if (rv != SCARD_S_SUCCESS) {
|
||||
fprintf(stderr, "SCardListReaders failed: %s\n", pcsc_stringify_error(rv));
|
||||
SCardReleaseContext(ctx);
|
||||
return -1;
|
||||
}
|
||||
char readers[2048];
|
||||
DWORD readersLen = sizeof(readers);
|
||||
rv = SCardListReaders(ctx, NULL, readers, &readersLen);
|
||||
if (rv != SCARD_S_SUCCESS) {
|
||||
fprintf(stderr, "SCardListReaders failed: %s\n", pcsc_stringify_error(rv));
|
||||
SCardReleaseContext(ctx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (readersLen <= 1) {
|
||||
fprintf(stderr, "No smartcard readers found via PC/SC.\n");
|
||||
SCardReleaseContext(ctx);
|
||||
return -1;
|
||||
}
|
||||
if (readersLen <= 1) {
|
||||
fprintf(stderr, "No smartcard readers found via PC/SC.\n");
|
||||
SCardReleaseContext(ctx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// readers is a multi-string: sequence of null-terminated strings
|
||||
// terminated by an extra null. Prefer a reader whose name contains
|
||||
// "IC Reader", otherwise use the first.
|
||||
const char *chosen = NULL;
|
||||
const char *p = readers;
|
||||
while (*p != '\0') {
|
||||
if (!chosen) {
|
||||
chosen = p;
|
||||
}
|
||||
if (strstr(p, "IC Reader") != NULL) {
|
||||
chosen = p;
|
||||
break;
|
||||
}
|
||||
p += strlen(p) + 1;
|
||||
}
|
||||
// readers is a multi-string: sequence of null-terminated strings
|
||||
// terminated by an extra null. Prefer a reader whose name contains
|
||||
// "IC Reader", otherwise use the first.
|
||||
const char *chosen = NULL;
|
||||
const char *p = readers;
|
||||
while (*p != '\0') {
|
||||
if (!chosen) {
|
||||
chosen = p;
|
||||
}
|
||||
if (strstr(p, "IC Reader") != NULL) {
|
||||
chosen = p;
|
||||
break;
|
||||
}
|
||||
p += strlen(p) + 1;
|
||||
}
|
||||
|
||||
if (!chosen) {
|
||||
fprintf(stderr, "Unable to choose a reader from PC/SC list.\n");
|
||||
SCardReleaseContext(ctx);
|
||||
return -1;
|
||||
}
|
||||
if (!chosen) {
|
||||
fprintf(stderr, "Unable to choose a reader from PC/SC list.\n");
|
||||
SCardReleaseContext(ctx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("Using reader: %s\n", chosen);
|
||||
printf("Using reader: %s\n", chosen);
|
||||
|
||||
SCARDHANDLE card;
|
||||
DWORD activeProt;
|
||||
rv = SCardConnect(ctx, chosen, SCARD_SHARE_SHARED,
|
||||
SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1,
|
||||
&card, &activeProt);
|
||||
if (rv != SCARD_S_SUCCESS) {
|
||||
fprintf(stderr, "SCardConnect failed: %s\n", pcsc_stringify_error(rv));
|
||||
SCardReleaseContext(ctx);
|
||||
return -1;
|
||||
}
|
||||
SCARDHANDLE card;
|
||||
DWORD activeProt;
|
||||
rv = SCardConnect(ctx, chosen, SCARD_SHARE_SHARED,
|
||||
SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1,
|
||||
&card, &activeProt);
|
||||
if (rv != SCARD_S_SUCCESS) {
|
||||
fprintf(stderr, "SCardConnect failed: %s\n", pcsc_stringify_error(rv));
|
||||
SCardReleaseContext(ctx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// At this point the reader has powered/reset the card and read the ATR.
|
||||
BYTE atr[64];
|
||||
DWORD atrLen = sizeof(atr);
|
||||
DWORD state, prot;
|
||||
rv = SCardStatus(card, NULL, NULL, &state, &prot, atr, &atrLen);
|
||||
if (rv == SCARD_S_SUCCESS) {
|
||||
printf("ATR (%u bytes): ", atrLen);
|
||||
for (DWORD i = 0; i < atrLen; i++) {
|
||||
printf("%02X ", atr[i]);
|
||||
}
|
||||
printf("\n");
|
||||
} else {
|
||||
fprintf(stderr, "SCardStatus failed: %s\n", pcsc_stringify_error(rv));
|
||||
}
|
||||
// At this point the reader has powered/reset the card and read the ATR.
|
||||
BYTE atr[64];
|
||||
DWORD atrLen = sizeof(atr);
|
||||
DWORD state, prot;
|
||||
rv = SCardStatus(card, NULL, NULL, &state, &prot, atr, &atrLen);
|
||||
if (rv == SCARD_S_SUCCESS) {
|
||||
printf("ATR (%u bytes): ", atrLen);
|
||||
for (DWORD i = 0; i < atrLen; i++) {
|
||||
printf("%02X ", atr[i]);
|
||||
}
|
||||
printf("\n");
|
||||
} else {
|
||||
fprintf(stderr, "SCardStatus failed: %s\n", pcsc_stringify_error(rv));
|
||||
}
|
||||
|
||||
SCardDisconnect(card, SCARD_LEAVE_CARD);
|
||||
SCardReleaseContext(ctx);
|
||||
return 0;
|
||||
SCardDisconnect(card, SCARD_LEAVE_CARD);
|
||||
SCardReleaseContext(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void usage(const char *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, " 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, "Note: on/off require root (write access to /sys/bus/usb/drivers/usb).\n");
|
||||
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, " 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, "Note: on/off require root (write access to /sys/bus/usb/drivers/usb).\n");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc != 2) {
|
||||
usage(argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (argc != 2) {
|
||||
usage(argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
char dev_name[64];
|
||||
if (find_usb_device_name(dev_name, sizeof(dev_name)) != 0) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
char dev_name[64];
|
||||
if (find_usb_device_name(dev_name, sizeof(dev_name)) != 0) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int rc;
|
||||
if (strcmp(argv[1], "off") == 0) {
|
||||
rc = disable_reader(dev_name);
|
||||
} else if (strcmp(argv[1], "on") == 0) {
|
||||
rc = enable_reader(dev_name);
|
||||
} else if (strcmp(argv[1], "scan") == 0) {
|
||||
rc = trigger_scan();
|
||||
} else {
|
||||
usage(argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
int rc;
|
||||
if (strcmp(argv[1], "off") == 0) {
|
||||
rc = disable_reader(dev_name);
|
||||
} else if (strcmp(argv[1], "on") == 0) {
|
||||
rc = enable_reader(dev_name);
|
||||
} else if (strcmp(argv[1], "scan") == 0) {
|
||||
rc = trigger_scan();
|
||||
} else {
|
||||
usage(argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (rc != 0) {
|
||||
fprintf(stderr, "Operation failed. Are you running as root?\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (rc != 0) {
|
||||
fprintf(stderr, "Operation failed. Are you running as root?\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
306
scan2.c
306
scan2.c
@@ -19,176 +19,176 @@ static unsigned long long last_time_standing = 0;
|
||||
// Map a subset of key codes (digits and Enter) to characters.
|
||||
static char keycode_to_char(unsigned short code)
|
||||
{
|
||||
switch (code) {
|
||||
case KEY_0: return '0';
|
||||
case KEY_1: return '1';
|
||||
case KEY_2: return '2';
|
||||
case KEY_3: return '3';
|
||||
case KEY_4: return '4';
|
||||
case KEY_5: return '5';
|
||||
case KEY_6: return '6';
|
||||
case KEY_7: return '7';
|
||||
case KEY_8: return '8';
|
||||
case KEY_9: return '9';
|
||||
default: return '\0';
|
||||
}
|
||||
switch (code) {
|
||||
case KEY_0: return '0';
|
||||
case KEY_1: return '1';
|
||||
case KEY_2: return '2';
|
||||
case KEY_3: return '3';
|
||||
case KEY_4: return '4';
|
||||
case KEY_5: return '5';
|
||||
case KEY_6: return '6';
|
||||
case KEY_7: return '7';
|
||||
case KEY_8: return '8';
|
||||
case KEY_9: return '9';
|
||||
default: return '\0';
|
||||
}
|
||||
}
|
||||
|
||||
// Thread that once per second prints how long it has been since
|
||||
// last_time_standing was updated.
|
||||
static void *time_watcher_thread(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
for (;;) {
|
||||
sleep(1);
|
||||
unsigned long long now = (unsigned long long)time(NULL);
|
||||
if (last_time_standing != 0) {
|
||||
unsigned long long delta = now - last_time_standing;
|
||||
printf("Seconds since last_time_standing: %llu (interval=%llus)\n",
|
||||
delta, interval_seconds);
|
||||
fflush(stdout);
|
||||
// If we've exceeded the configured interval, lock the screen
|
||||
if (delta >= interval_seconds) {
|
||||
// Use xinput to disable all keyboard-like devices until user stands again.
|
||||
// This pipeline lists input devices, filters keyboards (excluding XTEST),
|
||||
// extracts their IDs, and disables each one.
|
||||
system("xinput --list --short | "
|
||||
"grep -i 'keyboard' | grep -v 'XTEST' | "
|
||||
"sed -E 's/.*id=([0-9]+).*/\\1/' | "
|
||||
"xargs -r -n1 xinput disable");
|
||||
(void)arg;
|
||||
for (;;) {
|
||||
sleep(1);
|
||||
unsigned long long now = (unsigned long long)time(NULL);
|
||||
if (last_time_standing != 0) {
|
||||
unsigned long long delta = now - last_time_standing;
|
||||
printf("Seconds since last_time_standing: %llu (interval=%llus)\n",
|
||||
delta, interval_seconds);
|
||||
fflush(stdout);
|
||||
// If we've exceeded the configured interval, lock the screen
|
||||
if (delta >= interval_seconds) {
|
||||
// Use xinput to disable all keyboard-like devices until user stands again.
|
||||
// This pipeline lists input devices, filters keyboards (excluding XTEST),
|
||||
// extracts their IDs, and disables each one.
|
||||
system("xinput --list --short | "
|
||||
"grep -i 'keyboard' | grep -v 'XTEST' | "
|
||||
"sed -E 's/.*id=([0-9]+).*/\\1/' | "
|
||||
"xargs -r -n1 xinput disable");
|
||||
|
||||
system("i3lock -n -i /usr/local/share/lockscreens/standing_gopher.png");
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
system("i3lock -n -i /usr/local/share/lockscreens/standing_gopher.png");
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
// Replace with the specific event node for your keyboard
|
||||
// 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";
|
||||
struct input_event ev;
|
||||
int fd;
|
||||
// Replace with the specific event node for your keyboard
|
||||
// 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";
|
||||
struct input_event ev;
|
||||
int fd;
|
||||
|
||||
// Optional: -i <interval>[s|m] to override interval_seconds
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "i:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'i': {
|
||||
char *end = NULL;
|
||||
unsigned long long v = strtoull(optarg, &end, 10);
|
||||
if (!optarg[0] || end == optarg || v == 0) {
|
||||
fprintf(stderr, "Invalid interval '%s' for -i (must start with positive integer)\n", optarg);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
// Optional: -i <interval>[s|m] to override interval_seconds
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "i:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'i': {
|
||||
char *end = NULL;
|
||||
unsigned long long v = strtoull(optarg, &end, 10);
|
||||
if (!optarg[0] || end == optarg || v == 0) {
|
||||
fprintf(stderr, "Invalid interval '%s' for -i (must start with positive integer)\n", optarg);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
char unit = 'm'; // default unit: minutes
|
||||
if (*end != '\0') {
|
||||
// Allow a single unit character 's' or 'm'
|
||||
if (end[1] != '\0') {
|
||||
fprintf(stderr, "Invalid interval suffix in '%s' (use optional 's' or 'm')\n", optarg);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
unit = (char)tolower((unsigned char)*end);
|
||||
if (unit != 's' && unit != 'm') {
|
||||
fprintf(stderr, "Unknown interval unit '%c' in '%s' (use 's' or 'm')\n", *end, optarg);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
char unit = 'm'; // default unit: minutes
|
||||
if (*end != '\0') {
|
||||
// Allow a single unit character 's' or 'm'
|
||||
if (end[1] != '\0') {
|
||||
fprintf(stderr, "Invalid interval suffix in '%s' (use optional 's' or 'm')\n", optarg);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
unit = (char)tolower((unsigned char)*end);
|
||||
if (unit != 's' && unit != 'm') {
|
||||
fprintf(stderr, "Unknown interval unit '%c' in '%s' (use 's' or 'm')\n", *end, optarg);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (unit == 's') {
|
||||
interval_seconds = v;
|
||||
} else { // 'm'
|
||||
interval_seconds = v * 60ULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
fprintf(stderr, "Usage: %s [-i interval{s|m}]\n", argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
if (unit == 's') {
|
||||
interval_seconds = v;
|
||||
} else { // 'm'
|
||||
interval_seconds = v * 60ULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
fprintf(stderr, "Usage: %s [-i interval{s|m}]\n", argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
fd = open(dev, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
perror("Cannot open device");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
fd = open(dev, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
perror("Cannot open device");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Grab the device: This blocks all other apps from seeing these keystrokes
|
||||
if (ioctl(fd, EVIOCGRAB, 1) == -1) {
|
||||
perror("Could not grab device");
|
||||
close(fd);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
// Grab the device: This blocks all other apps from seeing these keystrokes
|
||||
if (ioctl(fd, EVIOCGRAB, 1) == -1) {
|
||||
perror("Could not grab device");
|
||||
close(fd);
|
||||
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"
|
||||
char buf_str[128];
|
||||
size_t buf_len = 0;
|
||||
// Buffer to accumulate the characters the reader "types"
|
||||
char buf_str[128];
|
||||
size_t buf_len = 0;
|
||||
|
||||
// Initialize last_time_standing and start the watcher thread
|
||||
last_time_standing = (unsigned long long)time(NULL);
|
||||
pthread_t watcher;
|
||||
if (pthread_create(&watcher, NULL, time_watcher_thread, NULL) != 0) {
|
||||
perror("Failed to create watcher thread");
|
||||
ioctl(fd, EVIOCGRAB, 0);
|
||||
close(fd);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
pthread_detach(watcher);
|
||||
// Continuous loop to capture events
|
||||
while (1) {
|
||||
ssize_t n = read(fd, &ev, sizeof(ev));
|
||||
if (n == (ssize_t)-1) {
|
||||
perror("Read error");
|
||||
break;
|
||||
} else if (n != sizeof(ev)) {
|
||||
continue;
|
||||
}
|
||||
// Process only key events (type 1)
|
||||
if (ev.type == EV_KEY) {
|
||||
if (ev.value == 1) { // key press
|
||||
if (ev.code == KEY_ENTER || ev.code == KEY_KPENTER) {
|
||||
// End of the "typed" sequence: print the accumulated string
|
||||
if (buf_len > 0) {
|
||||
buf_str[buf_len] = '\0';
|
||||
long long val = strtoll(buf_str, NULL, 10);
|
||||
// Get the SHA-256 hash of the value
|
||||
unsigned char hash[SHA256_DIGEST_LENGTH];
|
||||
SHA256((unsigned char*)buf_str, buf_len, hash);
|
||||
printf("SHA-256: ");
|
||||
unsigned long long hash_val = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
hash_val = (hash_val << 8) | hash[i];
|
||||
}
|
||||
printf(" (as number: %llu)", hash_val);
|
||||
printf("\n");
|
||||
printf("Typed: %s (as number: %lld)\n", buf_str, val);
|
||||
buf_len = 0;
|
||||
if (hash_val == 4798061567229363866L) {
|
||||
last_time_standing = (unsigned long long)time(NULL);
|
||||
printf("Desk reminder timer reset at %llu seconds since epoch.\n", last_time_standing);
|
||||
system("pkill i3lock");
|
||||
system("xinput --list --short | "
|
||||
"grep -i 'keyboard' | grep -v 'XTEST' | "
|
||||
"sed -E 's/.*id=([0-9]+).*/\\1/' | "
|
||||
"xargs -r -n1 xinput enable");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
char c = keycode_to_char(ev.code);
|
||||
if (c != '\0' && buf_len + 1 < sizeof(buf_str))
|
||||
buf_str[buf_len++] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Initialize last_time_standing and start the watcher thread
|
||||
last_time_standing = (unsigned long long)time(NULL);
|
||||
pthread_t watcher;
|
||||
if (pthread_create(&watcher, NULL, time_watcher_thread, NULL) != 0) {
|
||||
perror("Failed to create watcher thread");
|
||||
ioctl(fd, EVIOCGRAB, 0);
|
||||
close(fd);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
pthread_detach(watcher);
|
||||
// Continuous loop to capture events
|
||||
while (1) {
|
||||
ssize_t n = read(fd, &ev, sizeof(ev));
|
||||
if (n == (ssize_t)-1) {
|
||||
perror("Read error");
|
||||
break;
|
||||
} else if (n != sizeof(ev)) {
|
||||
continue;
|
||||
}
|
||||
// Process only key events (type 1)
|
||||
if (ev.type == EV_KEY) {
|
||||
if (ev.value == 1) { // key press
|
||||
if (ev.code == KEY_ENTER || ev.code == KEY_KPENTER) {
|
||||
// End of the "typed" sequence: print the accumulated string
|
||||
if (buf_len > 0) {
|
||||
buf_str[buf_len] = '\0';
|
||||
long long val = strtoll(buf_str, NULL, 10);
|
||||
// Get the SHA-256 hash of the value
|
||||
unsigned char hash[SHA256_DIGEST_LENGTH];
|
||||
SHA256((unsigned char*)buf_str, buf_len, hash);
|
||||
printf("SHA-256: ");
|
||||
unsigned long long hash_val = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
hash_val = (hash_val << 8) | hash[i];
|
||||
}
|
||||
printf(" (as number: %llu)", hash_val);
|
||||
printf("\n");
|
||||
printf("Typed: %s (as number: %lld)\n", buf_str, val);
|
||||
buf_len = 0;
|
||||
if (hash_val == 4798061567229363866L) {
|
||||
last_time_standing = (unsigned long long)time(NULL);
|
||||
printf("Desk reminder timer reset at %llu seconds since epoch.\n", last_time_standing);
|
||||
system("pkill i3lock");
|
||||
system("xinput --list --short | "
|
||||
"grep -i 'keyboard' | grep -v 'XTEST' | "
|
||||
"sed -E 's/.*id=([0-9]+).*/\\1/' | "
|
||||
"xargs -r -n1 xinput enable");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
char c = keycode_to_char(ev.code);
|
||||
if (c != '\0' && buf_len + 1 < sizeof(buf_str))
|
||||
buf_str[buf_len++] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Release the grab before exiting
|
||||
ioctl(fd, EVIOCGRAB, 0);
|
||||
close(fd);
|
||||
return 0;
|
||||
// Release the grab before exiting
|
||||
ioctl(fd, EVIOCGRAB, 0);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user