From 67ebbac0be7ad917e794ca5ea0496d0a1ead83b8 Mon Sep 17 00:00:00 2001 From: "B. Watson" Date: Tue, 6 May 2025 04:10:06 -0400 Subject: much work (options, rc script, make install, etc etc). --- marsond.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 105 insertions(+), 21 deletions(-) (limited to 'marsond.c') diff --git a/marsond.c b/marsond.c index 228310d..885a3e2 100644 --- a/marsond.c +++ b/marsond.c @@ -1,3 +1,5 @@ +#define _DEFAULT_SOURCE /* for getopt() and optarg */ + #include #include #include @@ -9,19 +11,17 @@ #include #include -#define DELAY_MS 30 +#define VERSION "0.0.1" -#define DEFAULT_KBD "/dev/input/by-id/usb-Marson_Marson_Keyboard_and_Mouse_Link_Ver:ps2120L-event-kbd" +#define DEFAULT_DELAY_MS 30 -/* eventually, this will take options to set the device and - delay for the Enter key, and will have an rc script to - start it...? */ +#define DEFAULT_KBD "/dev/input/by-id/usb-Marson_Marson_Keyboard_and_Mouse_Link_Ver:ps2120L-event-kbd" const char *self; -int debugging = 1; - -const char *keyboard_dev; +int debugging = 0; /* -v */ +const char *keyboard_dev = DEFAULT_KBD; /* -k */ +int delay_ms = DEFAULT_DELAY_MS; /* -d */ /* variadic macros are apparently C99 and not just a GNU extension */ void logmsg(const char *prefix, const char *fmt, ...) { @@ -34,8 +34,8 @@ void logmsg(const char *prefix, const char *fmt, ...) { } #define die(fmt, ...) { logmsg("fatal", fmt, ##__VA_ARGS__); exit(1); }; -#define warn(fmt, ...) logmsg("warning", fmt, ##__VA_ARGS__); -#define info(fmt, ...) logmsg("info", fmt, ##__VA_ARGS__); +#define warn(fmt, ...) { logmsg("warning", fmt, ##__VA_ARGS__); }; +#define info(fmt, ...) { logmsg("info", fmt, ##__VA_ARGS__); }; #define debug(fmt, ...) { if(debugging) logmsg("debug", fmt, ##__VA_ARGS__); }; void set_self(const char *argv0) { @@ -45,17 +45,93 @@ void set_self(const char *argv0) { if(p) self = p + 1; } +void print_help(void) { + /* helptext comes from usage.c, which gets generated by mkusage.pl, + from the content in the the .rst file. */ + extern const char *helptext[]; + + const char **helpline; + + puts("marsond " VERSION ", by B. Watson , WTFPL"); + puts("Usage:"); + + for(helpline = helptext; *helpline; helpline++) + puts(*helpline); +} + +void version(void) { + puts(VERSION); +} + +void parse_args(int argc, char **argv) { + int opt; + + opterr = 0; + + if(argc >= 2) { + if(strcmp(argv[1], "--help") == 0) { + print_help(); + exit(0); + } else if(strcmp(argv[1], "--version") == 0) { + version(); + exit(0); + } + } + + while( (opt = getopt(argc, argv, "d:hk:vV")) != -1) { + switch(opt) { + case 'v': debugging++; break; + case 'd': delay_ms = atoi(optarg); break; + case 'k': keyboard_dev = optarg; break; + case 'h': print_help(); exit(0); break; + case 'V': version(); exit(0); break; + case '?': die("invalid option (try --help)"); break; + default: print_help(); exit(1); break; + } + } + + if(delay_ms < 1) die("invalid -d argument"); +} + +void daemonize(void) { + int pid; + + pid = fork(); + if(pid < 0) { + die("fork() failed"); + } else if(pid) { + /* parent */ + exit(0); + } + + /* we are the child here */ + setsid(); + + pid = fork(); + if(pid < 0) { + die("fork() failed"); + } else if(pid) { + /* 2nd generation parent */ + info("forked to background, PID %d\n", pid); + exit(0); + } + + /* we are the grandchild here */ + chdir("/"); + close(0); + close(1); + close(2); +} + int main(int argc, char **argv) { int infd, outfd, i; struct uinput_user_dev dev; struct input_event ev; - static struct input_event deferred_ev; set_self(argv[0]); debug("starting up"); - if(!keyboard_dev) - keyboard_dev = DEFAULT_KBD; + parse_args(argc, argv); if((outfd = open("/dev/uinput", O_WRONLY | O_NONBLOCK)) >= 0) { debug("opened /dev/uinput"); @@ -88,12 +164,13 @@ int main(int argc, char **argv) { die("UI_SET_EVBIT failed: %s", strerror(errno)); } } + debug("UI_SET_KEYBIT OK"); memset(&dev, 0, sizeof(dev)); snprintf(dev.name, UINPUT_MAX_NAME_SIZE, "marsond virtual keyboard"); - dev.id.bustype == BUS_USB; - dev.id.vendor = 1; - dev.id.product = 1; + dev.id.bustype = BUS_USB; + dev.id.vendor = 0x69; + dev.id.product = 0x666; dev.id.version = 1; if(write(outfd, &dev, sizeof(dev)) >= 0) { @@ -108,25 +185,32 @@ int main(int argc, char **argv) { die("UI_DEV_CREATE failed: %s", strerror(errno)); } + if(!debugging) daemonize(); + + /* note: don't call die() unless debugging is true, since daemonize() + closes our stderr (there's nowhere for the error message to print). */ + while(1) { if(read(infd, &ev, sizeof(ev)) < 0) { - die("read from %s failed: %s", keyboard_dev, strerror(errno)); + if(debugging) + die("read from %s failed: %s", keyboard_dev, strerror(errno)); } debug("event: type %d, code %d, value %d\n", ev.type, ev.code, ev.value); if(ev.type == EV_KEY && ev.code == KEY_ENTER && ev.value == 0) { - debug("got Enter key release, delaying %d ms", DELAY_MS); - usleep(DELAY_MS * 1000); + debug("got Enter key release, delaying %d ms", delay_ms); + usleep(delay_ms * 1000); } if(write(outfd, &ev, sizeof(ev)) < 0) { - die("write to /dev/uinput failed: %s", strerror(errno)); + if(debugging) + die("write to /dev/uinput failed: %s", strerror(errno)); } } - exit(0); + exit(1); } /* -- cgit v1.2.3