Skip to content

replace variables and ~ in script paths#351

Merged
tsipinakis merged 2 commits into
dunst-project:masterfrom
bebehei:wordexp
Aug 19, 2017
Merged

replace variables and ~ in script paths#351
tsipinakis merged 2 commits into
dunst-project:masterfrom
bebehei:wordexp

Conversation

@bebehei
Copy link
Copy Markdown
Member

@bebehei bebehei commented Aug 4, 2017

wordexp replaces all variables and ~ in the string. TBH I don't quite like the thing, that it replaces all variables, but there is no other way.

Fixes #350

@bebehei
Copy link
Copy Markdown
Member Author

bebehei commented Aug 4, 2017

Well, it might be good here, to add tests, too.

@tsipinakis
Copy link
Copy Markdown
Member

Yeah, tests are a good idea. option_parser.c already has tests for most of the functions so it should be trivial to extend them for the path one.

@bebehei
Copy link
Copy Markdown
Member Author

bebehei commented Aug 5, 2017

Well, it might be good here, to add tests, too.

Here they are.

Comment thread src/option_parser.c Outdated

wordexp_t replaced_path;
if (path && 0 == wordexp(path, &replaced_path, WRDE_NOCMD)){
path = g_strdup(replaced_path.we_wordv[0]);
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tsipinakis I'm missing here a free(path);, right?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah you are missing a free, path from init_get_string is never freed.

Comment thread test/option_parser.c Outdated
free(ptr);

path = ini_get_string(section, "expand_home", "");
wordexp(path, &replaced_path, WRDE_NOCMD);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we know the contents of the expansion we should use the simplest method (read: getenv) to get the data we need to compile the test case. Using the exact same code the function you're testing is using is error prone and can miss quite a few bugs.

(hint: You can use the string_replace function from utils.c to do the actual replacement)

Comment thread test/option_parser.c Outdated

path = ini_get_string(section, "expand_tilde", "");
wordexp(path, &replaced_path, WRDE_NOCMD);
ASSERT_STR_EQ(replaced_path.we_wordv[0], (ptr = ini_get_path(section, "expand_tilde", "")));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same with this test, we should use the simplest method to setup the test case.

Comment thread src/option_parser.c Outdated

wordexp_t replaced_path;
if (path && 0 == wordexp(path, &replaced_path, WRDE_NOCMD)){
path = g_strdup(replaced_path.we_wordv[0]);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah you are missing a free, path from init_get_string is never freed.

Comment thread src/option_parser.c Outdated
char *path = ini_get_string(section, key, def);

wordexp_t replaced_path;
if (path && 0 == wordexp(path, &replaced_path, WRDE_NOCMD)){
Copy link
Copy Markdown
Member

@tsipinakis tsipinakis Aug 6, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some more error handling here would be nice, especially for WRDE_BADVAL and WRDE_CMDSUB.

Comment thread src/option_parser.c Outdated

wordexp_t replaced_path;
if (path && 0 == wordexp(path, &replaced_path, WRDE_NOCMD)){
path = g_strdup(replaced_path.we_wordv[0]);
Copy link
Copy Markdown
Member

@tsipinakis tsipinakis Aug 6, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're also only getting the first word here, we_wordv is a string array (char **), not a char *. It's a common mistake so please also add a regression test for this.

@bebehei
Copy link
Copy Markdown
Member Author

bebehei commented Aug 7, 2017

Disclaimer: I'm currently not at my laptop for the next few days and can't test it. I read the wordexp manpage over and over again until I fully understood the Problems.

I have to conclude, that this is the shittiest approach possible.

Here is why:

You're also only getting the first word here, we_wordv is a string array

Yes this is correct. So if there are multiple words, we have to strcat all we_wordv elements together with $IFS.

Field splitting is done using the environment variable $IFS. If it is not set, the field separators are space, tab and newline.

Well, if someone sets `IFS=/', the returned path is broken.

Even worse: IFS is unset, the path contains spaces. So how should we deterministically chain the words again together?

Wordexp also does more stuff, I personally dislike. It also replaces other variables. IMO in our case only $HOME (maybe additionally $USER) should get expanded and nothing more.

(hint: You can use the string_replace function from utils.c to do the actual replacement)

What about using this in the actual ini_get_string? I think about replacing the first two characters if they match ~/ with getenv('HOME').

@bebehei bebehei force-pushed the wordexp branch 7 times, most recently from 246a5c2 to 4e873fe Compare August 13, 2017 19:38
@bebehei
Copy link
Copy Markdown
Member Author

bebehei commented Aug 13, 2017

Field splitting is done using the environment variable $IFS. If it is not set, the field separators are space, tab and newline.

Well, if someone sets `IFS=/', the returned path is broken.

Even worse: IFS is unset, the path contains spaces. So how should we deterministically chain the words again together?

Well, it turns out to be true in all cases. wordexp makes classical word. This is uesless.

What about using this in the actual ini_get_string? I think about replacing the first two characters if they match ~/ with getenv('HOME').

So, I went for that. Here are the commits. Sorry for the spam on travis. In my previous commits, I failed using strcat. 🤦

@tsipinakis
Copy link
Copy Markdown
Member

So, I went for that. Here are the commits. Sorry for the spam on travis. In my previous commits, I failed using strcat.

No worries, you're not a C programmer until you've wasted a few hours debugging weird memory issues :p

It might be beneficial to also apply this to the dmenu and browser settings, they are also paths after all.

@bebehei
Copy link
Copy Markdown
Member Author

bebehei commented Aug 15, 2017

It might be beneficial to also apply this to the dmenu and browser settings, they are also paths after all.

Thanks for the hint.

@bebehei
Copy link
Copy Markdown
Member Author

bebehei commented Aug 15, 2017

It might be beneficial to also apply this to the dmenu and browser settings, they are also paths after all.

I moved the logics now to a function in utils.h, added cmdline support and dmenu and the browser use these settings now, too.

The tests from test_ini_get_path about correct expansion have moved now to a separate test in utils.h, while in test_(ini|cmdline|option)_get_path now only test, if expansion works. and the handling of cmdline precedence.

@tsipinakis
Copy link
Copy Markdown
Member

LGTM 👍

Thank you for implementing this.

@tsipinakis tsipinakis merged commit 3c257ea into dunst-project:master Aug 19, 2017
@bebehei bebehei deleted the wordexp branch August 19, 2017 10:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants