wasi_net/process/stdio.rs
1use crate::backend::StdioMode;
2
3/// Describes what to do with a standard I/O stream for a child process when
4/// passed to the [`stdin`], [`stdout`], and [`stderr`] methods of [`Command`].
5///
6/// [`stdin`]: Command::stdin
7/// [`stdout`]: Command::stdout
8/// [`stderr`]: Command::stderr
9#[derive(Debug, Clone)]
10pub struct Stdio {
11 pub(super) mode: StdioMode,
12}
13
14impl Stdio {
15 /// A new pipe should be arranged to connect the parent and child processes.
16 ///
17 /// # Examples
18 ///
19 /// With stdout:
20 ///
21 /// ```no_run
22 /// use std::process::{Command, Stdio};
23 ///
24 /// let output = Command::new("echo")
25 /// .arg("Hello, world!")
26 /// .stdout(Stdio::piped())
27 /// .output()
28 /// .expect("Failed to execute command");
29 ///
30 /// assert_eq!(String::from_utf8_lossy(&output.stdout), "Hello, world!\n");
31 /// // Nothing echoed to console
32 /// ```
33 ///
34 /// With stdin:
35 ///
36 /// ```no_run
37 /// use std::io::Write;
38 /// use std::process::{Command, Stdio};
39 ///
40 /// let mut child = Command::new("rev")
41 /// .stdin(Stdio::piped())
42 /// .stdout(Stdio::piped())
43 /// .spawn()
44 /// .expect("Failed to spawn child process");
45 ///
46 /// let mut stdin = child.stdin.take().expect("Failed to open stdin");
47 /// std::thread::spawn(move || {
48 /// stdin.write_all("Hello, world!".as_bytes()).expect("Failed to write to stdin");
49 /// });
50 ///
51 /// let output = child.wait_with_output().expect("Failed to read stdout");
52 /// assert_eq!(String::from_utf8_lossy(&output.stdout), "!dlrow ,olleH");
53 /// ```
54 ///
55 /// Writing more than a pipe buffer's worth of input to stdin without also reading
56 /// stdout and stderr at the same time may cause a deadlock.
57 /// This is an issue when running any program that doesn't guarantee that it reads
58 /// its entire stdin before writing more than a pipe buffer's worth of output.
59 /// The size of a pipe buffer varies on different targets.
60 ///
61 pub fn piped() -> Stdio {
62 Stdio { mode: StdioMode::Piped }
63 }
64
65 /// The child inherits from the corresponding parent descriptor.
66 ///
67 /// # Examples
68 ///
69 /// With stdout:
70 ///
71 /// ```no_run
72 /// use std::process::{Command, Stdio};
73 ///
74 /// let output = Command::new("echo")
75 /// .arg("Hello, world!")
76 /// .stdout(Stdio::inherit())
77 /// .output()
78 /// .expect("Failed to execute command");
79 ///
80 /// assert_eq!(String::from_utf8_lossy(&output.stdout), "");
81 /// // "Hello, world!" echoed to console
82 /// ```
83 ///
84 /// With stdin:
85 ///
86 /// ```no_run
87 /// use std::process::{Command, Stdio};
88 /// use std::io::{self, Write};
89 ///
90 /// let output = Command::new("rev")
91 /// .stdin(Stdio::inherit())
92 /// .stdout(Stdio::piped())
93 /// .output()
94 /// .expect("Failed to execute command");
95 ///
96 /// print!("You piped in the reverse of: ");
97 /// io::stdout().write_all(&output.stdout).unwrap();
98 /// ```
99 pub fn inherit() -> Stdio {
100 Stdio { mode: StdioMode::Inherit }
101 }
102
103 /// This stream will be ignored. This is the equivalent of attaching the
104 /// stream to `/dev/null`.
105 ///
106 /// # Examples
107 ///
108 /// With stdout:
109 ///
110 /// ```no_run
111 /// use std::process::{Command, Stdio};
112 ///
113 /// let output = Command::new("echo")
114 /// .arg("Hello, world!")
115 /// .stdout(Stdio::null())
116 /// .output()
117 /// .expect("Failed to execute command");
118 ///
119 /// assert_eq!(String::from_utf8_lossy(&output.stdout), "");
120 /// // Nothing echoed to console
121 /// ```
122 ///
123 /// With stdin:
124 ///
125 /// ```no_run
126 /// use std::process::{Command, Stdio};
127 ///
128 /// let output = Command::new("rev")
129 /// .stdin(Stdio::null())
130 /// .stdout(Stdio::piped())
131 /// .output()
132 /// .expect("Failed to execute command");
133 ///
134 /// assert_eq!(String::from_utf8_lossy(&output.stdout), "");
135 /// // Ignores any piped-in input
136 /// ```
137 pub fn null() -> Stdio {
138 Stdio { mode: StdioMode::Null }
139 }
140}