aboutsummaryrefslogtreecommitdiff
path: root/marsond.c
diff options
context:
space:
mode:
authorB. Watson <urchlay@slackware.uk>2025-05-06 04:10:06 -0400
committerB. Watson <urchlay@slackware.uk>2025-05-06 04:10:06 -0400
commit67ebbac0be7ad917e794ca5ea0496d0a1ead83b8 (patch)
treed169b8481afe91a394023c294741a21e57cb033f /marsond.c
parentc4eda00ddbc16723f3e1d1e943edaaa2c6c2c748 (diff)
downloadmarsond-67ebbac0be7ad917e794ca5ea0496d0a1ead83b8.tar.gz
much work (options, rc script, make install, etc etc).
Diffstat (limited to 'marsond.c')
-rw-r--r--marsond.c126
1 files changed, 105 insertions, 21 deletions
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 <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -9,19 +11,17 @@
#include <linux/input.h>
#include <linux/uinput.h>
-#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 <urchlay@slackware.uk>, 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);
}
/*