Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.debian.user > #222971 > unrolled thread

Syntax regarding "Exec" instruction in .desktop files

Started byl0f4r0@tuta.io
First post2020-06-01 15:20 +0200
Last post2020-06-23 01:00 +0200
Articles 9 — 4 participants

Back to article view | Back to linux.debian.user


Contents

  Syntax regarding "Exec" instruction in .desktop files l0f4r0@tuta.io - 2020-06-01 15:20 +0200
    Re: Syntax regarding "Exec" instruction in .desktop files Greg Wooledge <wooledg@eeg.ccf.org> - 2020-06-01 15:30 +0200
      Re: Syntax regarding "Exec" instruction in .desktop files l0f4r0@tuta.io - 2020-06-01 17:40 +0200
        Re: Syntax regarding "Exec" instruction in .desktop files Andrei POPESCU <andreimpopescu@gmail.com> - 2020-06-01 20:10 +0200
          Re: Syntax regarding "Exec" instruction in .desktop files l0f4r0@tuta.io - 2020-06-01 20:40 +0200
            Re: Syntax regarding "Exec" instruction in .desktop files Andrei POPESCU <andreimpopescu@gmail.com> - 2020-06-02 07:50 +0200
    Re: Syntax regarding "Exec" instruction in .desktop files l0f4r0@tuta.io - 2020-06-22 19:50 +0200
      Re: Syntax regarding "Exec" instruction in .desktop files Greg Wooledge <wooledg@eeg.ccf.org> - 2020-06-22 19:50 +0200
      Re: Syntax regarding "Exec" instruction in .desktop files davidson <davidson@freevolt.org> - 2020-06-23 01:00 +0200

#222971 — Syntax regarding "Exec" instruction in .desktop files

Froml0f4r0@tuta.io
Date2020-06-01 15:20 +0200
SubjectSyntax regarding "Exec" instruction in .desktop files
Message-ID<AcSw9-84u-3@gated-at.bofh.it>
Hi,

Could someone explain to me the correct syntax (quoting & escaping) regarding "Exec" instruction in .desktop files please?

The FreeDesktop specification (https://specifications.freedesktop.org/desktop-entry-spec/latest/ar01s07.html) says the following:

===BEGIN EXTRACT===
"Arguments may be quoted in whole. If an argument contains a reserved character the argument must be quoted. The rules for quoting of arguments is also applicable to the executable name or path of the executable program as provided.

Quoting must be done by enclosing the argument between double quotes and escaping the double quote character, backtick character ("`"), dollar sign ("$") and backslash character ("\") by preceding it with an additional backslash character. Implementations must undo quoting before expanding field codes and before passing the argument to the executable program. Reserved characters are space (" "), tab, newline, double quote, single quote ("'"), backslash character ("\"), greater-than sign (">"), less-than sign ("<"), tilde ("~"), vertical bar ("|"), ampersand ("&"), semicolon (";"), dollar sign ("$"), asterisk ("*"), question mark ("?"), hash mark ("#"), parenthesis ("(") and (")") and backtick character ("`").

Note that the general escape rule for values of type string states that the backslash character can be escaped as ("\\") as well and that this escape rule is applied before the quoting rule. As such, to unambiguously represent a literal backslash character in a quoted argument in a desktop entry file requires the use of four successive backslash characters ("\\\\"). Likewise, a literal dollar sign in a quoted argument in a desktop entry file is unambiguously represented with ("\\$")."
===END EXTRACT===

I'm not sure to understand that totally...

Let's take an example, here is my fusuma.desktop file:[Desktop Entry]
Type=Application
Name=fusuma
Exec=sh -c 'if which ruby >/dev/null && which gem >/dev/null; then $(ruby -r rubygems -e "puts Gem.user_dir")/bin/fusuma -d; fi'
StartupNotify=false
Terminal=false

Actually, it WORKS on my Debian 10... but it's not considered as syntaxically correct:

desktop-file-validate fusuma.desktop 

fusuma.desktop: error: value "sh -c 'if which ruby >/dev/null && which gem >/dev/null; then $(ruby -r rubygems -e "puts Gem.user_dir")/bin/fusuma -d; fi'" for key "Exec" in group "Desktop Entry" contains a reserved character ''' outside of a quote
fusuma.desktop: error: value "sh -c 'if which ruby >/dev/null && which gem >/dev/null; then $(ruby -r rubygems -e "puts Gem.user_dir")/bin/fusuma -d; fi'" for key "Exec" in group "Desktop Entry" contains a reserved character '>' outside of a quote
fusuma.desktop: error: value "sh -c 'if which ruby >/dev/null && which gem >/dev/null; then $(ruby -r rubygems -e "puts Gem.user_dir")/bin/fusuma -d; fi'" for key "Exec" in group "Desktop Entry" contains a reserved character '&' outside of a quote
fusuma.desktop: error: value "sh -c 'if which ruby >/dev/null && which gem >/dev/null; then $(ruby -r rubygems -e "puts Gem.user_dir")/bin/fusuma -d; fi'" for key "Exec" in group "Desktop Entry" contains a reserved character '&' outside of a quote
fusuma.desktop: error: value "sh -c 'if which ruby >/dev/null && which gem >/dev/null; then $(ruby -r rubygems -e "puts Gem.user_dir")/bin/fusuma -d; fi'" for key "Exec" in group "Desktop Entry" contains a reserved character '>' outside of a quote
fusuma.desktop: error: value "sh -c 'if which ruby >/dev/null && which gem >/dev/null; then $(ruby -r rubygems -e "puts Gem.user_dir")/bin/fusuma -d; fi'" for key "Exec" in group "Desktop Entry" contains a reserved character ';' outside of a quote
fusuma.desktop: error: value "sh -c 'if which ruby >/dev/null && which gem >/dev/null; then $(ruby -r rubygems -e "puts Gem.user_dir")/bin/fusuma -d; fi'" for key "Exec" in group "Desktop Entry" contains a reserved character '$' outside of a quote
fusuma.desktop: error: value "sh -c 'if which ruby >/dev/null && which gem >/dev/null; then $(ruby -r rubygems -e "puts Gem.user_dir")/bin/fusuma -d; fi'" for key "Exec" in group "Desktop Entry" contains a reserved character '(' outside of a quote
fusuma.desktop: error: value "sh -c 'if which ruby >/dev/null && which gem >/dev/null; then $(ruby -r rubygems -e "puts Gem.user_dir")/bin/fusuma -d; fi'" for key "Exec" in group "Desktop Entry" contains a reserved character ')' outside of a quote
fusuma.desktop: error: value "sh -c 'if which ruby >/dev/null && which gem >/dev/null; then $(ruby -r rubygems -e "puts Gem.user_dir")/bin/fusuma -d; fi'" for key "Exec" in group "Desktop Entry" contains a reserved character ';' outside of a quote
fusuma.desktop: error: value "sh -c 'if which ruby >/dev/null && which gem >/dev/null; then $(ruby -r rubygems -e "puts Gem.user_dir")/bin/fusuma -d; fi'" for key "Exec" in group "Desktop Entry" contains a reserved character ''' outside of a quote

>From my understanding, I've tried:
Exec=sh -c "if which ruby \>/dev/null \&\& which gem \>/dev/null\; then \$\(ruby -r rubygems -e \"puts Gem.user_dir\"\)/bin/fusuma -d\; fi"

I get no warning except it does not work now!
It's probably a matter of successive backslashes but I don't understand how many are needed exactly...
Of course I'm interested in the correct syntax for my example but it's not so critical as it's already working.
I would rather be more interested if you could share with me your own understanding of the official spec, with 2 or 3 different examples so it's cristal clear :)

Thank you & Best regards,
l0f4r0

[toc] | [next] | [standalone]


#222972

FromGreg Wooledge <wooledg@eeg.ccf.org>
Date2020-06-01 15:30 +0200
Message-ID<AcSFP-87G-11@gated-at.bofh.it>
In reply to#222971
On Mon, Jun 01, 2020 at 03:12:03PM +0200, l0f4r0@tuta.io wrote:
> "Arguments may be quoted in whole. If an argument contains a reserved character the argument must be quoted. The rules for quoting of arguments is also applicable to the executable name or path of the executable program as provided.

> Quoting must be done by enclosing the argument between double quotes and escaping the double quote character, [...]

OK so far.

> Let's take an example, here is my fusuma.desktop file:[Desktop Entry]
> Type=Application
> Name=fusuma
> Exec=sh -c 'if which ruby >/dev/null && which gem >/dev/null; then $(ruby -r rubygems -e "puts Gem.user_dir")/bin/fusuma -d; fi'

You have not followed the allowed syntax.  You have an argument which
needs quoting, but you have not enclosed it in double-quotes.  Nor have
you escaped the characters within it that need escaping.

I would not even *attempt* to do what you are trying to do here.  Your
life would become enormously simpler if you would just put this shell
script inside a file, and Exec it as a script.

Attempting to in-line a shell script inside an Exec= line is madness.

[toc] | [prev] | [next] | [standalone]


#222975

Froml0f4r0@tuta.io
Date2020-06-01 17:40 +0200
Message-ID<AcUHE-QN-9@gated-at.bofh.it>
In reply to#222972
Hi Greg,

1 juin 2020 à 15:25 de wooledg@eeg.ccf.org:

> On Mon, Jun 01, 2020 at 03:12:03PM +0200, l0f4r0@tuta.io wrote:
>
>> Let's take an example, here is my fusuma.desktop file:[Desktop Entry]
>>
>> Type=Application
>> Name=fusuma
>> Exec=sh -c 'if which ruby >/dev/null && which gem >/dev/null; then $(ruby -r rubygems -e "puts Gem.user_dir")/bin/fusuma -d; fi'
>>
> You have not followed the allowed syntax.  You have an argument which
> needs quoting, but you have not enclosed it in double-quotes.  Nor have
> you escaped the characters within it that need escaping.
>
Yes, absolutely, that's why I mentioned my modifications some lines after in my OP ;)
What would be your 100% compliant version please?

> I would not even *attempt* to do what you are trying to do here.  Your
> life would become enormously simpler if you would just put this shell
> script inside a file, and Exec it as a script.
>
> Attempting to in-line a shell script inside an Exec= line is madness.
>
Interesting. Is it madness because it becomes too much complicated to write it easily and correctly according to the official specifications (namely quoting/escaping...)? Or for different reasons?

Thank you in advance.
Best regards,
l0f4r0

[toc] | [prev] | [next] | [standalone]


#222979

FromAndrei POPESCU <andreimpopescu@gmail.com>
Date2020-06-01 20:10 +0200
Message-ID<AcX2O-2oa-1@gated-at.bofh.it>
In reply to#222975

[Multipart message — attachments visible in raw view] — view raw

On Lu, 01 iun 20, 17:34:10, l0f4r0@tuta.io wrote:
> 1 juin 2020 à 15:25 de wooledg@eeg.ccf.org:
> 
> > I would not even *attempt* to do what you are trying to do here.  Your
> > life would become enormously simpler if you would just put this shell
> > script inside a file, and Exec it as a script.
> >
> > Attempting to in-line a shell script inside an Exec= line is madness.
> >
> Interesting. Is it madness because it becomes too much complicated to 
> write it easily and correctly according to the official specifications 
> (namely quoting/escaping...)? Or for different reasons?

Yes :)

Question for you: how much would it have taken you to write that into a 
script compared to the time you spent trying to get the quoting right?

Kind regards,
Andrei
-- 
http://wiki.debian.org/FAQsFromDebianUser

[toc] | [prev] | [next] | [standalone]


#222982

Froml0f4r0@tuta.io
Date2020-06-01 20:40 +0200
Message-ID<AcXvQ-2xy-5@gated-at.bofh.it>
In reply to#222979
Hi Andrei,

1 juin 2020 à 20:03 de andreimpopescu@gmail.com:

> On Lu, 01 iun 20, 17:34:10, l0f4r0@tuta.io wrote:
>
>> 1 juin 2020 à 15:25 de wooledg@eeg.ccf.org:
>>
>> > I would not even *attempt* to do what you are trying to do here.  Your
>> > life would become enormously simpler if you would just put this shell
>> > script inside a file, and Exec it as a script.
>> >
>> > Attempting to in-line a shell script inside an Exec= line is madness.
>> >
>> Interesting. Is it madness because it becomes too much complicated to 
>> write it easily and correctly according to the official specifications 
>> (namely quoting/escaping...)? Or for different reasons?
>>
> Yes :)
>
> Question for you: how much would it have taken you to write that into a 
> script compared to the time you spent trying to get the quoting right?
>
HaHa, of course the latter is much more time-consuming than the former BUT the former makes me more knowledgeable.
A workaround/bypass expedites the issue for sure and can sometimes be satisfying when particularly clever, but it prevents you from understanding the machinery.
I tend to implement workaround when everything else fail.

Best regards,
l0f4r0

[toc] | [prev] | [next] | [standalone]


#222996

FromAndrei POPESCU <andreimpopescu@gmail.com>
Date2020-06-02 07:50 +0200
Message-ID<Ad7Yd-t2-1@gated-at.bofh.it>
In reply to#222982

[Multipart message — attachments visible in raw view] — view raw

On Lu, 01 iun 20, 20:33:28, l0f4r0@tuta.io wrote:
> 1 juin 2020 à 20:03 de andreimpopescu@gmail.com:
> >
> > Question for you: how much would it have taken you to write that into a 
> > script compared to the time you spent trying to get the quoting right?
> >
> HaHa, of course the latter is much more time-consuming than the former 
> BUT the former makes me more knowledgeable.

Some knowledge is more useful that other. Given limited time, in my 
opinion, it makes sense to (try to) pick the useful one[1].

> A workaround/bypass expedites the issue for sure and can sometimes be 
> satisfying when particularly clever, but it prevents you from 
> understanding the machinery.
>
> I tend to implement workaround when everything else fail.

In this particular case I consider the script option to be the optimal 
one, not a workaround, if only because it's easier to maintain (a proper 
script has structure and comments).

Unless you exercise your knowledge of quoting regularly you might find 
that months later, if you need to tweak or fix that Exec= line you have 
to re-learn what you did now.

Your system, your rules :)

[1] for me that means "with practical applications"

Kind regards,
Andrei
-- 
http://wiki.debian.org/FAQsFromDebianUser

[toc] | [prev] | [next] | [standalone]


#223891

Froml0f4r0@tuta.io
Date2020-06-22 19:50 +0200
Message-ID<AkyJX-4if-1@gated-at.bofh.it>
In reply to#222971
Hi davidson,

I share your great answer (see below) with the whole list as I think your explanations are very didactic, relevant and could be beneficial to anyone.

 I've just tested and it works so thank you very much :)

If I have well understood, my issue was that I've mixed up reserved characters with distinguished ones, right?

So if I sum up, here is the logic:

* As soon as there is at least one *reserved* characters (like [SPACE] [TAB] [NEWLINE] " ' \ > < ~ | & ; $ * ? # ( )) in an argument, one needs to escape the whole argument

* Argument escaping is done by adding double quotes around it and prefixing each *distinguished* characters (like " ` $ \) with a \

* Reserved characters must be escaped individually only if they must lose their specific meaning and be interpreted litterally

* Escaping reserved characters is done by prefixing them with a \ but as the argument needs quoting, the extra \ itself must be prefixed by a leading \ so a litteral $ becomes \\$, a \ becomes \\\\, & becomes \\& and so on...

Am I correct please?

Thanks a lot!
Best regards,
l0f4r0


16 juin 2020 à 07:07 de davidson@freevolt.org:

> On Mon, 1 Jun 2020, l0f4r0@tuta.io wrote to debian-user:
>
>> Let's take an example, here is my fusuma.desktop file:[Desktop Entry]
>>
> [...]
>
>> Exec=sh -c 'if which ruby >/dev/null && which gem >/dev/null; then $(ruby -r rubygems -e "puts Gem.user_dir")/bin/fusuma -d; fi'
>>
>
> The third argument (everything after the '-c') of this Exec value,
> your shell script, contains all kinds of characters the spec indicates
> are reserved[1], like the following:
>
>  [SPACE] > & ; $ ( " )
>
> This means that the spec requires it (the argument containing reserved
> characters) to be quoted[2].
>
> But how to quote an argument? The spec explains[3] this is done by
> enclosing the argument inside double quotes, and escaping all of its
> occurences of four especially distinguished characters
>
>  " ` $ \
>
> with a backslash prefix.
>
> So to quote the argument (the script), remove the single quotes
> surrounding the script, replace them with double quotes, and then
> inside the script add one backslash in front of each occurence of the
> especially distinguished characters which require escaping (just the
> dollar sign introducing command substitution, and the pair of double
> quotes inside that command substitution) to obtain:
>
>  Exec=sh -c "if which ruby >/dev/null && which gem >/dev/null; then \$(ruby -r rubygems -e \"puts Gem.user_dir\")/bin/fusuma -d; fi"
>
>>> From my understanding, I've tried:
>>>
>> Exec=sh -c "if which ruby \>/dev/null \&\& which gem \>/dev/null\; then \$\(ruby -r rubygems -e \"puts Gem.user_dir\"\)/bin/fusuma -d\; fi"
>>
>> I get no warning except it does not work now!
>>
>> It's probably a matter of successive backslashes but I don't
>> understand how many are needed exactly...
>>
>> Of course I'm interested in the correct syntax for my example but
>> it's not so critical as it's already working.
>>
>
> In your attempted revision, you seem to have selectively prefixed
> backslashes to some reserved characters (eg, '>') but not others (eg,
> ' ').
>
> But why prefix backslashes to any characters at all, beyond those four
> required by the spec (the ones I called "especially distinguished")?
>
>  " ` $ \
>
> Reserved characters in an argument don't generally need any escaping
> at all.[4] Their *presence* means an argument containing them must be
> quoted, and quoting an argument entails prefixing a backslash to the
> four *special* reserved characters distinguished above.
>
> QUOTES (from the spec excerpt in OP) and NOTES
>
> 1.[quote] Reserved characters are space (" "), tab, newline, double quote,
> single quote ("'"), backslash character ("\"), greater-than sign
> (">"), less-than sign ("<"), tilde ("~"), vertical bar ("|"),
> ampersand ("&"), semicolon (";"), dollar sign ("$"), asterisk ("*"),
> question mark ("?"), hash mark ("#"), parenthesis ("(") and (")") and
> backtick character ("`").
>
> 2.[quote] Arguments may be quoted in whole. If an argument contains a
> reserved character the argument must be quoted.
>
> 3.[quote] Quoting must be done by enclosing the argument between double
> quotes and escaping the double quote character, backtick character
> ("`"), dollar sign ("$") and backslash character ("\") by preceding it
> with an additional backslash character.
>
> 4.[note] Unless you require a reserved character's literal
> interpretation. Your given example is simple because you want the
> non-literal interpretations of each of its reserved characters.
>

[toc] | [prev] | [next] | [standalone]


#223892

FromGreg Wooledge <wooledg@eeg.ccf.org>
Date2020-06-22 19:50 +0200
Message-ID<AkyJY-4if-5@gated-at.bofh.it>
In reply to#223891
On Mon, Jun 22, 2020 at 07:40:04PM +0200, l0f4r0@tuta.io wrote:
> So if I sum up, here is the logic:
[...]
> Am I correct please?

https://specifications.freedesktop.org/desktop-entry-spec/latest/ar01s07.html

[toc] | [prev] | [next] | [standalone]


#223895

Fromdavidson <davidson@freevolt.org>
Date2020-06-23 01:00 +0200
Message-ID<AkDzY-7cd-7@gated-at.bofh.it>
In reply to#223891
On Mon, 22 Jun 2020 l0f4r0@tuta.io wrote:
> Hi davidson,
>
> I share your great answer (see below) with the whole list as I think
> your explanations are very didactic, relevant and could be
> beneficial to anyone.
>
> I've just tested and it works so thank you very much :)

Lol. Good news! It is good to learn about empirical results.

> If I have well understood, my issue was that I've mixed up reserved
> characters with distinguished ones, right?

That is what it looked like to me.

The piece of the specification that you posted "distinguished" the
four anonymously, insisting they all four had to receive special
treatment, but gave their class no distinctive name.

By the way, I think it is interesting that bash(1) also explains (in a
paragraph[1] under the section "QUOTING") that inside double quotes,
those same four characters

     $ ` \ "

are exceptional, being the only characters whose literal value is not
preserved between a pair of double quotes (assuming either posix mode
or disabled history expansion).[2]

I suspect that putting together the details that give rise to this
coincidence would be cool to understand. I lack that understanding.

But even with little understanding, it is now easier to remember which
characters bash does not remove special meaning from inside double
quotes. (It is like with people: after you know like fifty other
things about them, it becomes easier to remember what their name is.)

> So if I sum up, here is the logic:
>
> * As soon as there is at least one *reserved* characters (like
>   [SPACE] [TAB] [NEWLINE] " ' \ > < ~ | & ; $ * ? # ( ))

Also, backtick.

>   in an argument, one needs to escape the whole argument
>
> * Argument escaping is done by adding double quotes around it and
>   prefixing each *distinguished* characters (like " ` $ \) with a \
>
> * Reserved characters must be escaped individually only if they must
>   lose their specific meaning and be interpreted litterally

Your breakdown of the escape of reserved characters paints a helpful
sequence of operations for me:

> * Escaping reserved characters is done by prefixing them with a \
>   but as the argument needs quoting, the extra \ itself must be
>   prefixed by a leading \ so a litteral $ becomes \\$, a \ becomes
>   \\\\, & becomes \\& and so on...

Also, the link Greg posted to the Desktop Entry Specification[3]
includes stuff about field codes that wasn't in the OP excerpt.

A selective excerpt in OP was natural enough, since the specific
example in OP appears to contain no field codes.

But appearances might be deceptive, and if I were considering putting
complex stuff (or even simple stuff) in the Exec field, I would
examine it all very carefully. There are land mines in there:

    Field codes must not be used inside a quoted argument, the result
    of field code expansion inside a quoted argument is undefined.

And not just the field codes the spec lists an interpretation for;
*any* alphabetic character immediately preceded by an unescaped '%'
character IS A FIELD CODE, and hence a potential land mine, according
to the spec. (And '%' is escaped in a way not like other characters,
because it is after all in a class by itself, and so on...)

> Am I correct please?

In the words of deloptes[4]:

    Believe you do in the church, not infront of the computer, when we
    see the output we can conclude ourself.

> Thanks a lot!

That is mutual.


NOTES and REFERENCES

1. From bash(1):

    QUOTING
    [...]
    Enclosing characters in double quotes preserves the literal value
    of all characters within the quotes, with the exception of

      $ ` \

    and, when history expansion is enabled,

      !

    When the shell is in posix mode, the ! has no special meaning
    within double quotes, even when history expansion is enabled.  The
    characters $ and ` retain their special meaning within double
    quotes.  The backslash retains its special meaning only when
    followed by one of the following characters: $, `, ", \, or
    <newline>.  A double quote may be quoted within double quotes by
    preceding it with a backslash.  If enabled, history expansion will
    be performed unless an !  appearing in double quotes is escaped
    using a backslash.  The backslash preceding the !  is not removed.
    [...]

2. You might need to squint a little, to see why I include the double
    quote character with the other three here. Also, in the case of
    double quoted strings in bash (as distinguished from the case of a
    desktop entry Exec value) it looks like the backslash is only
    special in that context when it is "doing some important
    backslashing". That is, when it isn't escaping a "live" special
    character, a backslash is just a literal backslash, inside double
    quotes in bash.

3. Desktop Entry Specification, "The Exec Key"
    https://specifications.freedesktop.org/desktop-entry-spec/latest/ar01s07.html

4. 23 Jan 2017, deloptes to debian-user
    https://lists.debian.org/msgid-search/o64ag3$iq2$1@blaine.gmane.org

-- 
Firstly, you must always implicitly obey orders, without attempting to
form any opinion of your own respecting their propriety. Secondly, you
must consider every man your enemy who speaks ill of your king; and
thirdly, you must hate a Frenchman, as you do the devil. --H. Nelson

[toc] | [prev] | [standalone]


Back to top | Article view | linux.debian.user


csiph-web