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

Use wordexp to resolve variables like $HOME in path like settings #1215

Merged
Show file tree
Hide file tree
Changes from all 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
13 changes: 13 additions & 0 deletions .valgrind.suppressions
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,19 @@
obj:/lib/ld-musl-x86_64.so.1
}

# Ignore another musls' weird error
{
musl_alpine_libc
Memcheck:Leak
match-leak-kinds: definite
fun:malloc
fun:realloc
fun:getdelim
obj:*
fun:vgMemCheck_new_block
obj:*
}

# rsvg_error_handle_close got fixed in
# - GNOME/librsvg@7bf1014
# (2018-11-12, first tags: v2.45.0, v2.44.9)
Expand Down
13 changes: 8 additions & 5 deletions docs/dunst.5.pod
Original file line number Diff line number Diff line change
Expand Up @@ -911,7 +911,8 @@ If B<icon_position> is set to off, this setting is ignored.

Updates the icon of the notification, it should be a path or a name for a valid
image. This overrides the icon that was sent with dunstify or another notification
tool.
tool. Expansion of the argument is carried out using wordexp(3)
with command substitution disabled.

=item C<icon_position> (values: [left/right/top/off], default: left)

Expand All @@ -922,7 +923,8 @@ disables icons.

Sets the default icon of the notification, it should be a path or a name for a
valid image. This does B<not> override the icon that was sent with dunstify or
another notification tool.
another notification tool. Expansion of the argument is carried out using
wordexp(3) with command substitution disabled.

=item C<set_stack_tag>

Expand Down Expand Up @@ -1087,9 +1089,10 @@ Note that some variables may be empty.
If the notification is suppressed, the script will not be run unless
B<always_run_script> is set to true.

If '~/' occurs at the beginning of the script parameter, it will get replaced by the
users' home directory. If the value is not an absolute path, the directories in the
PATH variable will be searched for an executable of the same name.
The script parameter is expanded according to wordexp(3) with command
substitution disabled. If the expanded value is not an absolute path, the
directories in the PATH variable will be searched for an executable of the same
name.

=head1 COLORS

Expand Down
35 changes: 27 additions & 8 deletions src/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#include <wordexp.h>

#include "log.h"
#include "settings_data.h"
Expand Down Expand Up @@ -179,16 +180,34 @@ int string_array_length(char **s)
/* see utils.h */
char *string_to_path(char *string)
{

if (string && STRN_EQ(string, "~/", 2)) {
char *home = g_strconcat(user_get_home(), "/", NULL);

string = string_replace_at(string, 0, 2, home);

g_free(home);
ASSERT_OR_RET(string, string);

wordexp_t we;
switch (wordexp(string, &we, WRDE_NOCMD | WRDE_UNDEF)) {
case 0:
break;
case WRDE_BADCHAR:
LOG_W("Expansion of \"%s\" failed. It contains invalid characters.", string);
return string;
case WRDE_BADVAL:
LOG_W("Expansion of \"%s\" failed. It contains an undefined variable.", string);
return string;
case WRDE_CMDSUB:
LOG_W("Expansion of \"%s\" failed. The requested command substitution is currently not supported.", string);
return string;
case WRDE_NOSPACE:
LOG_W("Expansion of \"%s\" failed. We ran out of memory.", string);
return string;
case WRDE_SYNTAX:
LOG_W("Expansion of \"%s\" failed. It contains invalid syntax.", string);
return string;
}
g_free(string);

char *res = g_strjoinv(" ", we.we_wordv);
wordfree(&we);

return string;
return res;
}

/* see utils.h */
Expand Down
10 changes: 10 additions & 0 deletions test/option_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -521,16 +521,23 @@ TEST test_string_to_path(void)
"/path/p argument",
"p with multiple arguments",
"~/p/p",
"$HOME/p/p",
"$TEST_ENV/p/p",
};

setenv("TEST_ENV", "foobar", 1);

char *expanded_home = g_strconcat(user_get_home(), "/", "p/p", NULL);
char *expanded_env = g_strconcat("foobar", "/p/p", NULL);
const char* results[] = {
"/bin/something",
"something",
"/path/path/path/",
"/path/p argument",
"p with multiple arguments",
expanded_home,
expanded_home,
expanded_env,
};

const char* results2[][5] = {
Expand All @@ -540,6 +547,8 @@ TEST test_string_to_path(void)
{"/path/p", "argument", NULL},
{"p", "with", "multiple", "arguments", NULL},
{expanded_home},
{expanded_home},
{expanded_env},
};

ARRAY_SAME_LENGTH(inputs, results);
Expand All @@ -557,6 +566,7 @@ TEST test_string_to_path(void)
}

g_free(val);
g_free(expanded_env);
g_free(expanded_home);
g_strfreev(val2);
PASS();
Expand Down
16 changes: 16 additions & 0 deletions test/utils.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#include <features.h>

#include "../src/utils.c"
#include "greatest.h"

Expand Down Expand Up @@ -152,6 +154,7 @@ TEST test_string_to_path(void)
ASSERT_STR_EQ(exp, (ptr = string_to_path(g_strdup(exp))));
free(ptr);

// This might fail, when a user named path exists on the host running the tests.
exp = "~path/with/wrong/tilde";
ASSERT_STR_EQ(exp, (ptr = string_to_path(g_strdup(exp))));
free(ptr);
Expand All @@ -166,6 +169,19 @@ TEST test_string_to_path(void)
free(exp);
free(ptr);

ASSERT_STR_EQ((exp = g_strconcat(home, "/.path/with/HOME environment variable", NULL)),
(ptr = string_to_path(g_strdup("$HOME/.path/with/HOME environment variable"))));
free(exp);
free(ptr);

// Just glibc properly returns an error when using `WRDE_UNDEF` and an
// undefined variable is found. musl accepts this flag and ignores it.
#ifdef __GLIBC__
exp = "/some/$UNDEFINED/variable";
ASSERT_STR_EQ(exp, (ptr = string_to_path(g_strdup(exp))));
free(ptr);
#endif

PASS();
}

Expand Down
Loading