99 lines
2.2 KiB
C
99 lines
2.2 KiB
C
#include <signal.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include <getopt.h>
|
|
|
|
#include "actkbd.h"
|
|
|
|
/* file names */
|
|
char *device = NULL, *config = NULL;
|
|
|
|
static int got_hup = 0;
|
|
|
|
int verbose = 0;
|
|
|
|
static void hup_handler(int signum __attribute__((unused))) {
|
|
got_hup = 0;
|
|
}
|
|
|
|
int main(int argc, char *const argv[]) {
|
|
/* event data */
|
|
Key key;
|
|
int type;
|
|
/* so we can DRY the help message */
|
|
/* tracking conf changes */
|
|
struct stat conf_info;
|
|
time_t conf_last_changed = 0;
|
|
void * callback;
|
|
|
|
int opt, ret = USAGE;
|
|
while ((opt = getopt(argc, argv, "vhd:c:")) != -1) {
|
|
switch (opt) {
|
|
case 'v': verbose = 1; break;
|
|
case 'd': device = optarg; break;
|
|
case 'c': config = optarg; break;
|
|
case 'h':
|
|
ret = EXIT_SUCCESS;
|
|
__attribute__((fallthrough));
|
|
default:
|
|
printf("actkbd [-d DEVICE|-c CONFIG_FILE|-h|-v]\n");
|
|
exit(ret);
|
|
}
|
|
}
|
|
|
|
if (!device) {
|
|
fprintf(stderr, "Must specify a device file!\n");
|
|
exit(USAGE);
|
|
}
|
|
|
|
if (!config) {
|
|
fprintf(stderr, "Must specify a configuration file!\n");
|
|
exit(USAGE);
|
|
}
|
|
|
|
/* end of cli processing */
|
|
|
|
open_dev();
|
|
extension_init();
|
|
|
|
/* Setup the signal handling */
|
|
signal(SIGHUP, hup_handler);
|
|
|
|
/* event loop */
|
|
do {
|
|
if(got_hup) {
|
|
/* got a SIGHUP, so reload config... */
|
|
stat(config, &conf_info);
|
|
|
|
if (conf_info.st_mtime != conf_last_changed) {
|
|
/* ... but only if it changed */
|
|
clear_bindings();
|
|
extension_reload();
|
|
conf_last_changed = conf_info.st_mtime;
|
|
}
|
|
got_hup = 0;
|
|
}
|
|
|
|
/* we can ignore READERR because it causes the program to exit */
|
|
if(get_key(&key, &type) == EVERR) {
|
|
continue;
|
|
}
|
|
|
|
if (verbose) {
|
|
fprintf(stderr, "Key: %u, event: %i\n", key, type);
|
|
/* We don't currently have a string representation of foreign procedures
|
|
we could hack this by sending an invalid event that the code handles
|
|
specifically and returns a value that we could use, like a string.
|
|
This would probably need a bind-wrapper macro that evaluates the
|
|
procedure string and puts it onto the special code path. */
|
|
/* fprintf(stderr, "Executing: %i\n", bindings[key]); */
|
|
}
|
|
|
|
/* we onyl do stuff if the key is bound */
|
|
callback = get_cb(key);
|
|
if (callback != NULL) /* && (!noexec) */ {
|
|
call_bound_function(callback, type);
|
|
}
|
|
} while(1);
|
|
}
|