diff --git a/doc/man.md.j2 b/doc/man.md.j2 index 030cb3151..d564e89b8 100644 --- a/doc/man.md.j2 +++ b/doc/man.md.j2 @@ -160,6 +160,11 @@ file. : Update interval. +**-U \| \--unique** + +: Conky won't start if another Conky process is already running. Implemented + only for Linux. + **-v \| -V \| \--version** : Prints version, build information and general info. Exits after diff --git a/src/conky.cc b/src/conky.cc index 7a59b60d5..44399cc54 100644 --- a/src/conky.cc +++ b/src/conky.cc @@ -2107,6 +2107,9 @@ void set_current_config() { /* : means that character before that takes an argument */ const char *getopt_string = "vVqdDSs:t:u:i:hc:p:" +#if defined(__linux__) + "U" +#endif #ifdef BUILD_X11 "x:y:w:a:X:m:f:" #ifdef OWN_WINDOW @@ -2136,7 +2139,12 @@ 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'}, +#if defined(__linux__) + {"unique", 0, nullptr, 'U'}, +#endif /* Linux */ + {nullptr, 0, nullptr, 0} +}; void setup_inotify() { #ifdef HAVE_SYS_INOTIFY_H diff --git a/src/linux.cc b/src/linux.cc index 5a2a822f7..24bc40506 100644 --- a/src/linux.cc +++ b/src/linux.cc @@ -3147,3 +3147,45 @@ void get_top_info(void) { calc_io_each(); /* percentage of I/O for each task */ #endif /* BUILD_IOSTATS */ } + +/****************************************** + * Check if more than one conky process * + * is running * + ******************************************/ + +bool is_conky_already_running(void) { + DIR *dir; + struct dirent *ent; + char buf[512]; + int instances = 0; + + if (!(dir = opendir("/proc"))) { + NORM_ERR("can't open /proc: %s\n", strerror(errno)); + return false; + } + + while ((ent = readdir(dir)) != NULL) { + char *endptr = ent->d_name; + long lpid = strtol(ent->d_name, &endptr, 10); + if (*endptr != '\0') { + continue; + } + + snprintf(buf, sizeof(buf), "/proc/%ld/stat", lpid); + FILE *fp = fopen(buf, "r"); + if (!fp) { + continue; + } + + if (fgets(buf, sizeof(buf), fp) != NULL) { + char *conky = strstr(buf, "(conky)"); + if (conky) { + instances++; + } + } + fclose(fp); + } + + closedir(dir); + return instances > 1; +} diff --git a/src/linux.h b/src/linux.h index 91027f233..f5b9f4097 100644 --- a/src/linux.h +++ b/src/linux.h @@ -58,6 +58,8 @@ int update_stat(void); void print_distribution(struct text_object *, char *, unsigned int); +bool is_conky_already_running(void); + extern char e_iface[64]; extern char interfaces_arr[MAX_NET_INTERFACES][64]; diff --git a/src/main.cc b/src/main.cc index 8e937c61e..327ef59fd 100644 --- a/src/main.cc +++ b/src/main.cc @@ -44,6 +44,10 @@ #include "ccurl_thread.h" #endif /* BUILD_CURL */ +#if defined(__linux__) +#include "linux.h" +#endif /* Linux */ + #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) #include "freebsd.h" #endif /* FreeBSD */ @@ -268,8 +272,11 @@ 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", - prog_name); + "before doing anything\n" +#if defined(__linux__) + " -U, --unique only one conky process can be created\n" +#endif /* Linux */ + , prog_name); } inline void reset_optind() { @@ -293,6 +300,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 +358,23 @@ int main(int argc, char **argv) { window.window = strtol(optarg, nullptr, 0); break; #endif /* BUILD_X11 */ - +#if defined(__linux__) + case 'U': + unique_process = true; + break; +#endif /* Linux */ case '?': return EXIT_FAILURE; } } +#if defined(__linux__) + if (unique_process && is_conky_already_running()) { + NORM_ERR("already running"); + return 0; + } +#endif /* Linux */ + try { set_current_config();