2023-01-27 15:23:57 +01:00

144 lines
5.4 KiB
Rust

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),
};
}