1 use std::process::Command; 2 3 use anyhow::Context as _; 4 use clap::Parser; 5 6 use crate::{build::{build, Options as BuildOptions}, build_ebpf::Architecture}; 7 8 #[derive(Debug, Parser)] 9 pub struct Options { 10 /// Set the endianness of the BPF target 11 #[clap(default_value = "bpfel-unknown-none", long)] 12 pub bpf_target: Architecture, 13 /// Build and run the release target 14 #[clap(long)] 15 pub release: bool, 16 /// The command used to wrap your application 17 #[clap(short, long, default_value = "sudo -E")] 18 pub runner: String, 19 /// Arguments to pass to your application 20 #[clap(name = "args", last = true)] 21 pub run_args: Vec<String>, 22 } 23 24 25 /// Build and run the project 26 pub fn run(opts: Options) -> Result<(), anyhow::Error> { 27 // Build our ebpf program and the project 28 build(BuildOptions{ 29 bpf_target: opts.bpf_target, 30 release: opts.release, 31 }).context("Error while building project")?; 32 33 // profile we are building (release or debug) 34 let profile = if opts.release { "release" } else { "debug" }; 35 let bin_path = format!("target/{profile}/syscall_ebpf"); 36 37 // arguments to pass to the application 38 let mut run_args: Vec<_> = opts.run_args.iter().map(String::as_str).collect(); 39 40 // configure args 41 let mut args: Vec<_> = opts.runner.trim().split_terminator(' ').collect(); 42 args.push(bin_path.as_str()); 43 args.append(&mut run_args); 44 45 // run the command 46 let status = Command::new(args.first().expect("No first argument")) 47 .args(args.iter().skip(1)) 48 .status() 49 .expect("failed to run the command"); 50 51 if !status.success() { 52 anyhow::bail!("Failed to run `{}`", args.join(" ")); 53 } 54 Ok(()) 55 } 56