@@ -98,8 +98,8 @@ impl Process {
98
98
99
99
let env = config. env . map ( |a| a. to_owned ( ) ) ;
100
100
let cwd = config. cwd . map ( |a| Path :: new ( a) ) ;
101
- let res = spawn_process_os ( config. program , config . args , env ,
102
- cwd . as_ref ( ) , in_fd , out_fd , err_fd) ;
101
+ let res = spawn_process_os ( config, env , cwd . as_ref ( ) , in_fd , out_fd ,
102
+ err_fd) ;
103
103
104
104
unsafe {
105
105
for pipe in in_pipe. iter ( ) { let _ = libc:: close ( pipe. input ) ; }
@@ -180,7 +180,7 @@ struct SpawnProcessResult {
180
180
}
181
181
182
182
#[ cfg( windows) ]
183
- fn spawn_process_os ( prog : & str , args : & [ ~ str ] ,
183
+ fn spawn_process_os ( config : p :: ProcessConfig ,
184
184
env : Option < ~[ ( ~str , ~str ) ] > ,
185
185
dir : Option < & Path > ,
186
186
in_fd : c_int , out_fd : c_int ,
@@ -202,6 +202,14 @@ fn spawn_process_os(prog: &str, args: &[~str],
202
202
203
203
use std:: mem;
204
204
205
+ if config. gid . is_some ( ) || config. uid . is_some ( ) {
206
+ return Err ( io:: IoError {
207
+ kind : io:: OtherIoError ,
208
+ desc : "unsupported gid/uid requested on windows" ,
209
+ detail : None ,
210
+ } )
211
+ }
212
+
205
213
unsafe {
206
214
207
215
let mut si = zeroed_startupinfo ( ) ;
@@ -237,16 +245,23 @@ fn spawn_process_os(prog: &str, args: &[~str],
237
245
fail ! ( "failure in DuplicateHandle: {}" , os:: last_os_error( ) ) ;
238
246
}
239
247
240
- let cmd = make_command_line ( prog , args) ;
248
+ let cmd = make_command_line ( config . program , config . args ) ;
241
249
let mut pi = zeroed_process_information ( ) ;
242
250
let mut create_err = None ;
243
251
252
+ // stolen from the libuv code.
253
+ let mut flags = 0 ;
254
+ if config. detach {
255
+ flags |= libc:: DETACHED_PROCESS | libc:: CREATE_NEW_PROCESS_GROUP ;
256
+ }
257
+
244
258
with_envp ( env, |envp| {
245
259
with_dirp ( dir, |dirp| {
246
260
cmd. with_c_str ( |cmdp| {
247
261
let created = CreateProcessA ( ptr:: null ( ) , cast:: transmute ( cmdp) ,
248
262
ptr:: mut_null ( ) , ptr:: mut_null ( ) , TRUE ,
249
- 0 , envp, dirp, & mut si, & mut pi) ;
263
+ flags, envp, dirp, & mut si,
264
+ & mut pi) ;
250
265
if created == FALSE {
251
266
create_err = Some ( super :: last_error ( ) ) ;
252
267
}
@@ -364,15 +379,14 @@ fn make_command_line(prog: &str, args: &[~str]) -> ~str {
364
379
}
365
380
366
381
#[ cfg( unix) ]
367
- fn spawn_process_os ( prog : & str , args : & [ ~ str ] ,
382
+ fn spawn_process_os ( config : p :: ProcessConfig ,
368
383
env : Option < ~[ ( ~str , ~str ) ] > ,
369
384
dir : Option < & Path > ,
370
385
in_fd : c_int , out_fd : c_int ,
371
386
err_fd : c_int ) -> IoResult < SpawnProcessResult > {
372
387
use std:: libc:: funcs:: posix88:: unistd:: { fork, dup2, close, chdir, execvp} ;
373
388
use std:: libc:: funcs:: bsd44:: getdtablesize;
374
389
use std:: libc:: c_ulong;
375
- use std:: unstable:: intrinsics;
376
390
377
391
mod rustrt {
378
392
extern {
@@ -441,22 +455,34 @@ fn spawn_process_os(prog: &str, args: &[~str],
441
455
}
442
456
drop ( input) ;
443
457
458
+ fn fail ( output : & mut file:: FileDesc ) -> ! {
459
+ let errno = os:: errno ( ) ;
460
+ let bytes = [
461
+ ( errno << 24 ) as u8 ,
462
+ ( errno << 16 ) as u8 ,
463
+ ( errno << 8 ) as u8 ,
464
+ ( errno << 0 ) as u8 ,
465
+ ] ;
466
+ assert ! ( output. inner_write( bytes) . is_ok( ) ) ;
467
+ unsafe { libc:: _exit ( 1 ) }
468
+ }
469
+
444
470
rustrt:: rust_unset_sigprocmask ( ) ;
445
471
446
472
if in_fd == -1 {
447
473
let _ = libc:: close ( libc:: STDIN_FILENO ) ;
448
474
} else if retry ( || dup2 ( in_fd, 0 ) ) == -1 {
449
- fail ! ( "failure in dup2(in_fd, 0): {}" , os :: last_os_error ( ) ) ;
475
+ fail ( & mut output ) ;
450
476
}
451
477
if out_fd == -1 {
452
478
let _ = libc:: close ( libc:: STDOUT_FILENO ) ;
453
479
} else if retry ( || dup2 ( out_fd, 1 ) ) == -1 {
454
- fail ! ( "failure in dup2(out_fd, 1): {}" , os :: last_os_error ( ) ) ;
480
+ fail ( & mut output ) ;
455
481
}
456
482
if err_fd == -1 {
457
483
let _ = libc:: close ( libc:: STDERR_FILENO ) ;
458
484
} else if retry ( || dup2 ( err_fd, 2 ) ) == -1 {
459
- fail ! ( "failure in dup3(err_fd, 2): {}" , os :: last_os_error ( ) ) ;
485
+ fail ( & mut output ) ;
460
486
}
461
487
// close all other fds
462
488
for fd in range ( 3 , getdtablesize ( ) ) . rev ( ) {
@@ -465,9 +491,44 @@ fn spawn_process_os(prog: &str, args: &[~str],
465
491
}
466
492
}
467
493
494
+ match config. gid {
495
+ Some ( u) => {
496
+ if libc:: setgid ( u as libc:: gid_t ) != 0 {
497
+ fail ( & mut output) ;
498
+ }
499
+ }
500
+ None => { }
501
+ }
502
+ match config. uid {
503
+ Some ( u) => {
504
+ // When dropping privileges from root, the `setgroups` call will
505
+ // remove any extraneous groups. If we don't call this, then
506
+ // even though our uid has dropped, we may still have groups
507
+ // that enable us to do super-user things. This will fail if we
508
+ // aren't root, so don't bother checking the return value, this
509
+ // is just done as an optimistic privilege dropping function.
510
+ extern {
511
+ fn setgroups ( ngroups : libc:: c_int ,
512
+ ptr : * libc:: c_void ) -> libc:: c_int ;
513
+ }
514
+ let _ = setgroups ( 0 , 0 as * libc:: c_void ) ;
515
+
516
+ if libc:: setuid ( u as libc:: uid_t ) != 0 {
517
+ fail ( & mut output) ;
518
+ }
519
+ }
520
+ None => { }
521
+ }
522
+ if config. detach {
523
+ // Don't check the error of setsid because it fails if we're the
524
+ // process leader already. We just forked so it shouldn't return
525
+ // error, but ignore it anyway.
526
+ let _ = libc:: setsid ( ) ;
527
+ }
528
+
468
529
with_dirp ( dir, |dirp| {
469
530
if !dirp. is_null ( ) && chdir ( dirp) == -1 {
470
- fail ! ( "failure in chdir: {}" , os :: last_os_error ( ) ) ;
531
+ fail ( & mut output ) ;
471
532
}
472
533
} ) ;
473
534
@@ -476,17 +537,9 @@ fn spawn_process_os(prog: &str, args: &[~str],
476
537
set_environ ( envp) ;
477
538
}
478
539
} ) ;
479
- with_argv ( prog , args, |argv| {
540
+ with_argv ( config . program , config . args , |argv| {
480
541
let _ = execvp ( * argv, argv) ;
481
- let errno = os:: errno ( ) ;
482
- let bytes = [
483
- ( errno << 24 ) as u8 ,
484
- ( errno << 16 ) as u8 ,
485
- ( errno << 8 ) as u8 ,
486
- ( errno << 0 ) as u8 ,
487
- ] ;
488
- assert ! ( output. inner_write( bytes) . is_ok( ) ) ;
489
- intrinsics:: abort ( ) ;
542
+ fail ( & mut output) ;
490
543
} )
491
544
}
492
545
}
0 commit comments