1212
1313#![ deny( warnings) ]
1414
15+ #[ cfg( not( windows) ) ]
16+ use std:: fs:: Permissions ;
17+ #[ cfg( not( windows) ) ]
18+ use std:: os:: unix:: prelude:: * ;
19+
1520use std:: cmp;
1621use std:: env;
17- use std:: fs:: { self , File , Permissions } ;
22+ use std:: fs:: { self , File } ;
1823use std:: io:: prelude:: * ;
1924use std:: io:: { self , BufReader } ;
2025use std:: net:: { TcpListener , TcpStream } ;
21- use std:: os:: unix:: prelude:: * ;
2226use std:: path:: { Path , PathBuf } ;
23- use std:: process:: { Command , Stdio } ;
27+ use std:: process:: { Command , ExitStatus , Stdio } ;
2428use std:: str;
2529use std:: sync:: atomic:: { AtomicUsize , Ordering } ;
2630use std:: sync:: { Arc , Mutex } ;
@@ -72,21 +76,23 @@ fn main() {
7276
7377 let config = Config :: parse_args ( ) ;
7478
75- let bind_addr = if cfg ! ( target_os = "android" ) || config. remote {
79+ let bind_addr = if cfg ! ( target_os = "android" ) || cfg ! ( windows ) || config. remote {
7680 "0.0.0.0:12345"
7781 } else {
7882 "10.0.2.15:12345"
7983 } ;
8084
81- let ( listener, work) = if cfg ! ( target_os = "android" ) {
82- ( t ! ( TcpListener :: bind( bind_addr) ) , "/data/tmp/work" )
85+ let listener = t ! ( TcpListener :: bind( bind_addr) ) ;
86+ let work: PathBuf = if cfg ! ( windows) {
87+ env:: var_os ( "RUST_TEMP" ) . expect ( "Set RUST_TEMP to your preferred temp folder" ) . into ( )
88+ } else if cfg ! ( target_os = "android" ) {
89+ "/data/tmp/work" . into ( )
8390 } else {
84- ( t ! ( TcpListener :: bind ( bind_addr ) ) , "/tmp/work" )
91+ "/tmp/work" . into ( )
8592 } ;
8693 println ! ( "listening!" ) ;
8794
88- let work = Path :: new ( work) ;
89- t ! ( fs:: create_dir_all( work) ) ;
95+ t ! ( fs:: create_dir_all( & work) ) ;
9096
9197 let lock = Arc :: new ( Mutex :: new ( ( ) ) ) ;
9298
@@ -99,10 +105,11 @@ fn main() {
99105 if & buf[ ..] == b"ping" {
100106 t ! ( socket. write_all( b"pong" ) ) ;
101107 } else if & buf[ ..] == b"push" {
102- handle_push ( socket, work) ;
108+ handle_push ( socket, & work) ;
103109 } else if & buf[ ..] == b"run " {
104110 let lock = lock. clone ( ) ;
105- thread:: spawn ( move || handle_run ( socket, work, & lock) ) ;
111+ let work = work. clone ( ) ;
112+ thread:: spawn ( move || handle_run ( socket, & work, & lock) ) ;
106113 } else {
107114 panic ! ( "unknown command {:?}" , buf) ;
108115 }
@@ -196,17 +203,28 @@ fn handle_run(socket: TcpStream, work: &Path, lock: &Mutex<()>) {
196203 let exe = recv ( & path, & mut reader) ;
197204
198205 let mut cmd = Command :: new ( & exe) ;
199- for arg in args {
200- cmd. arg ( arg) ;
201- }
202- for ( k, v) in env {
203- cmd. env ( k, v) ;
204- }
206+ cmd. args ( args) ;
207+ cmd. envs ( env) ;
205208
206209 // Support libraries were uploaded to `work` earlier, so make sure that's
207210 // in `LD_LIBRARY_PATH`. Also include our own current dir which may have
208211 // had some libs uploaded.
209- cmd. env ( "LD_LIBRARY_PATH" , format ! ( "{}:{}" , work. display( ) , path. display( ) ) ) ;
212+ if cfg ! ( windows) {
213+ // On windows, libraries are just searched in the executable directory,
214+ // system directories, PWD, and PATH, in that order. PATH is the only one
215+ // we can change for this.
216+ cmd. env (
217+ "PATH" ,
218+ env:: join_paths (
219+ std:: iter:: once ( work. to_owned ( ) )
220+ . chain ( std:: iter:: once ( path. clone ( ) ) )
221+ . chain ( env:: split_paths ( & env:: var_os ( "PATH" ) . unwrap ( ) ) ) ,
222+ )
223+ . unwrap ( ) ,
224+ ) ;
225+ } else {
226+ cmd. env ( "LD_LIBRARY_PATH" , format ! ( "{}:{}" , work. display( ) , path. display( ) ) ) ;
227+ }
210228
211229 // Spawn the child and ferry over stdout/stderr to the socket in a framed
212230 // fashion (poor man's style)
@@ -223,10 +241,9 @@ fn handle_run(socket: TcpStream, work: &Path, lock: &Mutex<()>) {
223241
224242 // Finally send over the exit status.
225243 let status = t ! ( child. wait( ) ) ;
226- let ( which, code) = match status. code ( ) {
227- Some ( n) => ( 0 , n) ,
228- None => ( 1 , status. signal ( ) . unwrap ( ) ) ,
229- } ;
244+
245+ let ( which, code) = get_status_code ( & status) ;
246+
230247 t ! ( socket. lock( ) . unwrap( ) . write_all( & [
231248 which,
232249 ( code >> 24 ) as u8 ,
@@ -236,6 +253,19 @@ fn handle_run(socket: TcpStream, work: &Path, lock: &Mutex<()>) {
236253 ] ) ) ;
237254}
238255
256+ #[ cfg( not( windows) ) ]
257+ fn get_status_code ( status : & ExitStatus ) -> ( u8 , i32 ) {
258+ match status. code ( ) {
259+ Some ( n) => ( 0 , n) ,
260+ None => ( 1 , status. signal ( ) . unwrap ( ) ) ,
261+ }
262+ }
263+
264+ #[ cfg( windows) ]
265+ fn get_status_code ( status : & ExitStatus ) -> ( u8 , i32 ) {
266+ ( 0 , status. code ( ) . unwrap ( ) )
267+ }
268+
239269fn recv < B : BufRead > ( dir : & Path , io : & mut B ) -> PathBuf {
240270 let mut filename = Vec :: new ( ) ;
241271 t ! ( io. read_until( 0 , & mut filename) ) ;
@@ -253,10 +283,17 @@ fn recv<B: BufRead>(dir: &Path, io: &mut B) -> PathBuf {
253283 let dst = dir. join ( t ! ( str :: from_utf8( & filename[ ..len] ) ) ) ;
254284 let amt = read_u32 ( io) as u64 ;
255285 t ! ( io:: copy( & mut io. take( amt) , & mut t!( File :: create( & dst) ) ) ) ;
256- t ! ( fs :: set_permissions( & dst, Permissions :: from_mode ( 0o755 ) ) ) ;
286+ set_permissions ( & dst) ;
257287 dst
258288}
259289
290+ #[ cfg( not( windows) ) ]
291+ fn set_permissions ( path : & Path ) {
292+ t ! ( fs:: set_permissions( & dst, Permissions :: from_mode( 0o755 ) ) ) ;
293+ }
294+ #[ cfg( windows) ]
295+ fn set_permissions ( _path : & Path ) { }
296+
260297fn my_copy ( src : & mut dyn Read , which : u8 , dst : & Mutex < dyn Write > ) {
261298 let mut b = [ 0 ; 1024 ] ;
262299 loop {
0 commit comments