[gambit-list] shell-command failing in Gambit 4.6.2 (MinGW build)

REPLeffect repleffect at gmail.com
Tue Jan 17 13:11:38 EST 2012


On Tue, Jan 17, 2012 at 10:07 AM, Marc Feeley <feeley at iro.umontreal.ca> wrote:
>
> On 2012-01-17, at 3:01 AM, REPLeffect wrote:
>
>> All of these tests were run against the current prebuilt versions of
>> Gambit 4.6.0 and 4.6.2 downloaded from Gambit's web site.
>>
>> I'll be happy to test any patches or other changes needed to fix this problem.
>
> The implementation of the shell-command procedure is tricky.  On Unix, the tradition of using /bin/sh is maintained.  On Windows there are options: CMD.EXE, COMMAND.COM and sh (when MSYS or CYGWIN are installed).  If MSYS or CYGWIN are installed and Gambit was launched from a shell in those environments, then it is reasonable to think that the user is executing shell-commands which make sense for those environments (for example, using "ls" instead of "dir").  Other users might expect or prefer the default Windows shell.
>
> The implementation of shell-command tries to figure this out to start the correct shell to process the command.  The logic is a bit brittle, and as you have experienced, it guessed the wrong shell.
>
> I'm attaching below a new implementation of shell-command which does a better job.  Can you try it out and let me know if it works for you?  If you know of better heuristics, let me know!
>
> Marc
>
>
> (define ##shell-program #f)
>
> (define (##get-shell-program)
>
>  (define unix-shell-program    '("/bin/sh" . "-c"))
>  (define windows-shell-program '("CMD.EXE" . "/C"))
>  (define default-shell-program '("sh"      . "-c"))
>
>  (or ##shell-program
>      (let ((sp
>             (if (##file-exists? (##car unix-shell-program))
>                 unix-shell-program
>                 (if (##getenv "HOME" #f)
>                     default-shell-program
>                     (let ((comspec (##getenv "COMSPEC" #f)))
>                       (if comspec
>                           (##cons comspec "/C")
>                           windows-shell-program))))))
>        (set! ##shell-program sp)
>        sp)))
>
> (define (shell-command cmd)
>  (let* ((shell-prog
>          (##get-shell-program))
>         (path-or-settings
>          (##list path: (##car shell-prog)
>                  arguments:
>                  (##list
>                   (##cdr shell-prog)
>                   cmd)
>                  stdin-redirection: #f
>                  stdout-redirection: #f
>                  stderr-redirection: #f)))
>    (##open-process-generic
>     3;(macro-direction-inout)
>     #t
>     (lambda (port)
>       (##close-port port)
>       (##process-status port))
>     open-process
>     path-or-settings)))
>

Marc,

  That implemenation fixes the problem where running gsi in the
standard cmd.exe shell had failed before, and I get the results I
would expect when running (shell-command "dir 1 2 3").

However, when I run gsi from the MinGW Msys shell, and then run
(shell-command "ls 1 2 3"), I still get the results you would expect
from running (shell-command "ls") -- that is, there is no error, and
it displays the contents of the current directory, rather than trying
to list the files named "1" "2" and "3".  Running under gdb again, I
see that the command string returned from argv_to_cmd is "sh -c ls 1 2
3" -- just as it was in my previous testing.

So, next I ran gdb in the cmd.exe shell, and debugged gsi from there
(setting the same breakpoint in argv_to_cmd):

Breakpoint 1, argv_to_ccmd (argv=0x1281648) at os_io.c:6817
6817      return ccmd;
(gdb) p ccmd
$1 = 0x1281740 "C:\\WINDOWS\\system32\\cmd.exe /C dir 1 2 3"

Here again, the command being executed does not have quotes around it.
 It just so happens that under cmd.exe, that doesn't matter.  You get
the same results if you execute this:

  cmd.exe /c dir 1 2 3

that you get if you execute this:

  cmd.exe /c "dir 1 2 3"

However, if from the MinGW Msys shell you execute this:

  sh -c ls 1 2 3

You will *not* get a listing of the files named "1" "2" and "3".  You
will get a listing of the current directory, just as if you had
executed "sh -c ls".

However, executing this:

  sh -c "ls 1 2 3"

gives the results you would expect:

  ls: 1: No such file or directory
  ls: 2: No such file or directory
  ls: 3: No such file or directory



More information about the Gambit-list mailing list