use std::sync::Arc;
use libunftp::{auth::Authenticator, ServerBuilder};
use std::path::PathBuf;
mod auth;
mod global_consts;
use global_consts::{SimpleAuthenticator, UserEntry};
use local_ip_address::local_ip;
mod init;
use init::init;
mod cli;
use cli::{Cli, Commands};
use clap::{Parser};
use std::process::Command;
mod config;
use config::Config;
use tokio::{process::Command as TokioCommand};
use crate::global_consts::create_rooted_storage;
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
init()?;
let mut config = Config::load();
eprintln!("Using root_dir = {}", config.root_dir.display());
let path = config.root_dir.join("credentials.json");
let auth = SimpleAuthenticator::new(path);
let cli = Cli::parse();
let ip = local_ip().unwrap();
let addr = format!("{}:{}",ip,2121);
match cli.command {
Commands::Start{daemon} => {
println!("Starting FTP server...");
start_server(daemon, auth,config.root_dir.clone(),addr.clone()).await?;
},
Commands::Stop=> {
stop_server().await;
println!("Stopping FTP server...");
},
Commands::Setdir{path} => {
config.root_dir = path;
config.save();
println!("Root directory set to: {}", config.root_dir.display());
},
Commands::Status => {
println!("Current configuration:");
println!("Root Directory: {}", config.root_dir.display()); },
}
Ok(())
}
async fn start_server(daemon: bool, auth: SimpleAuthenticator,root_dir: PathBuf,addr:String) -> Result<(), Box<dyn std::error::Error>> {
if daemon {
Command::new("nohup")
.arg("rootftp")
.arg("start")
.spawn()
.expect("Failed to start daemon");
} else {
let dir = root_dir.join("ftpd");
let storage = create_rooted_storage(dir.clone());
let auth_arc: Arc<dyn Authenticator<UserEntry> + Send + Sync> = Arc::new(auth);
let server = ServerBuilder::with_authenticator(storage,auth_arc)
.build()
.expect("Failed to build server");
println!("Listening on {}", addr);
server.listen(addr).await?;
}
Ok(())
}
pub async fn stop_server() {
TokioCommand::new("pkill")
.arg("-f")
.arg("rootftp")
.status()
.await
.expect("Failed to stop server");
}