Skip to content

Commit

Permalink
Allow built-in commands in shell mode for Windows
Browse files Browse the repository at this point in the history
- build a command string for windows where we quote arguments containing
  special characters (whitespace and &()[]{}^=;!'+,`~).
- use cmd /s /c "string" to run the command without modifying the quoting
- add a "verbatimargument" input parameter to jl_spawn(), which passes the
  flag UV_PROCESS_WINDOW_VERBATIM_ARGUMENTS to libuv, also in order no to
  change the quoting
- make Cmd pass the same flag to jl_spawn()
  • Loading branch information
ncnc committed May 29, 2015
1 parent 6b4c275 commit 1f19262
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 5 deletions.
12 changes: 12 additions & 0 deletions base/client.jl
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,18 @@ function repl_cmd(cmd, out)
ENV["OLDPWD"] = new_oldpwd
println(out, pwd())
else
@windows_only begin
# build correctly quoted string for cmd.exe
special = r".*[ &()[\]{}\^=;!'+,`~]+.*"
cmdstr, sep = "", ""
for s in cmd.exec
dq = ismatch(special, s) ? "\"" : ""
cmdstr = cmdstr * sep * dq * s * dq
sep = " "
end
cmd.exec = ["cmd"; "/s /c \"" * cmdstr * "\""]
cmd.verbatimargument = true
end
run(ignorestatus(@windows? cmd : (isa(STDIN, TTY) ? `$shell -i -c "($(shell_escape(cmd))) && true"` : `$shell -c "($(shell_escape(cmd))) && true"`)))
end
nothing
Expand Down
10 changes: 7 additions & 3 deletions base/process.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ type Cmd <: AbstractCmd
exec::Vector{ByteString}
ignorestatus::Bool
detach::Bool
verbatimargument::Bool
env::Union(Array{ByteString},Void)
dir::UTF8String
Cmd(exec::Vector{ByteString}) = new(exec, false, false, nothing, "")
Cmd(exec::Vector{ByteString}) = new(exec, false, false, false, nothing, "")
end

type OrCmds <: AbstractCmd
Expand Down Expand Up @@ -215,10 +216,13 @@ function _jl_spawn(cmd, argv, loop::Ptr{Void}, pp::Process,
proc = Libc.malloc(_sizeof_uv_process)
error = ccall(:jl_spawn, Int32,
(Ptr{UInt8}, Ptr{Ptr{UInt8}}, Ptr{Void}, Ptr{Void}, Any, Int32,
Ptr{Void}, Int32, Ptr{Void}, Int32, Ptr{Void}, Int32, Ptr{Ptr{UInt8}}, Ptr{UInt8}),
Ptr{Void}, Int32, Ptr{Void}, Int32, Ptr{Void}, Int32, Int32,
Ptr{Ptr{UInt8}}, Ptr{UInt8}),
cmd, argv, loop, proc, pp, uvtype(in),
uvhandle(in), uvtype(out), uvhandle(out), uvtype(err), uvhandle(err),
pp.cmd.detach, pp.cmd.env === nothing ? C_NULL : pp.cmd.env, isempty(pp.cmd.dir) ? C_NULL : pp.cmd.dir)
pp.cmd.detach, pp.cmd.verbatimargument,
pp.cmd.env === nothing ? C_NULL : pp.cmd.env,
isempty(pp.cmd.dir) ? C_NULL : pp.cmd.dir)
if error != 0
disassociate_julia_struct(proc)
ccall(:jl_forceclose_uv, Void, (Ptr{Void},), proc)
Expand Down
4 changes: 3 additions & 1 deletion src/jl_uv.c
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ DLLEXPORT int jl_spawn(char *name, char **argv, uv_loop_t *loop,
uv_handle_type stdin_type, uv_pipe_t *stdin_pipe,
uv_handle_type stdout_type, uv_pipe_t *stdout_pipe,
uv_handle_type stderr_type, uv_pipe_t *stderr_pipe,
int detach, char **env, char *cwd)
int detach, int verbatimargument, char **env, char *cwd)
{
uv_process_options_t opts;
uv_stdio_container_t stdio[3];
Expand All @@ -372,6 +372,8 @@ DLLEXPORT int jl_spawn(char *name, char **argv, uv_loop_t *loop,
opts.args = argv;
if (detach)
opts.flags |= UV_PROCESS_DETACHED;
if (verbatimargument)
opts.flags |= UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS;
opts.stdio = stdio;
opts.stdio_count = 3;
stdio[0].type = stdin_type;
Expand Down
2 changes: 1 addition & 1 deletion src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -1453,7 +1453,7 @@ DLLEXPORT int jl_spawn(char *name, char **argv, uv_loop_t *loop,
uv_handle_type stdin_type,uv_pipe_t *stdin_pipe,
uv_handle_type stdout_type,uv_pipe_t *stdout_pipe,
uv_handle_type stderr_type,uv_pipe_t *stderr_pipe,
int detach, char **env, char *cwd);
int detach, int verbatimargument, char **env, char *cwd);
DLLEXPORT void jl_run_event_loop(uv_loop_t *loop);
DLLEXPORT int jl_run_once(uv_loop_t *loop);
DLLEXPORT int jl_process_events(uv_loop_t *loop);
Expand Down

0 comments on commit 1f19262

Please sign in to comment.