Last active
July 20, 2022 17:40
-
-
Save TrinityCoder/793c097b5a4ab25b8fabf5cd67e92f05 to your computer and use it in GitHub Desktop.
Rust: Converting Vec<String> into a C-style 'char**' array to be used in libc library calls, such as in libc::execvp()
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Build by running `cargo make` | |
# or `cargo build`. | |
# | |
# Run by `cargo run`. | |
[package] | |
name = "experiment" | |
version = "0.1.0" | |
edition = "2018" | |
[dependencies] | |
libc = "0.2.55" | |
[[bin]] | |
name = "main" | |
path = "main.rs" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
mod utils { | |
use libc::c_char; | |
use std::ffi::CString; | |
/// Consumes a `Vec<String>` and saves some helper data, so it can provide | |
/// the `*const *const c_char` (`argv`) and `*const c_char` (`argv[0]`) | |
/// when the user needs them i. e. for [`libc::execvp()`] library call. | |
pub struct Argv { | |
argv: Vec<CString>, | |
argv_ptr: Vec<*const c_char>, | |
} | |
impl Argv { | |
/// Creates a new `Argv` structure. | |
pub fn new(args: Vec<String>) -> Self { | |
let argv: Vec<_> = args | |
.iter() | |
.map(|arg| CString::new(arg.as_str()).unwrap()) | |
.collect(); | |
let mut argv_ptr: Vec<_> = argv.iter().map(|arg| arg.as_ptr()).collect(); | |
argv_ptr.push(std::ptr::null()); | |
Self { argv, argv_ptr } | |
} | |
/// Returns the C language's `argv` (`*const *const c_char`). | |
pub fn get_argv(&self) -> *const *const c_char { self.argv_ptr.as_ptr() } | |
/// Returns the C language's `argv[0]` (`*const c_char`). | |
pub fn get_argv0(&self) -> *const c_char { self.argv_ptr[0] } | |
/// Gets total length of the `argv` array (including the last null pointer). | |
pub fn get_len(&self) -> usize { self.argv_ptr.len() } | |
} | |
} | |
fn main() { | |
let args = vec!["ls".to_string(), "-l".to_string(), "-h".to_string()]; | |
let argv = utils::Argv::new(args.clone()); | |
unsafe { | |
libc::execvp(argv.get_argv0(), argv.get_argv()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment