aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkoekeishiya <aasvi93@hotmail.com>2019-03-07 22:43:23 +0100
committerkoekeishiya <aasvi93@hotmail.com>2019-03-07 22:43:23 +0100
commit3922cf456a6c711032a1a6650442be67cfbb80fb (patch)
tree86cb6d88498a6c20fdb8237b8baf58f2def293af
parentac494e3f72e397aaf3245b0401bd1b963bd4ebd3 (diff)
downloadskhd-3922cf456a6c711032a1a6650442be67cfbb80fb.tar.gz
skhd-3922cf456a6c711032a1a6650442be67cfbb80fb.zip
#54 ability to disable hotloader and trigger manual reload of config file
-rw-r--r--README.md6
-rw-r--r--src/parse.c9
-rw-r--r--src/skhd.c103
3 files changed, 102 insertions, 16 deletions
diff --git a/README.md b/README.md
index 24b9226..c4b1a8d 100644
--- a/README.md
+++ b/README.md
@@ -56,6 +56,12 @@ Requires xcode-8 command-line tools.
-c | --config: Specify location of config file
skhd -c ~/.skhdrc
+-r | --reload: Signal a running instance of skhd to reload its config file
+ skhd -r
+
+-h | --no-hotload: Disable system for hotloading config file
+ skhd -h
+
-k | --key: Synthesize a keypress (same syntax as when defining a hotkey)
skhd -k "shift + alt - 7"
diff --git a/src/parse.c b/src/parse.c
index 9f14389..e2b4c4d 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -588,7 +588,7 @@ void parser_report_error(struct parser *parser, struct token token, const char *
parser->error = true;
}
-void parser_do_directives(struct parser *parser, struct hotloader *hotloader)
+void parser_do_directives(struct parser *parser, struct hotloader *hotloader, bool thwart_hotloader)
{
bool error = false;
@@ -597,13 +597,16 @@ void parser_do_directives(struct parser *parser, struct hotloader *hotloader)
struct parser directive_parser;
if (parser_init(&directive_parser, parser->mode_map, parser->blacklst, load.file)) {
- hotloader_add_file(hotloader, load.file);
+ if (!thwart_hotloader) {
+ hotloader_add_file(hotloader, load.file);
+ }
if (parse_config(&directive_parser)) {
- parser_do_directives(&directive_parser, hotloader);
+ parser_do_directives(&directive_parser, hotloader, thwart_hotloader);
} else {
error = true;
}
+
parser_destroy(&directive_parser);
} else {
warn("skhd: could not open file '%s' from load directive #%d:%d\n", load.file, load.option.line, load.option.cursor);
diff --git a/src/skhd.c b/src/skhd.c
index c90c4b6..1ae7976 100644
--- a/src/skhd.c
+++ b/src/skhd.c
@@ -5,6 +5,10 @@
#include <getopt.h>
#include <signal.h>
#include <string.h>
+#include <fcntl.h>
+#include <sys/file.h>
+#include <sys/types.h>
+#include <sys/uio.h>
#include <unistd.h>
#include <Carbon/Carbon.h>
@@ -38,6 +42,7 @@ extern bool CGSIsSecureEventInputSet();
#define global static
#define SKHD_CONFIG_FILE ".skhdrc"
+#define SKHD_PID_FILE "/tmp/skhd.pid"
global unsigned major_version = 0;
global unsigned minor_version = 3;
@@ -49,6 +54,7 @@ global struct hotloader hotloader;
global struct mode *current_mode;
global struct table mode_map;
global struct table blacklst;
+global bool thwart_hotloader;
global char *config_file;
internal HOTLOADER_CALLBACK(config_handler);
@@ -58,21 +64,25 @@ parse_config_helper(char *absolutepath)
{
struct parser parser;
if (parser_init(&parser, &mode_map, &blacklst, absolutepath)) {
- hotloader_end(&hotloader);
- hotloader_add_file(&hotloader, absolutepath);
+ if (!thwart_hotloader) {
+ hotloader_end(&hotloader);
+ hotloader_add_file(&hotloader, absolutepath);
+ }
if (parse_config(&parser)) {
- parser_do_directives(&parser, &hotloader);
+ parser_do_directives(&parser, &hotloader, thwart_hotloader);
}
parser_destroy(&parser);
- if (hotloader_begin(&hotloader, config_handler)) {
- debug("skhd: watching files for changes:\n", absolutepath);
- for (int i = 0; i < hotloader.watch_count; ++i) {
- debug("\t%s\n", hotloader.watch_list[i].file_info.absolutepath);
+ if (!thwart_hotloader) {
+ if (hotloader_begin(&hotloader, config_handler)) {
+ debug("skhd: watching files for changes:\n", absolutepath);
+ for (int i = 0; i < hotloader.watch_count; ++i) {
+ debug("\t%s\n", hotloader.watch_list[i].file_info.absolutepath);
+ }
+ } else {
+ warn("skhd: could not start watcher.. hotloading is not enabled\n");
}
- } else {
- warn("skhd: could not start watcher.. hotloading is not enabled\n");
}
} else {
warn("skhd: could not open file '%s'\n", absolutepath);
@@ -137,18 +147,73 @@ internal EVENT_TAP_CALLBACK(key_handler)
return event;
}
+internal void
+sigusr1_handler(int signal)
+{
+ BEGIN_TIMED_BLOCK("sigusr1");
+ debug("skhd: SIGUSR1 received.. reloading config\n");
+ free_mode_map(&mode_map);
+ free_blacklist(&blacklst);
+ parse_config_helper(config_file);
+ END_TIMED_BLOCK();
+}
+
+internal pid_t
+read_pid_file(void)
+{
+ pid_t pid = 0;
+
+ int handle = open(SKHD_PID_FILE, O_RDWR);
+ if (handle == -1) {
+ error("skhd: could not open pid-file..\n");
+ }
+
+ if (flock(handle, LOCK_EX | LOCK_NB) == 0) {
+ error("skhd: could not locate existing instance..\n");
+ } else if (read(handle, &pid, sizeof(pid_t)) == -1) {
+ error("skhd: could not read pid-file..\n");
+ }
+
+ close(handle);
+ return pid;
+}
+
+internal void
+create_pid_file(void)
+{
+ pid_t pid = getpid();
+
+ int handle = open(SKHD_PID_FILE, O_CREAT | O_WRONLY, 0644);
+ if (handle == -1) {
+ error("skhd: could not create pid-file! abort..\n");
+ }
+
+ if (flock(handle, LOCK_EX | LOCK_NB) == -1) {
+ error("skhd: could not lock pid-file! abort..\n");
+ } else if (write(handle, &pid, sizeof(pid_t)) == -1) {
+ error("skhd: could not write pid-file! abort..\n");
+ }
+
+ // NOTE(koekeishiya): we intentionally leave the handle open,
+ // as calling close(..) will release the lock we just acquired.
+
+ debug("skhd: successfully created pid-file..\n");
+}
+
internal bool
parse_arguments(int argc, char **argv)
{
int option;
- const char *short_option = "VPvc:k:t:";
+ const char *short_option = "VPvc:k:t:rh";
struct option long_option[] = {
{ "verbose", no_argument, NULL, 'V' },
{ "profile", no_argument, NULL, 'P' },
{ "version", no_argument, NULL, 'v' },
{ "config", required_argument, NULL, 'c' },
+ { "no-hotload", no_argument, NULL, 'h' },
{ "key", required_argument, NULL, 'k' },
{ "text", required_argument, NULL, 't' },
+ { "reload", no_argument, NULL, 'r' },
{ NULL, 0, NULL, 0 }
};
@@ -167,6 +232,9 @@ parse_arguments(int argc, char **argv)
case 'c': {
config_file = copy_string(optarg);
} break;
+ case 'h': {
+ thwart_hotloader = true;
+ } break;
case 'k': {
synthesize_key(optarg);
return true;
@@ -175,6 +243,11 @@ parse_arguments(int argc, char **argv)
synthesize_text(optarg);
return true;
} break;
+ case 'r': {
+ pid_t pid = read_pid_file();
+ if (pid) kill(pid, SIGUSR1);
+ return true;
+ } break;
}
}
@@ -219,15 +292,17 @@ use_default_config_path(void)
int main(int argc, char **argv)
{
+ if (getuid() == 0 || geteuid() == 0) {
+ error("skhd: running as root is not allowed! abort..\n");
+ }
+
if (parse_arguments(argc, argv)) {
return EXIT_SUCCESS;
}
BEGIN_SCOPED_TIMED_BLOCK("total_time");
BEGIN_SCOPED_TIMED_BLOCK("init");
- if (getuid() == 0 || geteuid() == 0) {
- error("skhd: running as root is not allowed! abort..\n");
- }
+ create_pid_file();
if (secure_keyboard_entry_enabled()) {
error("skhd: secure keyboard entry is enabled! abort..\n");
@@ -257,6 +332,8 @@ int main(int argc, char **argv)
CFNotificationSuspensionBehaviorCoalesce);
signal(SIGCHLD, SIG_IGN);
+ signal(SIGUSR1, sigusr1_handler);
+
init_shell();
table_init(&mode_map, 13, (table_hash_func) hash_string, (table_compare_func) compare_string);
table_init(&blacklst, 13, (table_hash_func) hash_string, (table_compare_func) compare_string);