Loading ...
Sorry, an error occurred while loading the content.
 

Re: inadequate shellescape() implementation

Expand Messages
  • Hari Krishna Dara
    ... The shellslash() would give plugin writers a false sense that it is a cross-platform tool to execute external commands, so at least documenting the
    Message 1 of 3 , Jun 26, 2009
      On Tue, Jun 16, 2009 at 4:22 AM, Bram Moolenaar<Bram@...> wrote:
      >
      > Hari Krishna Dara wrote:
      >
      >> I have been using a custom function called genutils#EscapeCommand()
      >> (available as part of genutils.vim library) in all my plugins but
      >> always wanted something native in Vim. I was very excited to see
      >> shellescape() function when it was included in a recent Vim release,
      >> however I find that its implementation is not accurate, at least for
      >> windows when cygwin shell is used. This is a special condition on
      >> windows because the arguments somewhat get seen by native programs as
      >> well as the cygwin shell. As a simple example, let us say we want to
      >> run the command 'ls a"b' (without outer quotes) where the filename is
      >> 'a"b' (without outer quotes). On dos cmd.exe, it would be:
      >>
      >> > ls "a""b"
      >> ls: cannot access a"b: No such file or directory
      >>
      >> on bash prompt, it would be:
      >>
      >> $ ls 'a"b'
      >> ls: cannot access a"b: No such file or directory
      >>
      >> Let us try the same from Vim. Start a clean vim instance using -u NONE
      >> option (which guarantees 'noshellslash' and "cmd.exe" for 'shell') and
      >> try:
      >>
      >> :exec '!ls '. shellescape('a"b')
      >>
      >> and you would see the below as expected:
      >>
      >> C:\WINDOWS\system32\cmd.exe /c ls "a""b"
      >> ls: cannot access a"b: No such file or directory
      >> shell returned 2
      >> Hit any key to close this window...
      >>
      >> Let us try the same with cygwin as shell:
      >>
      >> :set shell=c:/cygwin/bin/bash.exe
      >> :set shellcmdflag=-c
      >> :set shellslash
      >> :set shellredir=>%s\ 2>&1
      >> :set shellpipe=2>&1\|\ tee
      >> :set shellxquote=\"
      >> :exec '!ls '. shellescape('a"b')
      >>
      >> What we get is:
      >>
      >> c:/cygwin/bin/bash.exe -c "ls 'a"b'"
      >> /usr/bin/bash: -c: line 0: unexpected EOF while looking for matching `''
      >> /usr/bin/bash: -c: line 1: syntax error: unexpected end of file
      >> shell returned 2
      >> Hit any key to close this window...
      >>
      >> This is because the command-line is seen by native command-line parser
      >> as well which expects the inner double-quote be doubled. The below
      >> works as expected:
      >>
      >> :exec '!ls '. shellescape('a""b')
      >>
      >> but this requires checking for platform and shell and so defeats the
      >> purpose of shellescape().
      >>
      >> I have also noticed that shellescape() is not sensitive to
      >> 'shellquote' and 'shellxquote' settings. E.g., if you try the below
      >> settings on top of the previous:
      >>
      >> :shellxquote='
      >> :exec '!ls '. shellescape('a""b')
      >>
      >> you get:
      >>
      >> c:/cygwin/bin/bash.exe -c 'ls 'a""b''
      >> ls: cannot access ab: No such file or directory
      >> shell returned 2
      >> Hit any key to close this window...
      >>
      >> Obviously, Vim didn't replace the inner single quotes, when it could
      >> very well know that the 'shellxquote' would cause an outer set of
      >> single quotes.
      >>
      >> For now I am sticking to my genutils#EscapeCommand() such they work in
      >> more vim environments, and hope that the built-in function will be
      >> improved to work with these and other possible scenarios.
      >
      > You can't really expect shellescape() to work in all environments with
      > all possible combination of option values.
      >
      > First of all, using a Unix shell on windows is already a problem, it
      > makes it very tricky to handle the mixed environment.  You can have
      > cmd.exe excute a Unix shell that executes a DOS command.  Then where do
      > you put quotes and what does a backslash mean?  It becomes a wonderful
      > puzzle.  It comes down to that the option values depend on the command
      > you want to execute.  E.g., "ls" requires forward slashes while "dir"
      > requires backslashes in the path.

      The shellslash() would give plugin writers a false sense that it is a
      cross-platform tool to execute external commands, so at least
      documenting the combinations that work/don't work will be helpful.

      >
      > Did you try unsetting shellslash?

      I didn't but it will probably cause others issues when using a unix
      shell (e.g., the path separator characters).

      -- Hari

      >
      > --
      > If Pacman had affected us as kids we'd be running around in dark rooms,
      > munching pills and listening to repetitive music.
      >                       -- Marcus Brigstocke
      >
      >  /// Bram Moolenaar -- Bram@... -- http://www.Moolenaar.net   \\\
      > ///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
      > \\\        download, build and distribute -- http://www.A-A-P.org        ///
      >  \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///
      >

      --~--~---------~--~----~------------~-------~--~----~
      You received this message from the "vim_use" maillist.
      For more information, visit http://www.vim.org/maillist.php
      -~----------~----~----~----~------~----~------~--~---
    Your message has been successfully submitted and would be delivered to recipients shortly.