From 0a5530a670f3ebdf8a35441a2e9e32651dd8a7e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=B3th=20J=C3=A1nos?= Date: Wed, 2 Oct 2024 11:59:23 +0200 Subject: [PATCH] Implement `-U`. If this argument is provided Conky won't start if another Conky process is already running. --- doc/man.md.j2 | 4 ++++ src/conky.cc | 5 +++-- src/main.cc | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 64 insertions(+), 3 deletions(-) diff --git a/doc/man.md.j2 b/doc/man.md.j2 index 030cb315..cbb86afb 100644 --- a/doc/man.md.j2 +++ b/doc/man.md.j2 @@ -160,6 +160,10 @@ file. : Update interval. +**-U \| \--unique** + +: Conky won't start if another Conky process is already running. + **-v \| -V \| \--version** : Prints version, build information and general info. Exits after diff --git a/src/conky.cc b/src/conky.cc index 7a59b60d..a9a4abef 100644 --- a/src/conky.cc +++ b/src/conky.cc @@ -2106,7 +2106,7 @@ void set_current_config() { /* : means that character before that takes an argument */ const char *getopt_string = - "vVqdDSs:t:u:i:hc:p:" + "vVqdDSs:t:u:i:hc:p:U" #ifdef BUILD_X11 "x:y:w:a:X:m:f:" #ifdef OWN_WINDOW @@ -2136,7 +2136,8 @@ const struct option longopts[] = { {"double-buffer", 0, nullptr, 'b'}, {"window-id", 1, nullptr, 'w'}, #endif /* BUILD_X11 */ {"text", 1, nullptr, 't'}, {"interval", 1, nullptr, 'u'}, - {"pause", 1, nullptr, 'p'}, {nullptr, 0, nullptr, 0}}; + {"pause", 1, nullptr, 'p'}, {"unique", 0, nullptr, 'U'}, + {nullptr, 0, nullptr, 0}}; void setup_inotify() { #ifdef HAVE_SYS_INOTIFY_H diff --git a/src/main.cc b/src/main.cc index 8e937c61..92ce7fd0 100644 --- a/src/main.cc +++ b/src/main.cc @@ -36,6 +36,8 @@ #include "display-output.hh" #include "lua-config.hh" +#include + #ifdef BUILD_X11 #include "x11.h" #endif /* BUILD_X11 */ @@ -268,10 +270,54 @@ static void print_help(const char *prog_name) { " -i COUNT number of times to update " PACKAGE_NAME " (and quit)\n" " -p, --pause=SECS pause for SECS seconds at startup " - "before doing anything\n", + "before doing anything\n" + " -U, --unique only one conky process can be created\n", prog_name); } +static bool is_conky_already_running() { + DIR* dir; + struct dirent* ent; + char* endptr; + char buf[512]; + + const size_t len_conky = 5; // "conky" + int instances = 0; + + if (!(dir = opendir("/proc"))) { + NORM_ERR("can't open /proc: %s\n", strerror(errno)); + return false; + } + + while ((ent = readdir(dir)) != NULL) { + long lpid = strtol(ent->d_name, &endptr, 10); + if (*endptr != '\0') { + continue; + } + + snprintf(buf, sizeof(buf), "/proc/%ld/cmdline", lpid); + FILE* fp = fopen(buf, "r"); + if (fp) { + if (fgets(buf, sizeof(buf), fp) != NULL) { + const char* name = strtok(buf, " "); + const size_t len = strlen(name); + + if (len >= len_conky) { + name = name + len - len_conky; + } + + if (!strcmp(name, "conky")) { + instances++; + } + } + fclose(fp); + } + } + + closedir(dir); + return instances > 1; +} + inline void reset_optind() { #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \ defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) @@ -293,6 +339,8 @@ int main(int argc, char **argv) { g_sighup_pending = 0; g_sigusr2_pending = 0; + bool unique_process = false; + #ifdef BUILD_CURL struct curl_global_initializer { curl_global_initializer() { @@ -349,12 +397,20 @@ int main(int argc, char **argv) { window.window = strtol(optarg, nullptr, 0); break; #endif /* BUILD_X11 */ + case 'U': + unique_process = true; + break; case '?': return EXIT_FAILURE; } } + if (unique_process && is_conky_already_running()) { + NORM_ERR("already running"); + return 0; + } + try { set_current_config();