12
12
13
13
#![ deny( warnings) ]
14
14
15
+ #[ cfg( not( windows) ) ]
16
+ use std:: fs:: Permissions ;
17
+ #[ cfg( not( windows) ) ]
18
+ use std:: os:: unix:: prelude:: * ;
19
+
15
20
use std:: cmp;
16
21
use std:: env;
17
- use std:: fs:: { self , File , Permissions } ;
22
+ use std:: fs:: { self , File } ;
18
23
use std:: io:: prelude:: * ;
19
24
use std:: io:: { self , BufReader } ;
20
25
use std:: net:: { TcpListener , TcpStream } ;
21
- use std:: os:: unix:: prelude:: * ;
22
26
use std:: path:: { Path , PathBuf } ;
23
- use std:: process:: { Command , Stdio } ;
27
+ use std:: process:: { Command , ExitStatus , Stdio } ;
24
28
use std:: str;
25
29
use std:: sync:: atomic:: { AtomicUsize , Ordering } ;
26
30
use std:: sync:: { Arc , Mutex } ;
@@ -72,21 +76,23 @@ fn main() {
72
76
73
77
let config = Config :: parse_args ( ) ;
74
78
75
- let bind_addr = if cfg ! ( target_os = "android" ) || config. remote {
79
+ let bind_addr = if cfg ! ( target_os = "android" ) || cfg ! ( windows ) || config. remote {
76
80
"0.0.0.0:12345"
77
81
} else {
78
82
"10.0.2.15:12345"
79
83
} ;
80
84
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 ( )
83
90
} else {
84
- ( t ! ( TcpListener :: bind ( bind_addr ) ) , "/tmp/work" )
91
+ "/tmp/work" . into ( )
85
92
} ;
86
93
println ! ( "listening!" ) ;
87
94
88
- let work = Path :: new ( work) ;
89
- t ! ( fs:: create_dir_all( work) ) ;
95
+ t ! ( fs:: create_dir_all( & work) ) ;
90
96
91
97
let lock = Arc :: new ( Mutex :: new ( ( ) ) ) ;
92
98
@@ -99,10 +105,11 @@ fn main() {
99
105
if & buf[ ..] == b"ping" {
100
106
t ! ( socket. write_all( b"pong" ) ) ;
101
107
} else if & buf[ ..] == b"push" {
102
- handle_push ( socket, work) ;
108
+ handle_push ( socket, & work) ;
103
109
} else if & buf[ ..] == b"run " {
104
110
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) ) ;
106
113
} else {
107
114
panic ! ( "unknown command {:?}" , buf) ;
108
115
}
@@ -196,17 +203,28 @@ fn handle_run(socket: TcpStream, work: &Path, lock: &Mutex<()>) {
196
203
let exe = recv ( & path, & mut reader) ;
197
204
198
205
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) ;
205
208
206
209
// Support libraries were uploaded to `work` earlier, so make sure that's
207
210
// in `LD_LIBRARY_PATH`. Also include our own current dir which may have
208
211
// 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
+ }
210
228
211
229
// Spawn the child and ferry over stdout/stderr to the socket in a framed
212
230
// fashion (poor man's style)
@@ -223,10 +241,9 @@ fn handle_run(socket: TcpStream, work: &Path, lock: &Mutex<()>) {
223
241
224
242
// Finally send over the exit status.
225
243
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
+
230
247
t ! ( socket. lock( ) . unwrap( ) . write_all( & [
231
248
which,
232
249
( code >> 24 ) as u8 ,
@@ -236,6 +253,19 @@ fn handle_run(socket: TcpStream, work: &Path, lock: &Mutex<()>) {
236
253
] ) ) ;
237
254
}
238
255
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
+
239
269
fn recv < B : BufRead > ( dir : & Path , io : & mut B ) -> PathBuf {
240
270
let mut filename = Vec :: new ( ) ;
241
271
t ! ( io. read_until( 0 , & mut filename) ) ;
@@ -253,10 +283,17 @@ fn recv<B: BufRead>(dir: &Path, io: &mut B) -> PathBuf {
253
283
let dst = dir. join ( t ! ( str :: from_utf8( & filename[ ..len] ) ) ) ;
254
284
let amt = read_u32 ( io) as u64 ;
255
285
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) ;
257
287
dst
258
288
}
259
289
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
+
260
297
fn my_copy ( src : & mut dyn Read , which : u8 , dst : & Mutex < dyn Write > ) {
261
298
let mut b = [ 0 ; 1024 ] ;
262
299
loop {
0 commit comments