1 // Copyright 2021, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 use command_fds::{CommandFdExt, FdMapping};
16 use std::fs::{read_dir, read_link, File};
17 use std::io::stdin;
18 use std::os::fd::AsFd;
19 use std::os::unix::process::CommandExt;
20 use std::process::Command;
21 use std::thread::sleep;
22 use std::time::Duration;
23
24 /// Print out a list of all open file descriptors.
list_fds()25 fn list_fds() {
26 let dir = read_dir("/proc/self/fd").unwrap();
27 for entry in dir {
28 let entry = entry.unwrap();
29 let target = read_link(entry.path()).unwrap();
30 println!("{:?} {:?}", entry, target);
31 }
32 }
33
main()34 fn main() {
35 list_fds();
36
37 // Open a file.
38 let file = File::open("Cargo.toml").unwrap();
39 println!("File: {:?}", file);
40 list_fds();
41
42 // Prepare to run `ls -l /proc/self/fd` with some FDs mapped.
43 let mut command = Command::new("ls");
44 let stdin = stdin().as_fd().try_clone_to_owned().unwrap();
45 command.arg("-l").arg("/proc/self/fd");
46 command
47 .fd_mappings(vec![
48 // Map `file` as FD 3 in the child process.
49 FdMapping {
50 parent_fd: file.into(),
51 child_fd: 3,
52 },
53 // Map this process's stdin as FD 5 in the child process.
54 FdMapping {
55 parent_fd: stdin,
56 child_fd: 5,
57 },
58 ])
59 .unwrap();
60 unsafe {
61 command.pre_exec(move || {
62 println!("pre_exec");
63 list_fds();
64 Ok(())
65 });
66 }
67
68 // Spawn the child process.
69 println!("Spawning command");
70 let mut child = command.spawn().unwrap();
71 sleep(Duration::from_millis(100));
72 println!("Spawned");
73 list_fds();
74
75 println!("Waiting for command");
76 println!("{:?}", child.wait().unwrap());
77 }
78