You are not logged in.
Not sure it belongs in General Programming, but here it goes:
I have a Irssi script that shows a OSD when I'm highlighted. It's based on knotify, but I've changed
system("dcop knotify default notify 'New message' Irssi '$text' '' '' 16 0");
to
system("kdialog --passivepopup '$text' 10");
(and some other small things, but it's not relevant here).
It works as expected, but there's one problem: if the highlighted text has ' in it, I get the follow error message:
sh: -c: line 0: unexpected EOF while looking for matching `''
[19:04]line 1: syntax error: unexpected end of file
While I understand the error, I have no idea how to fix it. Any suggestions?
Last edited by Mogger (2010-01-15 10:36:05)
Offline
And here I thought it would be very easy to solve.
For now I use
system("kdialog --passivepopup \"$text\" 10");
There's still a problem if someone writes a single ", but it's more rare than a single ' so it's an improvement. Still, not quite what I would call a solution.
Offline
I think the problem here is that using the "system" call invokes sh to launch kdialog and therefore is interpreting that string directly, so if someone were to type '";rm -Rf /' into their IRC client there would be nothing stopping your script from allowing someone to wipe your system. You might be able to get around this by just replacing ' and " with something else in your $text variable before you put it into the command line. Otherwise the more common way to get around this is to use a fork and exec pattern, but I'm not so sure how this works in perl. Basically you fork so that you're running along side the original app, then you call exec and pass arguments individually, such as "kdialog", "--passivepopup", $text, 10. This is what the shell does internally, but I'm not quite sure how to do this from perl.
Hopefully this points you in the right direction anyhow, good luck
Offline
Basically you fork so that you're running along side the original app, then you call exec and pass arguments individually, such as "kdialog", "--passivepopup", $text, 10.
Perl's system does this when you pass it a list of arguments (more than one argument). For example, instead of passing system a string as before, it would be like:
system 'kdedialog', '--passivepopup', $text, 10;
Here is a quote from the command "perldoc -f system" which shows the docs for the system builtin:
If there is more than one argument in LIST, or if LIST is an array with more than one value, starts the program given by the first element of the list with arguments given by the rest of the list. If there is only one scalar argument, the argument is checked for shell metacharacters, and if there are any, the entire argument is passed to the system's command shell for parsing (this is /bin/sh -c on Unix platforms, but varies on other platforms).
The original problem was you were passing one argument and there were shell metacharacters involved (the quotes) so your arguments to system were being passed to sh -c "...".
I think it would be easier to use the method HashBox mentioned earlier and just pass a list to system. But in case you need to escape these special shell metacharacters/quotes in the future for some other reason you can do it with a replace regex:
$text =~ s/([\$!"\\`])/\\$1/g;
This inserts a \ character before whatever character matches inside the [...].
Offline
I think the problem here is that using the "system" call invokes sh to launch kdialog and therefore is interpreting that string directly, so if someone were to type '";rm -Rf /' into their IRC client there would be nothing stopping your script from allowing someone to wipe your system.
That sounds... bad. I didn't even think about that - glad I asked here instead of on IRC.
Perl's system does this when you pass it a list of arguments (more than one argument). For example, instead of passing system a string as before, it would be like:
system 'kdedialog', '--passivepopup', $text, 10;
Yes, that does the trick!
Thank you both for your answers, I learned a lot from them.
Offline