// Copyright 2021, The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. use command_fds::{CommandFdExt, FdMapping}; use std::fs::{read_dir, read_link, File}; use std::io::stdin; use std::os::fd::AsFd; use std::os::unix::process::CommandExt; use std::process::Command; use std::thread::sleep; use std::time::Duration; /// Print out a list of all open file descriptors. fn list_fds() { let dir = read_dir("/proc/self/fd").unwrap(); for entry in dir { let entry = entry.unwrap(); let target = read_link(entry.path()).unwrap(); println!("{:?} {:?}", entry, target); } } fn main() { list_fds(); // Open a file. let file = File::open("Cargo.toml").unwrap(); println!("File: {:?}", file); list_fds(); // Prepare to run `ls -l /proc/self/fd` with some FDs mapped. let mut command = Command::new("ls"); let stdin = stdin().as_fd().try_clone_to_owned().unwrap(); command.arg("-l").arg("/proc/self/fd"); command .fd_mappings(vec![ // Map `file` as FD 3 in the child process. FdMapping { parent_fd: file.into(), child_fd: 3, }, // Map this process's stdin as FD 5 in the child process. FdMapping { parent_fd: stdin, child_fd: 5, }, ]) .unwrap(); unsafe { command.pre_exec(move || { println!("pre_exec"); list_fds(); Ok(()) }); } // Spawn the child process. println!("Spawning command"); let mut child = command.spawn().unwrap(); sleep(Duration::from_millis(100)); println!("Spawned"); list_fds(); println!("Waiting for command"); println!("{:?}", child.wait().unwrap()); }