• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! This is an example of how to use `dup2` to replace the stdin and stdout
2 //! file descriptors.
3 
4 #[cfg(not(windows))]
main()5 fn main() {
6     use rustix::io::{dup2, pipe};
7     use std::io::{BufRead, BufReader};
8     use std::mem::forget;
9 
10     // Create some new file descriptors that we'll use to replace stdio's file
11     // descriptors with.
12     let (reader, writer) = pipe().unwrap();
13 
14     // Acquire `OwnedFd` instances for stdin and stdout. These APIs are `unsafe`
15     // because in general, with low-level APIs like this, libraries can't assume
16     // that stdin and stdout will be open or safe to use. It's ok here, because
17     // we're directly inside `main`, so we know that stdin and stdout haven't
18     // been closed and aren't being used for other purposes.
19     let (mut stdin, mut stdout) = unsafe { (rustix::io::take_stdin(), rustix::io::take_stdout()) };
20 
21     // Use `dup2` to copy our new file descriptors over the stdio file descriptors.
22     //
23     // These take their second argument as an `&mut OwnedFd` rather than the
24     // usual `impl AsFd` because they conceptually do a `close` on the original
25     // file descriptor, which one shouldn't be able to do with just a
26     // `BorrowedFd`.
27     dup2(&reader, &mut stdin).unwrap();
28     dup2(&writer, &mut stdout).unwrap();
29 
30     // Then, forget the stdio `OwnedFd`s, because actually dropping them would
31     // close them. Here, we want stdin and stdout to remain open for the rest
32     // of the program.
33     forget(stdin);
34     forget(stdout);
35 
36     // We can also drop the original file descriptors now, since `dup2` creates
37     // new file descriptors with independent lifetimes.
38     drop(reader);
39     drop(writer);
40 
41     // Now we can print to "stdout" in the usual way, and it'll go to our pipe.
42     println!("hello, world!");
43 
44     // And we can read from stdin, and it'll read from our pipe. It's a little
45     // silly that we connected our stdout to our own stdin, but it's just an
46     // example :-).
47     let mut s = String::new();
48     BufReader::new(std::io::stdin()).read_line(&mut s).unwrap();
49     assert_eq!(s, "hello, world!\n");
50 }
51 
52 #[cfg(windows)]
main()53 fn main() {
54     unimplemented!()
55 }
56