Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] config reload mechanism #1350

Merged
merged 18 commits into from
Jul 15, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions completions/_dunstctl.zshcomp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ case $state in
'set-pause-level:Set the pause level'
'rule:Enable or disable a rule by its name'
'rules:Displays configured rules'
'reload:Reload the settings of the running instance, optionally with specific configuration files'
'debug:Print debugging information'
'help:Show help'
)
Expand Down
2 changes: 1 addition & 1 deletion completions/dunstctl.bashcomp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ _dunstctl() {
local opts cur prev
_get_comp_words_by_ref cur prev
COMPREPLY=()
opts='action close close-all context count debug help history history-clear history-pop history-rm is-paused rule rules set-paused get-pause-level set-pause-level'
opts='action close close-all context count debug help history history-clear history-pop history-rm is-paused rule rules set-paused get-pause-level set-pause-level reload'

case "$prev" in
count) COMPREPLY=( $( compgen -W 'displayed history waiting' -- "$cur" ) )
Expand Down
3 changes: 2 additions & 1 deletion completions/dunstctl.fishcomp
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,12 @@ complete -c dunstctl -f -n __fish_use_subcommand -a get-pause-level -d 'Get the
complete -c dunstctl -f -n __fish_use_subcommand -a set-pause-level -d 'Set the pause level'
complete -c dunstctl -f -n __fish_use_subcommand -a rules -d 'Displays configured rules (optionally in JSON)'
complete -c dunstctl -f -n __fish_use_subcommand -a rule -d 'Enable or disable a rule by its name'
complete -c dunstctl -f -n __fish_use_subcommand -a reload -d 'Reload the settings of the running instance, optionally with specific configuration files'
complete -c dunstctl -f -n __fish_use_subcommand -a debug -d 'Print debugging information'
complete -c dunstctl -f -n __fish_use_subcommand -a help -d 'Show help'

# command specific arguments
complete -c dunstctl -x -n '__fish_seen_subcommand_from action close close-all context history history-clear is-paused get-pause-level set-pause-level debug help'
complete -c dunstctl -x -n '__fish_seen_subcommand_from action close close-all context history history-clear is-paused get-pause-level set-pause-level reload debug help'
bynect marked this conversation as resolved.
Show resolved Hide resolved
complete -c dunstctl -x -n '__fish_seen_subcommand_from count' -a 'displayed history waiting'
complete -c dunstctl -x -n '__fish_seen_subcommand_from history-pop history-rm' -a '(__fish_dunstctl_info history id appname)'
complete -c dunstctl -x -n '__fish_seen_subcommand_from set-paused' -a 'true false toggle'
Expand Down
7 changes: 7 additions & 0 deletions docs/dunstctl.pod
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,13 @@ to temporarily activate or deactivate specific rules.

Exports all currently configured rules (optionally JSON formatted).

=item B<reload> [dunstrc ...]

Reload the settings of the running dunst instance. You can optionally specify
which configuration files to use. Otherwise, the previous one will be used.
bynect marked this conversation as resolved.
Show resolved Hide resolved
When dunst is reloaded all the rules are reapplied, however previosly modified
notifications will not be reverted back.

=item B<debug>

Tries to contact dunst and checks for common faults between dunstctl and dunst.
Expand Down
9 changes: 8 additions & 1 deletion dunstctl
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ show_help() {
context menu of the notification at the
given position
close [ID] Close the last notification or the
notification with given ID.
notification with given ID
close-all Close all the notifications
context Open context menu
count [displayed|history|waiting] Show the number of notifications
Expand All @@ -37,6 +37,9 @@ show_help() {
rule name enable|disable|toggle Enable or disable a rule by its name
rules [--json] Displays configured rules (optionally
in JSON)
reload [dunstrc ...] Reload the settings of the running
bynect marked this conversation as resolved.
Show resolved Hide resolved
instance, optionally with specific
configuration files
debug Print debugging information
help Show help
EOH
Expand Down Expand Up @@ -206,6 +209,10 @@ case "${1:-}" in
busctl --user --json=pretty --no-pager call org.freedesktop.Notifications /org/freedesktop/Notifications org.dunstproject.cmd0 NotificationListHistory 2>/dev/null \
|| die "Dunst is not running."
;;
"reload")
shift
method_call "${DBUS_IFAC_DUNST}.ConfigReload" "array:string:$(IFS=','; echo "$*")" >/dev/null
;;
"")
die "dunstctl: No command specified. Please consult the usage."
;;
Expand Down
2 changes: 1 addition & 1 deletion main.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "src/dunst.h"

int main(int argc, char *argv[])
int main(int argc, const char *argv[])
bynect marked this conversation as resolved.
Show resolved Hide resolved
{
return dunst_main(argc, argv);
}
Expand Down
22 changes: 21 additions & 1 deletion src/dbus.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ static const char *introspection_xml =
" <method name=\"RuleList\">"
" <arg direction=\"out\" name=\"rules\" type=\"aa{sv}\"/>"
" </method>"
" <method name=\"ConfigReload\">"
" <arg direction=\"in\" name=\"configs\" type=\"as\"/>"
" </method>"
" <method name=\"Ping\" />"

" <property name=\"paused\" type=\"b\" access=\"readwrite\">"
Expand Down Expand Up @@ -193,8 +196,12 @@ DBUS_METHOD(dunst_NotificationRemoveFromHistory);
DBUS_METHOD(dunst_NotificationShow);
DBUS_METHOD(dunst_RuleEnable);
DBUS_METHOD(dunst_RuleList);
DBUS_METHOD(dunst_ConfigReload);
DBUS_METHOD(dunst_Ping);

// NOTE: Keep the names sorted alphabetically
static struct dbus_method methods_dunst[] = {
{"ConfigReload", dbus_cb_dunst_ConfigReload},
{"ContextMenuCall", dbus_cb_dunst_ContextMenuCall},
{"NotificationAction", dbus_cb_dunst_NotificationAction},
{"NotificationClearHistory", dbus_cb_dunst_NotificationClearHistory},
Expand Down Expand Up @@ -603,6 +610,19 @@ static void dbus_cb_dunst_RuleEnable(GDBusConnection *connection,
g_dbus_connection_flush(connection, NULL, NULL, NULL);
}

static void dbus_cb_dunst_ConfigReload(GDBusConnection *connection,
const gchar *sender,
GVariant *parameters,
GDBusMethodInvocation *invocation)
{
gchar **configs = NULL;
g_variant_get(parameters, "(^as)", &configs);
reload(configs);

g_dbus_method_invocation_return_value(invocation, NULL);
g_dbus_connection_flush(connection, NULL, NULL, NULL);
}

/* Just a simple Ping command to give the ability to dunstctl to test for the existence of this interface
* Any other way requires parsing the XML of the Introspection or other foo. Just calling the Ping on an old dunst version will fail. */
static void dbus_cb_dunst_Ping(GDBusConnection *connection,
Expand Down Expand Up @@ -1083,7 +1103,7 @@ gboolean dbus_cb_dunst_Properties_Set(GDBusConnection *connection,
int targetPauseLevel = -1;
if (STR_EQ(property_name, "paused")) {
if (g_variant_get_boolean(value)) {
targetPauseLevel = MAX_PAUSE_LEVEL;
targetPauseLevel = MAX_PAUSE_LEVEL;
} else {
targetPauseLevel = 0;
}
Expand Down
1 change: 1 addition & 0 deletions src/draw.c
Original file line number Diff line number Diff line change
Expand Up @@ -974,6 +974,7 @@ void draw(void)

void draw_deinit(void)
{
pango_font_description_free(pango_fdesc);
output->win_destroy(win);
output->deinit();
if (settings.enable_recursive_icon_lookup)
Expand Down
44 changes: 38 additions & 6 deletions src/dunst.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ GMainLoop *mainloop = NULL;

static struct dunst_status status;
static bool setup_done = false;
static char **config_paths = NULL;

/* see dunst.h */
void dunst_status(const enum dunst_status_field field,
Expand Down Expand Up @@ -205,11 +206,36 @@ static void teardown(void)
queues_teardown();

draw_deinit();

g_strfreev(config_paths);
}

int dunst_main(int argc, char *argv[])
void reload(char **const configs)
{
guint length = g_strv_length(configs);
LOG_M("Reloading settings (with the %s files)", length != 0 ? "new" : "old");

if (length != 0) {
g_strfreev(config_paths);
config_paths = configs;
}

pause_signal(NULL);

setup_done = false;
draw_deinit();

load_settings(config_paths);
draw_setup();
setup_done = true;

queues_reapply_all_rules();

unpause_signal(NULL);
}

int dunst_main(int argc, const char *argv[])
{
dunst_status_int(S_PAUSE_LEVEL, 0);
dunst_status(S_IDLE, false);

Expand All @@ -229,10 +255,16 @@ int dunst_main(int argc, char *argv[])
log_set_level_from_string(verbosity);
g_free(verbosity);

char *cmdline_config_path;
cmdline_config_path =
cmdline_get_string("-conf/-config", NULL,
"Path to configuration file");
cmdline_usage_append("-conf/-config", "string", "Path to configuration file");

int start = 1, count = 1;
while (cmdline_get_string_offset("-conf/-config", NULL, start, &start))
count++;

config_paths = g_malloc0(sizeof(char *) * count);
bynect marked this conversation as resolved.
Show resolved Hide resolved
start = 1, count = 0;

while ((config_paths[count++] = cmdline_get_string_offset("-conf/-config", NULL, start, &start)));
bynect marked this conversation as resolved.
Show resolved Hide resolved

settings.print_notifications = cmdline_get_bool("-print/--print", false, "Print notifications to stdout");

Expand All @@ -244,7 +276,7 @@ int dunst_main(int argc, char *argv[])
usage(EXIT_SUCCESS);
}

load_settings(cmdline_config_path);
load_settings(config_paths);
int dbus_owner_id = dbus_init();

mainloop = g_main_loop_new(NULL, FALSE);
Expand Down
3 changes: 2 additions & 1 deletion src/dunst.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ void dunst_status_int(const enum dunst_status_field field,
struct dunst_status dunst_status_get(void);

void wake_up(void);
void reload(char **const configs);

int dunst_main(int argc, char *argv[]);
int dunst_main(int argc, const char *argv[]);

void usage(int exit_status);
void print_version(void);
Expand Down
3 changes: 2 additions & 1 deletion src/log.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@

#include "utils.h"

static GLogLevelFlags log_level = G_LOG_LEVEL_WARNING;
// NOTE: Keep updated with the dunst manual
static GLogLevelFlags log_level = G_LOG_LEVEL_MESSAGE;

/* see log.h */
static const char *log_level_to_string(GLogLevelFlags level)
Expand Down
2 changes: 2 additions & 0 deletions src/notification.c
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,8 @@ void notification_unref(struct notification *n)
notification_private_free(n->priv);

if (n->script_count > 0) {
for (int i = 0; i < n->script_count; i++)
g_free(n->scripts[i]);
bynect marked this conversation as resolved.
Show resolved Hide resolved
g_free(n->scripts);
}

Expand Down
2 changes: 1 addition & 1 deletion src/notification.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ struct notification {

enum markup_mode markup;
const char *format;
const char **scripts;
char **scripts;
int script_count;
struct notification_colors colors;

Expand Down
44 changes: 24 additions & 20 deletions src/option_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,8 @@
#include "settings_data.h"

static int cmdline_argc;
static char **cmdline_argv;

static const char **cmdline_argv;
static char *usage_str = NULL;
static void cmdline_usage_append(const char *key, const char *type, const char *description);

static int cmdline_find_option(const char *key);

#define STRING_PARSE_RET(string, value) if (STR_EQ(s, string)) { *ret = value; return true; }

Expand Down Expand Up @@ -511,20 +507,20 @@ void save_settings(struct ini *ini) {
}
}

void cmdline_load(int argc, char *argv[])
void cmdline_load(int argc, const char *argv[])
{
cmdline_argc = argc;
cmdline_argv = argv;
}

int cmdline_find_option(const char *key)
static int cmdline_find_option(const char *key, int start)
{
ASSERT_OR_RET(key, -1);

gchar **keys = g_strsplit(key, "/", -1);

for (int i = 0; keys[i] != NULL; i++) {
for (int j = 0; j < cmdline_argc; j++) {
for (int j = start; j < cmdline_argc; j++) {
if (STR_EQ(keys[i], cmdline_argv[j])) {
g_strfreev(keys);
return j;
Expand All @@ -536,13 +532,16 @@ int cmdline_find_option(const char *key)
return -1;
}

static const char *cmdline_get_value(const char *key)
static const char *cmdline_get_value(const char *key, int start, int *found)
{
int idx = cmdline_find_option(key);
int idx = cmdline_find_option(key, start);
if (idx < 0) {
return NULL;
}

if (found)
*found = idx + 1;

if (idx + 1 >= cmdline_argc) {
/* the argument is missing */
LOG_W("%s: Missing argument. Ignoring.", key);
Expand All @@ -551,10 +550,9 @@ static const char *cmdline_get_value(const char *key)
return cmdline_argv[idx + 1];
}

char *cmdline_get_string(const char *key, const char *def, const char *description)
char *cmdline_get_string_offset(const char *key, const char *def, int start, int *found)
{
cmdline_usage_append(key, "string", description);
const char *str = cmdline_get_value(key);
const char *str = cmdline_get_value(key, start, found);

if (str)
return g_strdup(str);
Expand All @@ -564,10 +562,16 @@ char *cmdline_get_string(const char *key, const char *def, const char *descripti
return NULL;
}

char *cmdline_get_string(const char *key, const char *def, const char *description)
{
cmdline_usage_append(key, "string", description);
return cmdline_get_string_offset(key, def, 1, NULL);
}

char *cmdline_get_path(const char *key, const char *def, const char *description)
{
cmdline_usage_append(key, "string", description);
const char *str = cmdline_get_value(key);
const char *str = cmdline_get_value(key, 1, NULL);

if (str)
return string_to_path(g_strdup(str));
Expand All @@ -578,7 +582,7 @@ char *cmdline_get_path(const char *key, const char *def, const char *description
char **cmdline_get_list(const char *key, const char *def, const char *description)
{
cmdline_usage_append(key, "list", description);
const char *str = cmdline_get_value(key);
const char *str = cmdline_get_value(key, 1, NULL);

if (str)
return string_to_array(str, ",");
Expand All @@ -589,7 +593,7 @@ char **cmdline_get_list(const char *key, const char *def, const char *descriptio
gint64 cmdline_get_time(const char *key, gint64 def, const char *description)
{
cmdline_usage_append(key, "time", description);
const char *timestring = cmdline_get_value(key);
const char *timestring = cmdline_get_value(key, 1, NULL);
gint64 val = def;

if (timestring) {
Expand All @@ -602,7 +606,7 @@ gint64 cmdline_get_time(const char *key, gint64 def, const char *description)
int cmdline_get_int(const char *key, int def, const char *description)
{
cmdline_usage_append(key, "int", description);
const char *str = cmdline_get_value(key);
const char *str = cmdline_get_value(key, 1, NULL);

if (str)
return atoi(str);
Expand All @@ -613,7 +617,7 @@ int cmdline_get_int(const char *key, int def, const char *description)
double cmdline_get_double(const char *key, double def, const char *description)
{
cmdline_usage_append(key, "double", description);
const char *str = cmdline_get_value(key);
const char *str = cmdline_get_value(key, 1, NULL);

if (str)
return atof(str);
Expand All @@ -624,7 +628,7 @@ double cmdline_get_double(const char *key, double def, const char *description)
int cmdline_get_bool(const char *key, int def, const char *description)
{
cmdline_usage_append(key, "", description);
int idx = cmdline_find_option(key);
int idx = cmdline_find_option(key, 1);

if (idx > 0)
return true;
Expand All @@ -634,7 +638,7 @@ int cmdline_get_bool(const char *key, int def, const char *description)

bool cmdline_is_set(const char *key)
{
return cmdline_get_value(key) != NULL;
return cmdline_get_value(key, 1, NULL) != NULL;
}

void cmdline_usage_append(const char *key, const char *type, const char *description)
Expand Down
Loading