Skip to content

Commit

Permalink
Add file redirection
Browse files Browse the repository at this point in the history
  • Loading branch information
Keno committed Jan 9, 2013
1 parent 258bf64 commit 5e63bba
Show file tree
Hide file tree
Showing 9 changed files with 73 additions and 44 deletions.
5 changes: 4 additions & 1 deletion base/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ include ../Make.inc

PCRE_CONST = 0x[0-9a-fA-F]+|[-+]?\s*[0-9]+

all: pcre_h.jl errno_h.jl build_h.jl file_constants.jl
all: pcre_h.jl errno_h.jl build_h.jl file_constants.jl uv_constants.jl

pcre_h.jl:
$(QUIET_PERL) $(CPP) -dM $(shell $(PCRE_CONFIG) --prefix)/include/pcre.h | perl -nle '/^\s*#define\s+PCRE_(\w*)\s*\(?($(PCRE_CONST))\)?\s*$$/ and print "const $$1 = uint32($$2)"' | sort > $@
Expand All @@ -14,6 +14,9 @@ errno_h.jl:
file_constants.jl: ../src/file_constants.h
$(QUIET_PERL) ${CC} -E -P -DJULIA ../src/file_constants.h | perl -nle 'print "$$1" if /^(\s*const\s+[A-z_]+\s+=\s+[0-9A-z_]+\s*)$$/' > $@

uv_constants.jl: ../src/uv_constants.h
$(QUIET_PERL) ${CC} -E -P -I"../deps/libuv/include" -DJULIA ../src/uv_constants.h | tail -n 5 > $@

build_h.jl: ../Make.inc ../src/os_detect.h
$(QUIET_PERL) $(CC) -E -P -DJULIA ../src/os_detect.h | grep OS_NAME > $@
@echo "const libm_name = \"$(LIBMNAME)\"" >> $@
Expand Down
27 changes: 23 additions & 4 deletions base/fs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,27 @@
module FS
using Base

const S_IRUSR = 0o400
const S_IWUSR = 0o200
const S_IXUSR = 0o100
const S_IRWXU = S_IRUSR+S_IWUSR+S_IXUSR
const S_IRGRP = 0o040
const S_IWGRP = 0o020
const S_IXGRP = 0o010
const S_IRWXG = S_IRGRP+S_IWGRP+S_IXGRP
const S_IROTH = 0o004
const S_IWOTH = 0o002
const S_IXOTH = 0o001
const S_IRWXO = S_IROTH+S_IWOTH+S_IXOTH

export File, open, close, unlink, write,
JL_O_WRONLY, JL_O_RDONLY, JL_O_RDWR, JL_O_APPEND, JL_O_CREAT, JL_O_EXCL,
JL_O_TRUNC, JL_O_TEMPORARY, JL_O_SHORT_LIVED, JL_O_SEQUENTIAL, JL_O_RANDOM
JL_O_TRUNC, JL_O_TEMPORARY, JL_O_SHORT_LIVED, JL_O_SEQUENTIAL, JL_O_RANDOM,
S_IRUSR, S_IWUSR, S_IXUSR, S_IRWXU, S_IRGRP, S_IWGRP, S_IXGRP, S_IRWXG,
S_IROTH, S_IWOTH, S_IXOTH, S_IRWXO

#import Base.show, Base.open, Base.close, Base.write
import Base.uvtype, Base.uvhandle

include("file_constants.jl")

Expand All @@ -27,19 +43,22 @@ type AsyncFile <: AbstractFile
open::Bool
end

uvtype(::File) = Base.UV_RAW_FD
uvhandle(file::File) = file.handle

_uv_fs_result(req) = ccall(:jl_uv_fs_result,Int32,(Ptr{Void},),req)

function open(f::File,flags::Integer)
function open(f::File,flags::Integer,mode::Integer)
req = Base.Intrinsics.box(Ptr{Void},Intrinsics.jl_alloca(Base.Intrinsics.unbox(Int32,_sizeof_uv_fs_t)))
ccall(:uv_fs_open,Int32,(Ptr{Void},Ptr{Void},Ptr{Uint8},Int32,Int32,Ptr{Void}),
globalEventLoop(),req,bytestring(f.path),flags,0,C_NULL)
globalEventLoop(),req,bytestring(f.path),flags,mode,C_NULL)
uv_error(:open)
f.handle = _uv_fs_result(req)
f.open = true
ccall(:uv_fs_req_cleanup,Void,(Ptr{Void},),req)
f
end
open(f::String,flags::Integer) = open(File(f),flags)
open(f::String,flags,mode) = open(File(f),flags,mode)

function close(f::File)
if(!f.open)
Expand Down
50 changes: 25 additions & 25 deletions base/process.jl
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,11 @@ const STDIN_NO = 0
const STDOUT_NO = 1
const STDERR_NO = 2

type StreamRedirect <: AbstractCmd
typealias Redirectable Union(UVStream,FS.File)

type CmdRedirect <: AbstractCmd
cmd::AbstractCmd
stream::UVStream
handle::Redirectable
stream_no::Int
end

Expand All @@ -92,9 +94,13 @@ ignorestatus(cmd::Union(OrCmds,AndCmds)) = (ignorestatus(cmd.a); ignorestatus(cm

(&)(left::AbstractCmd,right::AbstractCmd) = AndCmds(left,right)
(|)(src::AbstractCmd,dest::AbstractCmd) = OrCmds(src,dest)
(<)(left::AbstractCmd,right::UVStream) = StreamRedirect(left,right,STDIN_NO)
(>)(left::AbstractCmd,right::UVStream) = StreamRedirect(left,right,STDOUT_NO)
(<)(left::AbstractCmd,right::Redirectable) = CmdRedirect(left,right,STDIN_NO)
(>)(left::AbstractCmd,right::Redirectable) = CmdRedirect(left,right,STDOUT_NO)
(<)(left::AbstractCmd,right::String) = left < FS.open(right,JL_O_RDONLY)
(>)(left::AbstractCmd,right::String) = left > FS.open(right,JL_O_WRONLY|JL_O_CREAT,S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)

typealias RawOrBoxedHandle Union(UVHandle,UVStream,FS.File)
typealias StdIOSet (RawOrBoxedHandle, RawOrBoxedHandle, RawOrBoxedHandle)

type Process
cmd::Cmd
Expand Down Expand Up @@ -136,13 +142,17 @@ type SpawnNullStream <: AsyncStream end
const null_handle = SpawnNullStream()
SpawnNullStream() = null_handle
copy(::SpawnNullStream) = null_handle
handle(::SpawnNullStream) = C_NULL
uvhandle(::SpawnNullStream) = C_NULL
uvhandle(x::Ptr) = x
uvtype(::Ptr) = UV_STREAM

function _jl_spawn(cmd::Ptr{Uint8}, argv::Ptr{Ptr{Uint8}}, loop::Ptr{Void}, pp::Process,
in::Ptr{Void}, out::Ptr{Void}, err::Ptr{Void})
in, out, err)
return ccall(:jl_spawn, Ptr{Void},
(Ptr{Uint8}, Ptr{Ptr{Uint8}}, Ptr{Void}, Process, Ptr{Void}, Ptr{Void}, Ptr{Void}),
cmd, argv, loop, pp, in, out, err)
(Ptr{Uint8}, Ptr{Ptr{Uint8}}, Ptr{Void}, Process, Int32,
Ptr{Void}, Int32, Ptr{Void}, Int32, Ptr{Void}),
cmd, argv, loop, pp, uvtype(in),
uvhandle(in), uvtype(out), uvhandle(out), uvtype(err), uvhandle(err))
end

function _uv_hook_return_spawn(proc::Process, exit_status::Int32, term_signal::Int32)
Expand All @@ -161,31 +171,26 @@ end
function spawn(pc::ProcessChainOrNot,cmd::Cmd,stdios::StdIOSet,exitcb::Callback,closecb::Callback)
loop = globalEventLoop()
close_in,close_out,close_err = false,false,false
pp = Process(cmd,C_NULL,stdios[1],stdios[2],stdios[3]);
in,out,err=stdios
if(isa(stdios[1],NamedPipe)&&stdios[1].handle==C_NULL)
in = box(Ptr{Void},Intrinsics.jl_alloca(unbox(Int32,_sizeof_uv_pipe)))
#in = c_malloc(_sizeof_uv_pipe)
link_pipe(in,false,stdios[1],true)
close_in = true
else
in = handle(stdios[1])
end
if(isa(stdios[2],NamedPipe)&&stdios[2].handle==C_NULL)
out = box(Ptr{Void},Intrinsics.jl_alloca(unbox(Int32,_sizeof_uv_pipe)))
#out = c_malloc(_sizeof_uv_pipe)
link_pipe(stdios[2],false,out,true)
close_out = true
else
out = handle(stdios[2])
end
if(isa(stdios[3],NamedPipe)&&stdios[3].handle==C_NULL)
err = box(Ptr{Void},Intrinsics.jl_alloca(unbox(Int32,_sizeof_uv_pipe)))
#err = c_malloc(_sizof_uv_pipe)
link_pipe(stdios[3],false,err,true)
close_err = true
else
err = handle(stdios[3])
end
pp = Process(cmd,C_NULL,stdios[1],stdios[2],stdios[3]);
ptrs = _jl_pre_exec(cmd.exec)
pp.exitcb = exitcb
pp.closecb = closecb
Expand All @@ -209,10 +214,10 @@ function spawn(pc::ProcessChainOrNot,cmd::Cmd,stdios::StdIOSet,exitcb::Callback,
pp
end

function spawn(pc::ProcessChainOrNot,redirect::StreamRedirect,stdios::StdIOSet,exitcb::Callback,closecb::Callback)
spawn(pc,redirect.cmd,(redirect.stream_no==STDIN_NO ?redirect.stream:stdios[1],
redirect.stream_no==STDOUT_NO?redirect.stream:stdios[2],
redirect.stream_no==STDERR_NO?redirect.stream:stdios[3]),exitcb,closecb)
function spawn(pc::ProcessChainOrNot,redirect::CmdRedirect,stdios::StdIOSet,exitcb::Callback,closecb::Callback)
spawn(pc,redirect.cmd,(redirect.stream_no==STDIN_NO ?redirect.handle:stdios[1],
redirect.stream_no==STDOUT_NO?redirect.handle:stdios[2],
redirect.stream_no==STDERR_NO?redirect.handle:stdios[3]),exitcb,closecb)
end

function spawn(pc::ProcessChainOrNot,cmds::OrCmds,stdios::StdIOSet,exitcb::Callback,closecb::Callback)
Expand Down Expand Up @@ -242,29 +247,24 @@ function spawn(pc::ProcessChainOrNot,cmds::AndCmds,stdios::StdIOSet,exitcb::Call
pc = ProcessChain(stdios)
end
close_in,close_out,close_err = false,false,false
in,out,err = stdios
if(isa(stdios[1],NamedPipe)&&stdios[1].handle==C_NULL)
in = box(Ptr{Void},Intrinsics.jl_alloca(unbox(Int32,_sizeof_uv_pipe)))
#in = c_malloc(_sizeof_uv_pipe)
link_pipe(in,false,stdios[1],true)
close_in = true
else
in = handle(stdios[1])
end
if(isa(stdios[2],NamedPipe)&&stdios[2].handle==C_NULL)
out = box(Ptr{Void},Intrinsics.jl_alloca(unbox(Int32,_sizeof_uv_pipe)))
#out = c_malloc(_sizeof_uv_pipe)
link_pipe(stdios[2],false,out,true)
close_out = true
else
out = handle(stdios[2])
end
if(isa(stdios[3],NamedPipe)&&stdios[3].handle==C_NULL)
err = box(Ptr{Void},Intrinsics.jl_alloca(unbox(Int32,_sizeof_uv_pipe)))
#err = c_malloc(_sizof_uv_pipe)
link_pipe(stdios[3],false,err,true)
close_err = true
else
err = handle(stdios[3])
end
spawn(pc, cmds.a, (in,out,err), exitcb, closecb)
spawn(pc, cmds.b, (in,out,err), exitcb, closecb)
Expand Down
6 changes: 4 additions & 2 deletions base/stream.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#TODO: Move stdio detection from C to Julia (might require some Clang magic)
include("uv_constants.jl")

## types ##

Expand All @@ -16,8 +17,6 @@ abstract AsyncStream <: Stream

typealias UVHandle Ptr{Void}
typealias UVStream AsyncStream
typealias RawOrBoxedHandle Union(UVHandle,UVStream)
typealias StdIOSet (RawOrBoxedHandle, RawOrBoxedHandle, RawOrBoxedHandle)

const _sizeof_uv_pipe = ccall(:jl_sizeof_uv_pipe_t,Int32,())

Expand Down Expand Up @@ -94,6 +93,9 @@ type UdpSocket <: Socket
end
end

uvtype(::AsyncStream) = UV_STREAM
uvhandle(stream::AsyncStream) = stream.handle

show(io,sock::UdpSocket) = print(io,"TcpSocket(",sock.open?"connected,":"disconnected,",nb_available(sock.buffer)," bytes waiting)")

copy(s::TTY) = TTY(s.handle,s.open)
Expand Down
4 changes: 2 additions & 2 deletions base/sysimg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,10 @@ include("inference.jl")
include("io.jl")
include("iostring.jl")
include("stream.jl")
include("process.jl")
include("fs.jl")
ccall(:jl_get_uv_hooks, Void, ())
using FS
include("process.jl")
ccall(:jl_get_uv_hooks, Void, ())
include("char.jl")
include("ascii.jl")
include("utf8.jl")
Expand Down
5 changes: 5 additions & 0 deletions base/uv_constants.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const UV_UNKNOWN_HANDLE = 0
handles = [:UV_ASYNC, :UV_CHECK, :UV_FS_EVENT, :UV_FS_POLL, :UV_HANDLE, :UV_IDLE, :UV_NAMED_PIPE, :UV_POLL, :UV_PREPARE, :UV_PROCESS, :UV_STREAM, :UV_TCP, :UV_TIMER, :UV_TTY, :UV_UDP, :UV_SIGNAL, :UV_FILE, :UV_HANDLE_TYPE_MAX, :UV_RAW_FD, :UV_RAW_HANDLE]
for i=1:(length(handles))
@eval const $(handles[i]) = $i
end
2 changes: 1 addition & 1 deletion base/version.jl
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ let
println("Warning: git failed in version.jl")
#println(err) # not a useful error msg currently
else
error(err)
rethrow(err)
end
end
end
Expand Down
6 changes: 3 additions & 3 deletions src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -781,9 +781,9 @@ DLLEXPORT jl_value_t *jl_env_done(char *pos);

DLLEXPORT uv_process_t *jl_spawn(char *name, char **argv, uv_loop_t *loop,
jl_value_t *julia_struct,
uv_pipe_t *stdin_pipe,
uv_pipe_t *stdout_pipe,
uv_pipe_t *stderr_pipe);
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);
DLLEXPORT void jl_run_event_loop(uv_loop_t *loop);
DLLEXPORT void jl_process_events(uv_loop_t *loop);

Expand Down
12 changes: 6 additions & 6 deletions src/wrapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,9 +257,9 @@ DLLEXPORT int jl_listen(uv_stream_t* stream, int backlog)
#endif
DLLEXPORT uv_process_t *jl_spawn(char *name, char **argv, uv_loop_t *loop,
jl_value_t *julia_struct,
uv_pipe_t *stdin_pipe,
uv_pipe_t *stdout_pipe,
uv_pipe_t *stderr_pipe)
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)
{
#ifdef __APPLE__
char **environ = *_NSGetEnviron();
Expand All @@ -279,11 +279,11 @@ DLLEXPORT uv_process_t *jl_spawn(char *name, char **argv, uv_loop_t *loop,
opts.flags = 0;
opts.stdio = stdio;
opts.stdio_count = 3;
stdio[0].type = UV_STREAM;
stdio[0].type = stdin_type;
stdio[0].data.stream = (uv_stream_t*)(stdin_pipe);
stdio[1].type = UV_STREAM;
stdio[1].type = stdout_type;
stdio[1].data.stream = (uv_stream_t*)(stdout_pipe);
stdio[2].type = UV_STREAM;
stdio[2].type = stderr_type;
stdio[2].data.stream = (uv_stream_t*)(stderr_pipe);
//opts.detached = 0; #This has been removed upstream to be uncommented once it is possible again
opts.exit_cb = &jl_return_spawn;
Expand Down

0 comments on commit 5e63bba

Please sign in to comment.