mod cli; mod server; mod signals; mod stdin; use clap::Parser; use cli::{BackupArgs, Cli, Commands, RunArgs}; use std::io; use std::sync::{Arc, Mutex}; fn backups_thread(counter: Arc>, frequency: u64) { loop { std::thread::sleep(std::time::Duration::from_secs(frequency * 60)); { let mut server = counter.lock().unwrap(); // We explicitely ignore the error here, as we don't want the thread to fail let _ = server.backup(); } } } fn command_run(cli: &Cli, args: &RunArgs) -> io::Result<()> { let (_, mut signals) = signals::install_signal_handlers()?; let mut cmd = server::ServerCommand::new(args.type_, &args.server_version) .java(&args.java) .jar(args.jar.clone()) .config(cli.config.clone()) .world(cli.world.clone()) .backup(cli.backup.clone()) .xms(args.xms) .xmx(args.xmx) .chain_len(cli.chain_len) .chains_to_keep(cli.chains); cmd.canonicalize()?; if args.dry { print!("{}", cmd); return Ok(()); } let counter = Arc::new(Mutex::new(cmd.spawn()?)); if args.frequency > 0 { let clone = Arc::clone(&counter); let frequency = args.frequency; std::thread::spawn(move || backups_thread(clone, frequency)); } // Spawn thread that handles the main stdin loop let clone = Arc::clone(&counter); std::thread::spawn(move || stdin::handle_stdin(clone)); // Signal handler loop exits the process when necessary signals::handle_signals(&mut signals, counter) } fn commands_backup(cli: &Cli, _args: &BackupArgs) -> io::Result<()> { let mut manager = server::BackupManager::new( cli.backup.clone(), cli.config.clone(), cli.world.clone(), cli.chain_len, cli.chains, ); manager.create_backup()?; manager.remove_old_backups() } fn main() -> io::Result<()> { let cli = Cli::parse(); match &cli.command { Commands::Run(args) => command_run(&cli, args), Commands::Backup(args) => commands_backup(&cli, args), } }