aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkoekeishiya <aasvi93@hotmail.com>2023-05-01 18:27:07 +0200
committerkoekeishiya <aasvi93@hotmail.com>2023-05-01 18:27:07 +0200
commit18dd6a0418ddb8a03e91aed5d6e465e519d95ebd (patch)
tree735b72d52c8e5a076badbc3db81850a691791c58
parentb659b90576cf88100b52ca6ab9270d84af7e579b (diff)
downloadskhd-18dd6a0418ddb8a03e91aed5d6e465e519d95ebd.tar.gz
skhd-18dd6a0418ddb8a03e91aed5d6e465e519d95ebd.zip
cleanup, add service commands
-rw-r--r--src/carbon.c8
-rw-r--r--src/hashtable.h8
-rw-r--r--src/hotkey.c31
-rw-r--r--src/hotkey.h10
-rw-r--r--src/hotload.c22
-rw-r--r--src/locale.c23
-rw-r--r--src/log.h14
-rw-r--r--src/parse.c36
-rw-r--r--src/sbuffer.h6
-rw-r--r--src/service.h183
-rw-r--r--src/skhd.c110
-rw-r--r--src/synthesize.c6
-rw-r--r--src/timing.h14
-rw-r--r--src/tokenize.c21
-rw-r--r--src/tokenize.h8
15 files changed, 330 insertions, 170 deletions
diff --git a/src/carbon.c b/src/carbon.c
index dcfc2d8..687820c 100644
--- a/src/carbon.c
+++ b/src/carbon.c
@@ -1,10 +1,8 @@
#include "carbon.h"
-#define internal static
-
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated"
-internal inline char *
+static inline char *
find_process_name_for_psn(ProcessSerialNumber *psn)
{
CFStringRef process_name_ref;
@@ -25,7 +23,7 @@ find_process_name_for_pid(pid_t pid)
return find_process_name_for_psn(&psn);
}
-internal inline char *
+static inline char *
find_active_process_name(void)
{
ProcessSerialNumber psn;
@@ -34,7 +32,7 @@ find_active_process_name(void)
}
#pragma clang diagnostic pop
-internal OSStatus
+static OSStatus
carbon_event_handler(EventHandlerCallRef ref, EventRef event, void *context)
{
struct carbon_event *carbon = (struct carbon_event *) context;
diff --git a/src/hashtable.h b/src/hashtable.h
index 8f73066..f593432 100644
--- a/src/hashtable.h
+++ b/src/hashtable.h
@@ -33,9 +33,7 @@ void *table_reset(struct table *table, int *count);
#include <stdlib.h>
#include <string.h>
-#define internal static
-
-internal struct bucket *
+static struct bucket *
table_new_bucket(void *key, void *value)
{
struct bucket *bucket = malloc(sizeof(struct bucket));
@@ -45,7 +43,7 @@ table_new_bucket(void *key, void *value)
return bucket;
}
-internal struct bucket **
+static struct bucket **
table_get_bucket(struct table *table, void *key)
{
struct bucket **bucket = table->buckets + (table->hash(key) % table->capacity);
@@ -58,8 +56,6 @@ table_get_bucket(struct table *table, void *key)
return bucket;
}
-#undef internal
-
void table_init(struct table *table, int capacity, table_hash_func hash, table_compare_func compare)
{
table->count = 0;
diff --git a/src/hotkey.c b/src/hotkey.c
index 780aa3a..6ed79f5 100644
--- a/src/hotkey.c
+++ b/src/hotkey.c
@@ -1,8 +1,5 @@
#include "hotkey.h"
-#define internal static
-#define global static
-
#define HOTKEY_FOUND ((1) << 0)
#define MODE_CAPTURE(a) ((a) << 1)
#define HOTKEY_PASSTHROUGH(a) ((a) << 2)
@@ -14,10 +11,10 @@
#define LMOD_OFFS 1
#define RMOD_OFFS 2
-global char arg[] = "-c";
-global char *shell = NULL;
+static char arg[] = "-c";
+static char *shell = NULL;
-internal uint32_t cgevent_lrmod_flag[] =
+static uint32_t cgevent_lrmod_flag[] =
{
Event_Mask_Alt, Event_Mask_LAlt, Event_Mask_RAlt,
Event_Mask_Shift, Event_Mask_LShift, Event_Mask_RShift,
@@ -25,7 +22,7 @@ internal uint32_t cgevent_lrmod_flag[] =
Event_Mask_Control, Event_Mask_LControl, Event_Mask_RControl,
};
-internal uint32_t hotkey_lrmod_flag[] =
+static uint32_t hotkey_lrmod_flag[] =
{
Hotkey_Flag_Alt, Hotkey_Flag_LAlt, Hotkey_Flag_RAlt,
Hotkey_Flag_Shift, Hotkey_Flag_LShift, Hotkey_Flag_RShift,
@@ -33,7 +30,7 @@ internal uint32_t hotkey_lrmod_flag[] =
Hotkey_Flag_Control, Hotkey_Flag_LControl, Hotkey_Flag_RControl,
};
-internal bool
+static bool
compare_lr_mod(struct hotkey *a, struct hotkey *b, int mod)
{
bool result = has_flags(a, hotkey_lrmod_flag[mod])
@@ -46,13 +43,13 @@ compare_lr_mod(struct hotkey *a, struct hotkey *b, int mod)
return result;
}
-internal bool
+static bool
compare_fn(struct hotkey *a, struct hotkey *b)
{
return has_flags(a, Hotkey_Flag_Fn) == has_flags(b, Hotkey_Flag_Fn);
}
-internal bool
+static bool
compare_nx(struct hotkey *a, struct hotkey *b)
{
return has_flags(a, Hotkey_Flag_NX) == has_flags(b, Hotkey_Flag_NX);
@@ -97,7 +94,7 @@ unsigned long hash_string(char *key)
return hash;
}
-internal inline void
+static inline void
fork_and_exec(char *command)
{
int cpid = fork();
@@ -109,13 +106,13 @@ fork_and_exec(char *command)
}
}
-internal inline void
+static inline void
passthrough(struct hotkey *hotkey, uint32_t *capture)
{
*capture |= HOTKEY_PASSTHROUGH((int)has_flags(hotkey, Hotkey_Flag_Passthrough));
}
-internal inline struct hotkey *
+static inline struct hotkey *
find_hotkey(struct mode *mode, struct hotkey *hotkey, uint32_t *capture)
{
struct hotkey *result = table_find(&mode->hotkey_map, hotkey);
@@ -123,7 +120,7 @@ find_hotkey(struct mode *mode, struct hotkey *hotkey, uint32_t *capture)
return result;
}
-internal inline bool
+static inline bool
should_capture_hotkey(uint32_t capture)
{
if ((capture & HOTKEY_FOUND)) {
@@ -143,7 +140,7 @@ should_capture_hotkey(uint32_t capture)
return (capture & MODE_CAPTURE(1));
}
-internal inline char *
+static inline char *
find_process_command_mapping(struct hotkey *hotkey, uint32_t *capture, struct carbon_event *carbon)
{
char *result = NULL;
@@ -238,7 +235,7 @@ void free_blacklist(struct table *blacklst)
}
}
-internal void
+static void
cgevent_lrmod_flag_to_hotkey_lrmod_flag(CGEventFlags eventflags, uint32_t *flags, int mod)
{
enum osx_event_mask mask = cgevent_lrmod_flag[mod];
@@ -255,7 +252,7 @@ cgevent_lrmod_flag_to_hotkey_lrmod_flag(CGEventFlags eventflags, uint32_t *flags
}
}
-internal uint32_t
+static uint32_t
cgevent_flags_to_hotkey_flags(uint32_t eventflags)
{
uint32_t flags = 0;
diff --git a/src/hotkey.h b/src/hotkey.h
index 6b6e92a..78aba3f 100644
--- a/src/hotkey.h
+++ b/src/hotkey.h
@@ -78,29 +78,25 @@ struct hotkey
struct mode **mode_list;
};
-#define internal static
-
-internal inline void
+static inline void
add_flags(struct hotkey *hotkey, uint32_t flag)
{
hotkey->flags |= flag;
}
-internal inline bool
+static inline bool
has_flags(struct hotkey *hotkey, uint32_t flag)
{
bool result = hotkey->flags & flag;
return result;
}
-internal inline void
+static inline void
clear_flags(struct hotkey *hotkey, uint32_t flag)
{
hotkey->flags &= ~flag;
}
-#undef internal
-
bool compare_string(char *a, char *b);
unsigned long hash_string(char *key);
diff --git a/src/hotload.c b/src/hotload.c
index 88d286a..830d565 100644
--- a/src/hotload.c
+++ b/src/hotload.c
@@ -4,8 +4,6 @@
#include <stdlib.h>
#include <string.h>
-#define internal static
-
#define FSEVENT_CALLBACK(name) void name(ConstFSEventStreamRef stream,\
void *context,\
size_t file_count,\
@@ -42,14 +40,14 @@ struct watched_entry
};
};
-internal inline bool
+static inline bool
same_string(const char *a, const char *b)
{
bool result = a && b && strcmp(a, b) == 0;
return result;
}
-internal char *
+static char *
copy_string(const char *s)
{
unsigned length = strlen(s);
@@ -59,7 +57,7 @@ copy_string(const char *s)
return result;
}
-internal char *
+static char *
file_directory(char *file)
{
char *last_slash = strrchr(file, '/');
@@ -69,7 +67,7 @@ file_directory(char *file)
return directory;
}
-internal char *
+static char *
file_name(char *file)
{
char *last_slash = strrchr(file, '/');
@@ -77,7 +75,7 @@ file_name(char *file)
return name;
}
-internal char *
+static char *
resolve_symlink(const char *file)
{
struct stat buffer;
@@ -97,7 +95,7 @@ resolve_symlink(const char *file)
return result;
}
-internal enum watch_kind
+static enum watch_kind
resolve_watch_kind(char *file)
{
struct stat buffer;
@@ -116,7 +114,7 @@ resolve_watch_kind(char *file)
return WATCH_KIND_INVALID;
}
-internal char *
+static char *
same_catalog(char *absolutepath, struct watched_catalog *catalog_info)
{
char *last_slash = strrchr(absolutepath, '/');
@@ -141,14 +139,14 @@ same_catalog(char *absolutepath, struct watched_catalog *catalog_info)
return filename;
}
-internal inline bool
+static inline bool
same_file(char *absolutepath, struct watched_file *file_info)
{
bool result = same_string(absolutepath, file_info->absolutepath);
return result;
}
-internal FSEVENT_CALLBACK(hotloader_handler)
+static FSEVENT_CALLBACK(hotloader_handler)
{
/* NOTE(koekeishiya): We sometimes get two events upon file save. */
struct hotloader *hotloader = (struct hotloader *) context;
@@ -178,7 +176,7 @@ internal FSEVENT_CALLBACK(hotloader_handler)
}
}
-internal inline void
+static inline void
hotloader_add_watched_entry(struct hotloader *hotloader, struct watched_entry entry)
{
if (!hotloader->watch_list) {
diff --git a/src/locale.c b/src/locale.c
index 64f8b04..d83cd31 100644
--- a/src/locale.c
+++ b/src/locale.c
@@ -6,14 +6,10 @@
#define array_count(a) (sizeof((a)) / sizeof(*(a)))
-#define internal static
-#define global static
+static struct table keymap_table;
+static char **keymap_keys;
-global struct table keymap_table;
-global char **keymap_keys;
-
-internal char *
-copy_cfstring(CFStringRef string)
+static char *copy_cfstring(CFStringRef string)
{
CFIndex num_bytes = CFStringGetMaximumSizeForEncoding(CFStringGetLength(string), kCFStringEncodingUTF8);
char *result = malloc(num_bytes + 1);
@@ -27,8 +23,7 @@ copy_cfstring(CFStringRef string)
return result;
}
-internal int
-hash_keymap(const char *a)
+static int hash_keymap(const char *a)
{
unsigned long hash = 0, high;
while (*a) {
@@ -42,8 +37,7 @@ hash_keymap(const char *a)
return hash;
}
-internal bool
-same_keymap(const char *a, const char *b)
+static bool same_keymap(const char *a, const char *b)
{
while (*a && *b && *a == *b) {
++a;
@@ -52,8 +46,7 @@ same_keymap(const char *a, const char *b)
return *a == '\0' && *b == '\0';
}
-internal void
-free_keycode_map(void)
+static void free_keycode_map(void)
{
for (int i = 0; i < buf_len(keymap_keys); ++i) {
free(keymap_keys[i]);
@@ -63,7 +56,7 @@ free_keycode_map(void)
keymap_keys = NULL;
}
-internal uint32_t layout_dependent_keycodes[] =
+static uint32_t layout_dependent_keycodes[] =
{
kVK_ANSI_A, kVK_ANSI_B, kVK_ANSI_C,
kVK_ANSI_D, kVK_ANSI_E, kVK_ANSI_F,
@@ -134,6 +127,6 @@ bool initialize_keycode_map(void)
uint32_t keycode_from_char(char key)
{
char lookup_key[] = { key, '\0' };
- uint32_t keycode = (uint32_t) table_find(&keymap_table, &lookup_key);
+ uint32_t keycode = (uint32_t) (uintptr_t) table_find(&keymap_table, &lookup_key);
return keycode;
}
diff --git a/src/log.h b/src/log.h
index 88c12a2..2e8167b 100644
--- a/src/log.h
+++ b/src/log.h
@@ -1,12 +1,9 @@
#ifndef SKHD_LOG_H
#define SKHD_LOG_H
-#define internal static
-#define global static
+static bool verbose;
-global bool verbose;
-
-internal inline void
+static inline void
debug(const char *format, ...)
{
if (!verbose) return;
@@ -17,7 +14,7 @@ debug(const char *format, ...)
va_end(args);
}
-internal inline void
+static inline void
warn(const char *format, ...)
{
va_list args;
@@ -26,7 +23,7 @@ warn(const char *format, ...)
va_end(args);
}
-internal inline void
+static inline void
error(const char *format, ...)
{
va_list args;
@@ -36,7 +33,4 @@ error(const char *format, ...)
exit(EXIT_FAILURE);
}
-#undef internal
-#undef global
-
#endif
diff --git a/src/parse.c b/src/parse.c
index 42feca2..d9c453a 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -10,9 +10,7 @@
#include <stdarg.h>
#include <stdbool.h>
-#define internal static
-
-internal struct mode *
+static struct mode *
find_or_init_default_mode(struct parser *parser)
{
struct mode *default_mode;
@@ -36,7 +34,7 @@ find_or_init_default_mode(struct parser *parser)
return default_mode;
}
-internal char *
+static char *
read_file(const char *file)
{
unsigned length;
@@ -56,7 +54,7 @@ read_file(const char *file)
return buffer;
}
-internal char *
+static char *
copy_string_count(char *s, int length)
{
char *result = malloc(length + 1);
@@ -65,7 +63,7 @@ copy_string_count(char *s, int length)
return result;
}
-internal uint32_t
+static uint32_t
keycode_from_hex(char *hex)
{
uint32_t result;
@@ -73,7 +71,7 @@ keycode_from_hex(char *hex)
return result;
}
-internal void
+static void
parse_command(struct parser *parser, struct hotkey *hotkey)
{
struct token command = parser_previous(parser);
@@ -82,7 +80,7 @@ parse_command(struct parser *parser, struct hotkey *hotkey)
buf_push(hotkey->command, result);
}
-internal void
+static void
parse_process_command_list(struct parser *parser, struct hotkey *hotkey)
{
if (parser_match(parser, Token_String)) {
@@ -121,7 +119,7 @@ parse_process_command_list(struct parser *parser, struct hotkey *hotkey)
}
}
-internal void
+static void
parse_activate(struct parser *parser, struct hotkey *hotkey)
{
parse_command(parser, hotkey);
@@ -132,7 +130,7 @@ parse_activate(struct parser *parser, struct hotkey *hotkey)
}
}
-internal uint32_t
+static uint32_t
parse_key_hex(struct parser *parser)
{
struct token key = parser_previous(parser);
@@ -143,7 +141,7 @@ parse_key_hex(struct parser *parser)
return keycode;
}
-internal uint32_t
+static uint32_t
parse_key(struct parser *parser)
{
uint32_t keycode;
@@ -155,7 +153,7 @@ parse_key(struct parser *parser)
#define KEY_HAS_IMPLICIT_FN_MOD 4
#define KEY_HAS_IMPLICIT_NX_MOD 35
-internal uint32_t literal_keycode_value[] =
+static uint32_t literal_keycode_value[] =
{
kVK_Return, kVK_Tab, kVK_Space,
kVK_Delete, kVK_Escape, kVK_ForwardDelete,
@@ -176,7 +174,7 @@ internal uint32_t literal_keycode_value[] =
NX_KEYTYPE_BRIGHTNESS_DOWN, NX_KEYTYPE_ILLUMINATION_UP, NX_KEYTYPE_ILLUMINATION_DOWN
};
-internal inline void
+static inline void
handle_implicit_literal_flags(struct hotkey *hotkey, int literal_index)
{
if ((literal_index > KEY_HAS_IMPLICIT_FN_MOD) &&
@@ -187,7 +185,7 @@ handle_implicit_literal_flags(struct hotkey *hotkey, int literal_index)
}
}
-internal void
+static void
parse_key_literal(struct parser *parser, struct hotkey *hotkey)
{
struct token key = parser_previous(parser);
@@ -201,7 +199,7 @@ parse_key_literal(struct parser *parser, struct hotkey *hotkey)
}
}
-internal enum hotkey_flag modifier_flags_value[] =
+static enum hotkey_flag modifier_flags_value[] =
{
Hotkey_Flag_Alt, Hotkey_Flag_LAlt, Hotkey_Flag_RAlt,
Hotkey_Flag_Shift, Hotkey_Flag_LShift, Hotkey_Flag_RShift,
@@ -210,7 +208,7 @@ internal enum hotkey_flag modifier_flags_value[] =
Hotkey_Flag_Fn, Hotkey_Flag_Hyper, Hotkey_Flag_Meh,
};
-internal uint32_t
+static uint32_t
parse_modifier(struct parser *parser)
{
struct token modifier = parser_previous(parser);
@@ -235,7 +233,7 @@ parse_modifier(struct parser *parser)
return flags;
}
-internal void
+static void
parse_mode(struct parser *parser, struct hotkey *hotkey)
{
struct token identifier = parser_previous(parser);
@@ -263,7 +261,7 @@ parse_mode(struct parser *parser, struct hotkey *hotkey)
}
}
-internal struct hotkey *
+static struct hotkey *
parse_hotkey(struct parser *parser)
{
struct hotkey *hotkey = malloc(sizeof(struct hotkey));
@@ -342,7 +340,7 @@ err:
return NULL;
}
-internal struct mode *
+static struct mode *
parse_mode_decl(struct parser *parser)
{
struct mode *mode = malloc(sizeof(struct mode));
diff --git a/src/sbuffer.h b/src/sbuffer.h
index dc98b6e..5dca5cc 100644
--- a/src/sbuffer.h
+++ b/src/sbuffer.h
@@ -24,9 +24,7 @@ struct buf_hdr
#define buf_last(b) ((b)[buf_len(b)-1])
#define buf_free(b) ((b) ? free(buf__hdr(b)) : 0)
-#define internal static
-
-internal void *buf__grow_f(const void *buf, size_t new_len, size_t elem_size)
+static void *buf__grow_f(const void *buf, size_t new_len, size_t elem_size)
{
size_t new_cap = buf_MAX(1 + 2*buf_cap(buf), new_len);
size_t new_size = buf_OFFSETOF(struct buf_hdr, buf) + new_cap*elem_size;
@@ -38,6 +36,4 @@ internal void *buf__grow_f(const void *buf, size_t new_len, size_t elem_size)
return new_hdr->buf;
}
-#undef internal
-
#endif
diff --git a/src/service.h b/src/service.h
new file mode 100644
index 0000000..01c5f75
--- /dev/null
+++ b/src/service.h
@@ -0,0 +1,183 @@
+#ifndef SERVICE_H
+#define SERVICE_H
+
+#include <spawn.h>
+
+#define MAXLEN 512
+
+#define _PATH_LAUNCHCTL "/bin/launchctl"
+#define _NAME_SKHD_PLIST "com.koekeishiya.skhd"
+#define _PATH_SKHD_PLIST "/Users/%s/Library/LaunchAgents/"_NAME_SKHD_PLIST".plist"
+
+#define _SKHD_PLIST \
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" \
+ "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" \
+ "<plist version=\"1.0\">\n" \
+ "<dict>\n" \
+ " <key>Label</key>\n" \
+ " <string>"_NAME_SKHD_PLIST"</string>\n" \
+ " <key>ProgramArguments</key>\n" \
+ " <array>\n" \
+ " <string>%s</string>\n" \
+ " </array>\n" \
+ " <key>EnvironmentVariables</key>\n" \
+ " <dict>\n" \
+ " <key>PATH</key>\n" \
+ " <string>%s</string>\n" \
+ " </dict>\n" \
+ " <key>RunAtLoad</key>\n" \
+ " <true/>\n" \
+ " <key>KeepAlive</key>\n" \
+ " <true/>\n" \
+ " <key>StandardOutPath</key>\n" \
+ " <string>/tmp/skhd_%s.out.log</string>\n" \
+ " <key>StandardErrorPath</key>\n" \
+ " <string>/tmp/skhd_%s.err.log</string>\n" \
+ " <key>ThrottleInterval</key>\n" \
+ " <integer>30</integer>\n" \
+ " <key>ProcessType</key>\n" \
+ " <string>Interactive</string>\n" \
+ " <key>Nice</key>\n" \
+ " <integer>-20</integer>\n" \
+ "</dict>\n" \
+ "</plist>"
+
+static bool file_exists(char *filename);
+
+static int safe_exec(char *const argv[])
+{
+ pid_t pid;
+ int status = posix_spawn(&pid, argv[0], NULL, NULL, argv, NULL);
+ if (status) return 1;
+
+ while ((waitpid(pid, &status, 0) == -1) && (errno == EINTR)) {
+ usleep(1000);
+ }
+
+ if (WIFSIGNALED(status)) {
+ return 1;
+ } else if (WIFSTOPPED(status)) {
+ return 1;
+ } else {
+ return WEXITSTATUS(status);
+ }
+}
+
+static void populate_plist_path(char *skhd_plist_path, int size)
+{
+ char *user = getenv("USER");
+ if (!user) {
+ error("skhd: 'env USER' not set! abort..\n");
+ }
+
+ snprintf(skhd_plist_path, size, _PATH_SKHD_PLIST, user);
+}
+
+static void populate_plist(char *skhd_plist, int size)
+{
+ char *user = getenv("USER");
+ if (!user) {
+ error("skhd: 'env USER' not set! abort..\n");
+ }
+
+ char *path_env = getenv("PATH");
+ if (!path_env) {
+ error("skhd: 'env PATH' not set! abort..\n");
+ }
+
+ char exe_path[4096];
+ unsigned int exe_path_size = sizeof(exe_path);
+ if (_NSGetExecutablePath(exe_path, &exe_path_size) < 0) {
+ error("skhd: unable to retrieve path of executable! abort..\n");
+ }
+
+ snprintf(skhd_plist, size, _SKHD_PLIST, exe_path, path_env, user, user);
+}
+
+static int service_install_internal(char *skhd_plist_path)
+{
+ char skhd_plist[4096];
+ populate_plist(skhd_plist, sizeof(skhd_plist));
+
+ FILE *handle = fopen(skhd_plist_path, "w");
+ if (!handle) return 1;
+
+ size_t bytes = fwrite(skhd_plist, strlen(skhd_plist), 1, handle);
+ int result = bytes == 1 ? 0 : 1;
+ fclose(handle);
+
+ return result;
+}
+
+static int service_install(void)
+{
+ char skhd_plist_path[MAXLEN];
+ populate_plist_path(skhd_plist_path, sizeof(skhd_plist_path));
+
+ if (file_exists(skhd_plist_path)) {
+ error("skhd: service file '%s' is already installed! abort..\n", skhd_plist_path);
+ }
+
+ return service_install_internal(skhd_plist_path);
+}
+
+static int service_uninstall(void)
+{
+ char skhd_plist_path[MAXLEN];
+ populate_plist_path(skhd_plist_path, sizeof(skhd_plist_path));
+
+ if (!file_exists(skhd_plist_path)) {
+ error("skhd: service file '%s' is not installed! abort..\n", skhd_plist_path);
+ }
+
+ return unlink(skhd_plist_path) == 0 ? 0 : 1;
+}
+
+static int service_start(void)
+{
+ char skhd_plist_path[MAXLEN];
+ populate_plist_path(skhd_plist_path, sizeof(skhd_plist_path));
+
+ if (!file_exists(skhd_plist_path)) {
+ warn("skhd: service file '%s' is not installed! attempting installation..\n", skhd_plist_path);
+
+ int result = service_install_internal(skhd_plist_path);
+ if (result) {
+ error("skhd: service file '%s' could not be installed! abort..\n", skhd_plist_path);
+ }
+ }
+
+ const char *const args[] = { _PATH_LAUNCHCTL, "load", "-w", skhd_plist_path, NULL };
+ return safe_exec((char *const*)args);
+}
+
+static int service_restart(void)
+{
+ char skhd_plist_path[MAXLEN];
+ populate_plist_path(skhd_plist_path, sizeof(skhd_plist_path));
+
+ if (!file_exists(skhd_plist_path)) {
+ error("skhd: service file '%s' is not installed! abort..\n", skhd_plist_path);
+ }
+
+ char skhd_service_id[MAXLEN];
+ snprintf(skhd_service_id, sizeof(skhd_service_id), "gui/%d/%s", getuid(), _NAME_SKHD_PLIST);
+
+ const char *const args[] = { _PATH_LAUNCHCTL, "kickstart", "-k", skhd_service_id, NULL };
+ return safe_exec((char *const*)args);
+}
+
+static int service_stop(void)
+{
+ char skhd_plist_path[MAXLEN];
+ populate_plist_path(skhd_plist_path, sizeof(skhd_plist_path));
+
+ if (!file_exists(skhd_plist_path)) {
+ error("skhd: service file '%s' is not installed! abort..\n", skhd_plist_path);
+ }
+
+ const char *const args[] = { _PATH_LAUNCHCTL, "unload", "-w", skhd_plist_path, NULL };
+ return safe_exec((char *const*)args);
+}
+
+#endif
diff --git a/src/skhd.c b/src/skhd.c
index 3525269..ee2da62 100644
--- a/src/skhd.c
+++ b/src/skhd.c
@@ -27,6 +27,7 @@
#include "parse.h"
#include "hotkey.h"
#include "synthesize.h"
+#include "service.h"
#include "hotload.c"
#include "event_tap.c"
@@ -47,28 +48,34 @@ extern bool CGSIsSecureEventInputSet(void);
typedef GLOBAL_CONNECTION_CALLBACK(global_connection_callback);
extern CGError CGSRegisterNotifyProc(void *handler, uint32_t type, void *context);
-#define internal static
-#define global static
-
#define SKHD_CONFIG_FILE ".skhdrc"
#define SKHD_PIDFILE_FMT "/tmp/skhd_%s.pid"
-global unsigned major_version = 0;
-global unsigned minor_version = 3;
-global unsigned patch_version = 5;
+#define VERSION_OPT_LONG "--version"
+#define VERSION_OPT_SHRT "-v"
+
+#define SERVICE_INSTALL_OPT "--install-service"
+#define SERVICE_UNINSTALL_OPT "--uninstall-service"
+#define SERVICE_START_OPT "--start-service"
+#define SERVICE_RESTART_OPT "--restart-service"
+#define SERVICE_STOP_OPT "--stop-service"
+
+#define MAJOR 0
+#define MINOR 3
+#define PATCH 6
-global struct carbon_event carbon;
-global struct event_tap event_tap;
-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[4096];
+static struct carbon_event carbon;
+static struct event_tap event_tap;
+static struct hotloader hotloader;
+static struct mode *current_mode;
+static struct table mode_map;
+static struct table blacklst;
+static bool thwart_hotloader;
+static char config_file[4096];
-internal HOTLOADER_CALLBACK(config_handler);
+static HOTLOADER_CALLBACK(config_handler);
-internal void
+static void
parse_config_helper(char *absolutepath)
{
struct parser parser;
@@ -100,7 +107,7 @@ parse_config_helper(char *absolutepath)
current_mode = table_find(&mode_map, "default");
}
-internal HOTLOADER_CALLBACK(config_handler)
+static HOTLOADER_CALLBACK(config_handler)
{
BEGIN_TIMED_BLOCK("hotload_config");
debug("skhd: config-file has been modified.. reloading config\n");
@@ -110,7 +117,7 @@ internal HOTLOADER_CALLBACK(config_handler)
END_TIMED_BLOCK();
}
-internal CF_NOTIFICATION_CALLBACK(keymap_handler)
+static CF_NOTIFICATION_CALLBACK(keymap_handler)
{
BEGIN_TIMED_BLOCK("keymap_changed");
if (initialize_keycode_map()) {
@@ -122,7 +129,7 @@ internal CF_NOTIFICATION_CALLBACK(keymap_handler)
END_TIMED_BLOCK();
}
-internal EVENT_TAP_CALLBACK(key_observer_handler)
+static EVENT_TAP_CALLBACK(key_observer_handler)
{
switch (type) {
case kCGEventTapDisabledByTimeout:
@@ -152,7 +159,7 @@ internal EVENT_TAP_CALLBACK(key_observer_handler)
return event;
}
-internal EVENT_TAP_CALLBACK(key_handler)
+static EVENT_TAP_CALLBACK(key_handler)
{
switch (type) {
case kCGEventTapDisabledByTimeout:
@@ -186,8 +193,7 @@ internal EVENT_TAP_CALLBACK(key_handler)
return event;
}
-internal void
-sigusr1_handler(int signal)
+static void sigusr1_handler(int signal)
{
BEGIN_TIMED_BLOCK("sigusr1");
debug("skhd: SIGUSR1 received.. reloading config\n");
@@ -197,8 +203,7 @@ sigusr1_handler(int signal)
END_TIMED_BLOCK();
}
-internal pid_t
-read_pid_file(void)
+static pid_t read_pid_file(void)
{
char pid_file[255] = {};
pid_t pid = 0;
@@ -225,8 +230,7 @@ read_pid_file(void)
return pid;
}
-internal void
-create_pid_file(void)
+static void create_pid_file(void)
{
char pid_file[255] = {};
pid_t pid = getpid();
@@ -263,15 +267,44 @@ create_pid_file(void)
debug("skhd: successfully created pid-file..\n");
}
-internal bool
-parse_arguments(int argc, char **argv)
+static inline bool string_equals(const char *a, const char *b)
+{
+ return a && b && strcmp(a, b) == 0;
+}
+
+static bool parse_arguments(int argc, char **argv)
{
+ if ((string_equals(argv[1], VERSION_OPT_LONG)) ||
+ (string_equals(argv[1], VERSION_OPT_SHRT))) {
+ fprintf(stdout, "skhd-v%d.%d.%d\n", MAJOR, MINOR, PATCH);
+ exit(EXIT_SUCCESS);
+ }
+
+ if (string_equals(argv[1], SERVICE_INSTALL_OPT)) {
+ exit(service_install());
+ }
+
+ if (string_equals(argv[1], SERVICE_UNINSTALL_OPT)) {
+ exit(service_uninstall());
+ }
+
+ if (string_equals(argv[1], SERVICE_START_OPT)) {
+ exit(service_start());
+ }
+
+ if (string_equals(argv[1], SERVICE_RESTART_OPT)) {
+ exit(service_restart());
+ }
+
+ if (string_equals(argv[1], SERVICE_STOP_OPT)) {
+ exit(service_stop());
+ }
+
int option;
const char *short_option = "VPvc:k:t:rho";
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' },
@@ -289,10 +322,6 @@ parse_arguments(int argc, char **argv)
case 'P': {
profile = true;
} break;
- case 'v': {
- printf("skhd version %d.%d.%d\n", major_version, minor_version, patch_version);
- return true;
- } break;
case 'c': {
snprintf(config_file, sizeof(config_file), "%s", optarg);
} break;
@@ -324,8 +353,7 @@ parse_arguments(int argc, char **argv)
return false;
}
-internal bool
-check_privileges(void)
+static bool check_privileges(void)
{
bool result;
const void *keys[] = { kAXTrustedCheckOptionPrompt };
@@ -343,8 +371,7 @@ check_privileges(void)
return result;
}
-internal inline bool
-file_exists(char *filename)
+static inline bool file_exists(char *filename)
{
struct stat buffer;
@@ -359,8 +386,7 @@ file_exists(char *filename)
return true;
}
-internal bool
-get_config_file(char *restrict filename, char *restrict buffer, int buffer_size)
+static bool get_config_file(char *restrict filename, char *restrict buffer, int buffer_size)
{
char *xdg_home = getenv("XDG_CONFIG_HOME");
if (xdg_home && *xdg_home) {
@@ -378,8 +404,7 @@ get_config_file(char *restrict filename, char *restrict buffer, int buffer_size)
return file_exists(buffer);
}
-internal char *
-secure_keyboard_entry_process_info(pid_t *pid)
+static char *secure_keyboard_entry_process_info(pid_t *pid)
{
char *process_name = NULL;
@@ -396,8 +421,7 @@ secure_keyboard_entry_process_info(pid_t *pid)
return process_name;
}
-internal void
-dump_secure_keyboard_entry_process_info(void)
+static void dump_secure_keyboard_entry_process_info(void)
{
pid_t pid;
char *process_name = secure_keyboard_entry_process_info(&pid);
diff --git a/src/synthesize.c b/src/synthesize.c
index 6eddd6f..0279f3d 100644
--- a/src/synthesize.c
+++ b/src/synthesize.c
@@ -5,18 +5,16 @@
#include "parse.h"
#include "hotkey.h"
-#define internal static
-
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated"
-internal inline void
+static inline void
create_and_post_keyevent(uint16_t key, bool pressed)
{
CGPostKeyboardEvent((CGCharCode)0, (CGKeyCode)key, pressed);
}
-internal inline void
+static inline void
synthesize_modifiers(struct hotkey *hotkey, bool pressed)
{
if (has_flags(hotkey, Hotkey_Flag_Alt)) {
diff --git a/src/timing.h b/src/timing.h
index b48028e..7b7aa46 100644
--- a/src/timing.h
+++ b/src/timing.h
@@ -19,10 +19,7 @@
#define END_TIMED_BLOCK() \
if (profile) end_timing(&timing)
-#define internal static
-#define global static
-
-global bool profile;
+static bool profile;
struct timing_info
{
@@ -35,7 +32,7 @@ struct timing_info
void begin_timing(struct timing_info *timing, char *note);
void end_timing(struct timing_info *timing);
-internal inline uint64_t
+static inline uint64_t
macos_get_wall_clock(void)
{
return mach_absolute_time();
@@ -51,14 +48,14 @@ static inline uint64_t macos_get_nanoseconds_elapsed(uint64_t start, uint64_t en
}
#pragma clang diagnostic pop
-internal inline double
+static inline double
macos_get_milliseconds_elapsed(uint64_t start, uint64_t end)
{
uint64_t ns = macos_get_nanoseconds_elapsed(start, end);
return (double)(ns / 1000000.0);
}
-internal inline double
+static inline double
macos_get_seconds_elapsed(uint64_t start, uint64_t end)
{
uint64_t ns = macos_get_nanoseconds_elapsed(start, end);
@@ -80,7 +77,4 @@ void end_timing(struct timing_info *timing) {
}
}
-#undef internal
-#undef global
-
#endif
diff --git a/src/tokenize.c b/src/tokenize.c
index eaf0e3a..f379a9f 100644
--- a/src/tokenize.c
+++ b/src/tokenize.c
@@ -1,7 +1,6 @@
#include "tokenize.h"
#include <ctype.h>
-#define internal static
#define array_count(a) (sizeof((a)) / sizeof(*(a)))
int token_equals(struct token token, const char *match)
@@ -15,7 +14,7 @@ int token_equals(struct token token, const char *match)
return (*at == 0);
}
-internal void
+static void
advance(struct tokenizer *tokenizer)
{
if (*tokenizer->at == '\n') {
@@ -26,7 +25,7 @@ advance(struct tokenizer *tokenizer)
++tokenizer->at;
}
-internal void
+static void
eat_whitespace(struct tokenizer *tokenizer)
{
while (*tokenizer->at && isspace(*tokenizer->at)) {
@@ -34,7 +33,7 @@ eat_whitespace(struct tokenizer *tokenizer)
}
}
-internal void
+static void
eat_comment(struct tokenizer *tokenizer)
{
while (*tokenizer->at && *tokenizer->at != '\n') {
@@ -42,7 +41,7 @@ eat_comment(struct tokenizer *tokenizer)
}
}
-internal void
+static void
eat_command(struct tokenizer *tokenizer)
{
while (*tokenizer->at && *tokenizer->at != '\n') {
@@ -53,7 +52,7 @@ eat_command(struct tokenizer *tokenizer)
}
}
-internal void
+static void
eat_hex(struct tokenizer *tokenizer)
{
while ((*tokenizer->at) &&
@@ -63,7 +62,7 @@ eat_hex(struct tokenizer *tokenizer)
}
}
-internal void
+static void
eat_string(struct tokenizer *tokenizer)
{
/*
@@ -79,7 +78,7 @@ eat_string(struct tokenizer *tokenizer)
}
}
-internal void
+static void
eat_option(struct tokenizer *tokenizer)
{
while (*tokenizer->at && !isspace(*tokenizer->at)) {
@@ -87,13 +86,13 @@ eat_option(struct tokenizer *tokenizer)
}
}
-internal inline bool
+static inline bool
isidentifier(char c)
{
return isalpha(c) || c == '_';
}
-internal void
+static void
eat_identifier(struct tokenizer *tokenizer)
{
while ((*tokenizer->at) && isidentifier(*tokenizer->at)) {
@@ -105,7 +104,7 @@ eat_identifier(struct tokenizer *tokenizer)
}
}
-internal enum token_type
+static enum token_type
resolve_identifier_type(struct token token)
{
if (token.length == 1) {
diff --git a/src/tokenize.h b/src/tokenize.h
index 52d76fc..13d7001 100644
--- a/src/tokenize.h
+++ b/src/tokenize.h
@@ -1,9 +1,7 @@
#ifndef SKHD_TOKENIZE_H
#define SKHD_TOKENIZE_H
-#define global static
-
-global const char *modifier_flags_str[] =
+static const char *modifier_flags_str[] =
{
"alt", "lalt", "ralt",
"shift", "lshift", "rshift",
@@ -12,7 +10,7 @@ global const char *modifier_flags_str[] =
"fn", "hyper", "meh",
};
-global const char *literal_keycode_str[] =
+static const char *literal_keycode_str[] =
{
"return", "tab", "space",
"backspace", "escape", "delete",
@@ -33,8 +31,6 @@ global const char *literal_keycode_str[] =
"brightness_down", "illumination_up", "illumination_down"
};
-#undef global
-
enum token_type
{
Token_Identifier,