use std::fs::File; use std::io::prelude::*; use std::process::{Command, exit}; use clap::Parser; use colored::*; mod parser; // setup cli parser #[derive(Parser, Debug)] #[command( author = "Julius Herrmann (juhe00002@uni-saarland.de)", about = "A simple tool to enable batch writing od 'sysoISIm-SJA2' cards with the corresponding CSV data by the manufacturer", long_about = None)] pub struct CliArgs { /// The path to the pySim binary #[arg(short = 'b', long = "binary", default_value_t = String::from("./pySim-prog.py"))] bin: String, /// The path to the csv file to read #[arg(short = 'c', long = "csv")] csv: String, /// Set the output file with the commands for the core #[arg(short = 'o', long = "output", default_value_t = String::from("output"))] output_file: String, /// The name of the nework #[arg(short = 'n', long = "name")] name: String, /// The mcc code #[arg(long = "mcc")] mcc: String, /// The mnc code #[arg(long = "mnc")] mnc: String, #[arg(short = 'd', long = "device", default_value_t = 0)] device: u8, #[arg(long = "ki", default_value_t = String::from("00000000000000000000000000000000"))] ki: String, #[arg(long = "opc", default_value_t = String::from("00000000000000000000000000000000"))] opc: String, /// Set true if you want to use an op key instead of opc #[arg(long = "use-op", default_value_t = false)] use_op: bool, #[arg(long = "op", default_value_t = String::from("00000000000000000000000000000000"))] op: String, /// Set true if you want to execute the "deactivate5g" script #[arg(long = "deactivate-5g", default_value_t = false)] deactivate5g: bool, /// Set true to only do a dry run (print commands and not execute them) #[arg(long = "dry-run", default_value_t = false)] dry_run: bool, } fn main() { let args = CliArgs::parse(); let mut user_provision_commands = vec![]; let mut pysim_outputs = vec![]; // parse the supplied card configs let card_configs = parser::parse_csv(&args.csv).unwrap(); for conf in card_configs { // create the arguments let imsi_ending = String::from(&conf.IMSI[6..]); // add command to be run on the open5gcore user_provision_commands.push(format!("./provision_user.sh -S 001010000012345 -k {} -a 8000 -o 00000000000000000000000000000000 -s 000000000010 -t 0 -c 1 -u 0 -T 12345", String::from(&conf.IMSI))); let pysim_args = conf.generate_pysim_args(&args); println!("\n{}:", "EXECUTING".red()); print!("{}", args.bin); for pysim_arg in &pysim_args { print!(" {}", pysim_arg); } if !wait_for_user(&format!("Please insert the sim-card with IMSI ending in: {}", imsi_ending.green())) { exit_programm(1); } if args.dry_run { println!("{}: The command is not executed since {} is enabled", "WARNING".yellow(), "dry_run".yellow()); } else { let mut command = Command::new(&args.bin); for pysim_arg in pysim_args { command.arg(pysim_arg); } // wait for the child process to stop // let child = command.stdout(Stdio::piped()).spawn().unwrap(); // let output = child.wait_with_output().unwrap(); let output = command.output().expect("process failed to execute"); if output.status.success() { let output_string = String::from_utf8(output.stdout).unwrap(); pysim_outputs.push(output_string.clone()); println!("{} ", output_string); println!("{} programmed sim card", "SUCCESSFULLY".green()); } else { println!("{} ", String::from_utf8(output.stderr).unwrap()); println!("{}, please check the output of pySim above!", "ERROR".red()); continue; } } // possibly execute deactivate5g command if args.deactivate5g { println!("{}: ./pySim-shell.py -p{} --script scripts/deactivate-5g.script", "EXECUTING".red(), &args.device); if args.dry_run { print!("{}: The command is not executed since {} is enabled\n", "WARNING".yellow(), "dry_run".yellow()); continue; } println!("{}. Not Implemented Yet!", "TODO".red()); } } // output to file let mut file = File::create(args.output_file).unwrap(); writeln!(&mut file, "PySim outputs:").unwrap(); for pysim_out in pysim_outputs { writeln!(&mut file, "{}", pysim_out).unwrap(); } writeln!(&mut file, "\nCommands to be executed on core:").unwrap(); for command in user_provision_commands { writeln!(&mut file, "{}", command).unwrap(); } exit_programm(0) } fn exit_programm(code: i32) -> () { println!("{}", "GOODBYE!".green()); exit(code); } // wait for user to input enter. If a is entered return false signaling to stop the program fn wait_for_user(msg: &str) -> bool { println!("\n{}\nPress enter to continue or 'a' to abort:", msg); let mut next_string = String::new(); match std::io::stdin().read_line(&mut next_string) { Ok(n) if n > 0 => { return 'a' != next_string.chars().next().unwrap() } Ok(_) => return true, // other input is ignored Err(err) => panic!("{}", err), }; }