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