10
10
11
11
//! Working with processes.
12
12
13
- #![ unstable ( feature = "process" , reason = "recently added via RFC 579 " ) ]
13
+ #![ stable ( feature = "process" , since = "1.0.0 " ) ]
14
14
#![ allow( non_upper_case_globals) ]
15
15
16
16
use prelude:: v1:: * ;
@@ -48,27 +48,33 @@ use thread;
48
48
/// let contents = output.stdout;
49
49
/// assert!(output.status.success());
50
50
/// ```
51
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
51
52
pub struct Child {
52
53
handle : ProcessImp ,
53
54
54
55
/// None until wait() or wait_with_output() is called.
55
56
status : Option < ExitStatusImp > ,
56
57
57
58
/// The handle for writing to the child's stdin, if it has been captured
59
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
58
60
pub stdin : Option < ChildStdin > ,
59
61
60
62
/// The handle for reading from the child's stdout, if it has been captured
63
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
61
64
pub stdout : Option < ChildStdout > ,
62
65
63
66
/// The handle for reading from the child's stderr, if it has been captured
67
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
64
68
pub stderr : Option < ChildStderr > ,
65
69
}
66
70
67
71
/// A handle to a child procesess's stdin
72
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
68
73
pub struct ChildStdin {
69
74
inner : AnonPipe
70
75
}
71
76
77
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
72
78
impl Write for ChildStdin {
73
79
fn write ( & mut self , buf : & [ u8 ] ) -> io:: Result < usize > {
74
80
self . inner . write ( buf)
@@ -80,21 +86,25 @@ impl Write for ChildStdin {
80
86
}
81
87
82
88
/// A handle to a child procesess's stdout
89
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
83
90
pub struct ChildStdout {
84
91
inner : AnonPipe
85
92
}
86
93
94
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
87
95
impl Read for ChildStdout {
88
96
fn read ( & mut self , buf : & mut [ u8 ] ) -> io:: Result < usize > {
89
97
self . inner . read ( buf)
90
98
}
91
99
}
92
100
93
101
/// A handle to a child procesess's stderr
102
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
94
103
pub struct ChildStderr {
95
104
inner : AnonPipe
96
105
}
97
106
107
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
98
108
impl Read for ChildStderr {
99
109
fn read ( & mut self , buf : & mut [ u8 ] ) -> io:: Result < usize > {
100
110
self . inner . read ( buf)
@@ -108,15 +118,14 @@ impl Read for ChildStderr {
108
118
/// to be changed (for example, by adding arguments) prior to spawning:
109
119
///
110
120
/// ```
111
- /// # #![feature(process)]
112
- ///
113
121
/// use std::process::Command;
114
122
///
115
123
/// let output = Command::new("sh").arg("-c").arg("echo hello").output().unwrap_or_else(|e| {
116
124
/// panic!("failed to execute process: {}", e)
117
125
/// });
118
126
/// let hello = output.stdout;
119
127
/// ```
128
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
120
129
pub struct Command {
121
130
inner : CommandImp ,
122
131
@@ -137,6 +146,7 @@ impl Command {
137
146
///
138
147
/// Builder methods are provided to change these defaults and
139
148
/// otherwise configure the process.
149
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
140
150
pub fn new < S : AsOsStr + ?Sized > ( program : & S ) -> Command {
141
151
Command {
142
152
inner : CommandImp :: new ( program. as_os_str ( ) ) ,
@@ -147,12 +157,14 @@ impl Command {
147
157
}
148
158
149
159
/// Add an argument to pass to the program.
160
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
150
161
pub fn arg < S : AsOsStr + ?Sized > ( & mut self , arg : & S ) -> & mut Command {
151
162
self . inner . arg ( arg. as_os_str ( ) ) ;
152
163
self
153
164
}
154
165
155
166
/// Add multiple arguments to pass to the program.
167
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
156
168
pub fn args < S : AsOsStr > ( & mut self , args : & [ S ] ) -> & mut Command {
157
169
self . inner . args ( args. iter ( ) . map ( AsOsStr :: as_os_str) ) ;
158
170
self
@@ -162,47 +174,54 @@ impl Command {
162
174
///
163
175
/// Note that environment variable names are case-insensitive (but case-preserving) on Windows,
164
176
/// and case-sensitive on all other platforms.
165
- pub fn env < S : ?Sized , T : ?Sized > ( & mut self , key : & S , val : & T ) -> & mut Command where
166
- S : AsOsStr , T : AsOsStr
177
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
178
+ pub fn env < K : ?Sized , V : ?Sized > ( & mut self , key : & K , val : & V ) -> & mut Command
179
+ where K : AsOsStr , V : AsOsStr
167
180
{
168
181
self . inner . env ( key. as_os_str ( ) , val. as_os_str ( ) ) ;
169
182
self
170
183
}
171
184
172
185
/// Removes an environment variable mapping.
173
- pub fn env_remove < S : ?Sized + AsOsStr > ( & mut self , key : & S ) -> & mut Command {
186
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
187
+ pub fn env_remove < K : ?Sized + AsOsStr > ( & mut self , key : & K ) -> & mut Command {
174
188
self . inner . env_remove ( key. as_os_str ( ) ) ;
175
189
self
176
190
}
177
191
178
192
/// Clears the entire environment map for the child process.
193
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
179
194
pub fn env_clear ( & mut self ) -> & mut Command {
180
195
self . inner . env_clear ( ) ;
181
196
self
182
197
}
183
198
184
199
/// Set the working directory for the child process.
200
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
185
201
pub fn current_dir < P : AsPath + ?Sized > ( & mut self , dir : & P ) -> & mut Command {
186
202
self . inner . cwd ( dir. as_path ( ) . as_os_str ( ) ) ;
187
203
self
188
204
}
189
205
190
206
/// Configuration for the child process's stdin handle (file descriptor 0).
191
207
/// Defaults to `CreatePipe(true, false)` so the input can be written to.
208
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
192
209
pub fn stdin ( & mut self , cfg : Stdio ) -> & mut Command {
193
210
self . stdin = Some ( cfg. 0 ) ;
194
211
self
195
212
}
196
213
197
214
/// Configuration for the child process's stdout handle (file descriptor 1).
198
215
/// Defaults to `CreatePipe(false, true)` so the output can be collected.
216
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
199
217
pub fn stdout ( & mut self , cfg : Stdio ) -> & mut Command {
200
218
self . stdout = Some ( cfg. 0 ) ;
201
219
self
202
220
}
203
221
204
222
/// Configuration for the child process's stderr handle (file descriptor 2).
205
223
/// Defaults to `CreatePipe(false, true)` so the output can be collected.
224
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
206
225
pub fn stderr ( & mut self , cfg : Stdio ) -> & mut Command {
207
226
self . stderr = Some ( cfg. 0 ) ;
208
227
self
@@ -234,6 +253,7 @@ impl Command {
234
253
/// Executes the command as a child process, returning a handle to it.
235
254
///
236
255
/// By default, stdin, stdout and stderr are inherited by the parent.
256
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
237
257
pub fn spawn ( & mut self ) -> io:: Result < Child > {
238
258
self . spawn_inner ( StdioImp :: Inherit )
239
259
}
@@ -258,8 +278,9 @@ impl Command {
258
278
/// println!("stdout: {}", String::from_utf8_lossy(output.stdout.as_slice()));
259
279
/// println!("stderr: {}", String::from_utf8_lossy(output.stderr.as_slice()));
260
280
/// ```
281
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
261
282
pub fn output ( & mut self ) -> io:: Result < Output > {
262
- self . spawn_inner ( StdioImp :: Capture ) . and_then ( |p| p. wait_with_output ( ) )
283
+ self . spawn_inner ( StdioImp :: Piped ) . and_then ( |p| p. wait_with_output ( ) )
263
284
}
264
285
265
286
/// Executes a command as a child process, waiting for it to finish and
@@ -279,6 +300,7 @@ impl Command {
279
300
///
280
301
/// println!("process exited with: {}", status);
281
302
/// ```
303
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
282
304
pub fn status ( & mut self ) -> io:: Result < ExitStatus > {
283
305
self . spawn ( ) . and_then ( |mut p| p. wait ( ) )
284
306
}
@@ -317,7 +339,7 @@ fn setup_io(io: &StdioImp, fd: libc::c_int, readable: bool)
317
339
Inherit => {
318
340
( Some ( AnonPipe :: from_fd ( fd) ) , None )
319
341
}
320
- Capture => {
342
+ Piped => {
321
343
let ( reader, writer) = try!( unsafe { pipe2:: anon_pipe ( ) } ) ;
322
344
if readable {
323
345
( Some ( reader) , Some ( writer) )
@@ -330,45 +352,60 @@ fn setup_io(io: &StdioImp, fd: libc::c_int, readable: bool)
330
352
331
353
/// The output of a finished process.
332
354
#[ derive( PartialEq , Eq , Clone ) ]
355
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
333
356
pub struct Output {
334
357
/// The status (exit code) of the process.
358
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
335
359
pub status : ExitStatus ,
336
360
/// The data that the process wrote to stdout.
361
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
337
362
pub stdout : Vec < u8 > ,
338
363
/// The data that the process wrote to stderr.
364
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
339
365
pub stderr : Vec < u8 > ,
340
366
}
341
367
342
368
/// Describes what to do with a standard io stream for a child process.
369
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
343
370
pub struct Stdio ( StdioImp ) ;
344
371
345
372
// The internal enum for stdio setup; see below for descriptions.
346
373
#[ derive( Clone ) ]
347
374
enum StdioImp {
348
- Capture ,
375
+ Piped ,
349
376
Inherit ,
350
377
Null ,
351
378
}
352
379
353
380
impl Stdio {
354
381
/// A new pipe should be arranged to connect the parent and child processes.
355
- pub fn capture ( ) -> Stdio { Stdio ( StdioImp :: Capture ) }
382
+ #[ unstable( feature = "process_capture" ) ]
383
+ #[ deprecated( since = "1.0.0" , reason = "renamed to `Stdio::piped`" ) ]
384
+ pub fn capture ( ) -> Stdio { Stdio :: piped ( ) }
385
+
386
+ /// A new pipe should be arranged to connect the parent and child processes.
387
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
388
+ pub fn piped ( ) -> Stdio { Stdio ( StdioImp :: Piped ) }
356
389
357
390
/// The child inherits from the corresponding parent descriptor.
391
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
358
392
pub fn inherit ( ) -> Stdio { Stdio ( StdioImp :: Inherit ) }
359
393
360
394
/// This stream will be ignored. This is the equivalent of attaching the
361
395
/// stream to `/dev/null`
396
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
362
397
pub fn null ( ) -> Stdio { Stdio ( StdioImp :: Null ) }
363
398
}
364
399
365
400
/// Describes the result of a process after it has terminated.
366
401
#[ derive( PartialEq , Eq , Clone , Copy , Debug ) ]
402
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
367
403
pub struct ExitStatus ( ExitStatusImp ) ;
368
404
369
405
impl ExitStatus {
370
406
/// Was termination successful? Signal termination not considered a success,
371
407
/// and success is defined as a zero exit status.
408
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
372
409
pub fn success ( & self ) -> bool {
373
410
self . 0 . success ( )
374
411
}
@@ -378,6 +415,7 @@ impl ExitStatus {
378
415
/// On Unix, this will return `None` if the process was terminated
379
416
/// by a signal; `std::os::unix` provides an extension trait for
380
417
/// extracting the signal and other details from the `ExitStatus`.
418
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
381
419
pub fn code ( & self ) -> Option < i32 > {
382
420
self . 0 . code ( )
383
421
}
@@ -387,6 +425,7 @@ impl AsInner<ExitStatusImp> for ExitStatus {
387
425
fn as_inner ( & self ) -> & ExitStatusImp { & self . 0 }
388
426
}
389
427
428
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
390
429
impl fmt:: Display for ExitStatus {
391
430
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
392
431
self . 0 . fmt ( f)
@@ -396,6 +435,7 @@ impl fmt::Display for ExitStatus {
396
435
impl Child {
397
436
/// Forces the child to exit. This is equivalent to sending a
398
437
/// SIGKILL on unix platforms.
438
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
399
439
pub fn kill ( & mut self ) -> io:: Result < ( ) > {
400
440
#[ cfg( unix) ] fn collect_status ( p : & mut Child ) {
401
441
// On Linux (and possibly other unices), a process that has exited will
@@ -436,6 +476,7 @@ impl Child {
436
476
/// before waiting. This helps avoid deadlock: it ensures that the
437
477
/// child does not block waiting for input from the parent, while
438
478
/// the parent waits for the child to exit.
479
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
439
480
pub fn wait ( & mut self ) -> io:: Result < ExitStatus > {
440
481
drop ( self . stdin . take ( ) ) ;
441
482
match self . status {
@@ -456,6 +497,7 @@ impl Child {
456
497
/// before waiting. This helps avoid deadlock: it ensures that the
457
498
/// child does not block waiting for input from the parent, while
458
499
/// the parent waits for the child to exit.
500
+ #[ stable( feature = "process" , since = "1.0.0" ) ]
459
501
pub fn wait_with_output ( mut self ) -> io:: Result < Output > {
460
502
drop ( self . stdin . take ( ) ) ;
461
503
fn read < T : Read + Send + ' static > ( stream : Option < T > ) -> Receiver < io:: Result < Vec < u8 > > > {
@@ -557,7 +599,7 @@ mod tests {
557
599
#[ test]
558
600
fn stdout_works ( ) {
559
601
let mut cmd = Command :: new ( "echo" ) ;
560
- cmd. arg ( "foobar" ) . stdout ( Stdio :: capture ( ) ) ;
602
+ cmd. arg ( "foobar" ) . stdout ( Stdio :: piped ( ) ) ;
561
603
assert_eq ! ( run_output( cmd) , "foobar\n " ) ;
562
604
}
563
605
@@ -567,7 +609,7 @@ mod tests {
567
609
let mut cmd = Command :: new ( "/bin/sh" ) ;
568
610
cmd. arg ( "-c" ) . arg ( "pwd" )
569
611
. current_dir ( "/" )
570
- . stdout ( Stdio :: capture ( ) ) ;
612
+ . stdout ( Stdio :: piped ( ) ) ;
571
613
assert_eq ! ( run_output( cmd) , "/\n " ) ;
572
614
}
573
615
@@ -576,8 +618,8 @@ mod tests {
576
618
fn stdin_works ( ) {
577
619
let mut p = Command :: new ( "/bin/sh" )
578
620
. arg ( "-c" ) . arg ( "read line; echo $line" )
579
- . stdin ( Stdio :: capture ( ) )
580
- . stdout ( Stdio :: capture ( ) )
621
+ . stdin ( Stdio :: piped ( ) )
622
+ . stdout ( Stdio :: piped ( ) )
581
623
. spawn ( ) . unwrap ( ) ;
582
624
p. stdin . as_mut ( ) . unwrap ( ) . write ( "foobar" . as_bytes ( ) ) . unwrap ( ) ;
583
625
drop ( p. stdin . take ( ) ) ;
@@ -675,7 +717,7 @@ mod tests {
675
717
#[ cfg( not( target_os="android" ) ) ]
676
718
#[ test]
677
719
fn test_wait_with_output_once ( ) {
678
- let prog = Command :: new ( "echo" ) . arg ( "hello" ) . stdout ( Stdio :: capture ( ) )
720
+ let prog = Command :: new ( "echo" ) . arg ( "hello" ) . stdout ( Stdio :: piped ( ) )
679
721
. spawn ( ) . unwrap ( ) ;
680
722
let Output { status, stdout, stderr} = prog. wait_with_output ( ) . unwrap ( ) ;
681
723
let output_str = str:: from_utf8 ( stdout. as_slice ( ) ) . unwrap ( ) ;
0 commit comments