Skip to content

Quotation in System.Process.system for Windows #51

@thomie

Description

@thomie

Moved from https://ghc.haskell.org/trac/ghc/ticket/5376:

Wagnerdm writes: I had a bit of fun recently tracking down quoting issues with the "system" command in Windows. For the examples below, I'll consistently use "Windows> " as the beginning of some text sent to the Windows command prompt cmd.exe, and use "GHC> " as the beginning of some text sent to a ghci session running in cmd.exe with System.Cmd imported.

The situation is this: I want to hand off a command line which has both a possibly-quoted command name and a (definitely) quoted argument. For concreteness, let's use "more" as the command and "foo.txt" as the argument, so that you can follow along at home on your favorite Windows system.

Windows> echo foo > foo.txt
Windows> "more" "foo.txt"
foo

All good so far. But:

GHC> system "\"more\" \"foo.txt\""
'more" "foo.txt' is not recognized as an internal or external command, operable program or batch file.
ExitFailure 1

After some digging, I discovered that system is shipping out to cmd /c, and indeed:

Windows> cmd /c "more" "foo.txt"
'more" "foo.txt' is not recognized as an internal or external command, operable program or batch file.

I don't know what the right fix is. However, after a bit of playing around, I discovered the following:

Windows> cmd /c ""more" "foo.txt""
foo
GHC> system "\"\"more\" \"foo.txt\"\""
foo
ExitSuccess

Wrapping commands with an extra pair of double-quotes this way seemed to give behavior matching the bare cmd.exe for all the examples I could think of, even ones I thought it would break. For example:

GHC> system "\"more foo.txt\""
foo
ExitSuccess

If this turns out to be the right thing to do, it's pretty easy to implement. In the commandToProcess function, at libraries/process/System/Process/Internals.hs:455, the change is just

-   return (cmd, translate cmd ++ "/c " ++ string)
+   return (cmd, translate cmd ++ "/c \"" ++ string ++ "\"")

(And in any case, the examples above should answer this amusing comment, immediately following those lines:

    -- We don't want to put the cmd into a single
    -- argument, because cmd.exe will not try to split it up.  Instead,
    -- we just tack the command on the end of the cmd.exe command line,
    -- which partly works.  There seem to be some quoting issues, but
    -- I don't have the energy to find+fix them right now (ToDo). --SDM
    -- (later) Now I don't know what the above comment means.  sigh.

Later, Brandon comments: What that comment means is that how CMD.EXE handles spaces is Windows-version-dependent. On the other hand, I think it's mostly consistent between XP and Windows 7 --- and I feel sorry for anyone forced to use an older version.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions