diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lock.c | 71 | ||||
-rw-r--r-- | src/lock.h | 8 | ||||
-rw-r--r-- | src/main.c | 6 |
3 files changed, 85 insertions, 0 deletions
diff --git a/src/lock.c b/src/lock.c new file mode 100644 index 0000000..133d327 --- /dev/null +++ b/src/lock.c @@ -0,0 +1,71 @@ +#include <errno.h> +#include <fcntl.h> +#include <stdbool.h> +#include <stdio.h> +#include <string.h> +#include <sys/file.h> +#include "log.h" +#include "xmalloc.h" + +static const char *default_cache_dir = ".cache/"; +static const char *lock_filename = "tofi.lock"; + +[[nodiscard("memory leaked")]] +static char *get_lock_path() { + char *lock_name = NULL; + const char *runtime_path = getenv("XDG_RUNTIME_DIR"); + if (runtime_path == NULL) { + runtime_path = getenv("XDG_CACHE_HOME"); + } + if (runtime_path == NULL) { + const char *home = getenv("HOME"); + if (home == NULL) { + log_error("Couldn't retrieve HOME from environment.\n"); + return NULL; + } + size_t len = strlen(home) + 1 + + strlen(default_cache_dir) + 1 + + strlen(lock_filename) + 1; + lock_name = xmalloc(len); + snprintf( + lock_name, + len, + "%s/%s/%s", + home, + default_cache_dir, + lock_filename); + } else { + size_t len = strlen(runtime_path) + 1 + + strlen(lock_filename) + 1; + lock_name = xmalloc(len); + snprintf( + lock_name, + len, + "%s/%s", + runtime_path, + lock_filename); + } + return lock_name; +} + +bool lock_check(void) +{ + bool ret = false; + char *filename = get_lock_path(); + errno = 0; + int fd = open(filename, O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR); + if (fd == -1) { + log_error("Failed to open lock file %s: %s.\n", filename, strerror(errno)); + } else if (flock(fd, LOCK_EX | LOCK_NB) == -1) { + if (errno == EWOULDBLOCK) { + /* + * We can't lock the file because another tofi process + * already has. + */ + ret = true; + } + } + + free(filename); + return ret; +} diff --git a/src/lock.h b/src/lock.h new file mode 100644 index 0000000..1ce402e --- /dev/null +++ b/src/lock.h @@ -0,0 +1,8 @@ +#ifndef LOCK_H +#define LOCK_H + +#include <stdbool.h> + +bool lock_check(void); + +#endif /* LOCK_H */ @@ -22,6 +22,7 @@ #include "input.h" #include "log.h" #include "nelem.h" +#include "lock.h" #include "shm.h" #include "string_vec.h" #include "string_vec.h" @@ -905,6 +906,11 @@ int main(int argc, char *argv[]) parse_args(&tofi, argc, argv); + if (lock_check()) { + log_error("Another instance of tofi is already running.\n"); + exit(EXIT_FAILURE); + } + /* * Initial Wayland & XKB setup. * The first thing to do is connect a listener to the global registry, |