|
| 1 | +use std::process::{Command, ExitStatus}; |
| 2 | +use std::env; |
| 3 | +use std::os::unix::fs::PermissionsExt; |
| 4 | +use colored::*; |
| 5 | +use std::io::{self, Write}; |
| 6 | +use std::thread; |
| 7 | +use std::time::Duration; |
| 8 | + |
| 9 | +const APT_PATH: &str = "/usr/lib/HackerOS/apt"; |
| 10 | +const VERSION: &str = "1.0.2"; |
| 11 | + |
| 12 | +fn print_help() { |
| 13 | + println!("{}", "HackerOS Package Manager".bold().green()); |
| 14 | + println!("Version: {}", VERSION); |
| 15 | + println!("{}", "A simple and fast package management tool for Debian".italic()); |
| 16 | + println!("\n{}", "Usage:".bold()); |
| 17 | + println!(" hacker <command> [arguments]"); |
| 18 | + println!("\n{}", "Available Commands:".bold()); |
| 19 | + let commands = [ |
| 20 | + ("autoremove", "Remove unneeded packages"), |
| 21 | + ("install", "Install one or more packages"), |
| 22 | + ("remove", "Remove one or more packages"), |
| 23 | + ("purge", "Remove packages and their configuration files"), |
| 24 | + ("list", "List installed packages"), |
| 25 | + ("list-available", "List all available packages"), |
| 26 | + ("list-upgradable", "List packages that can be upgraded"), |
| 27 | + ("search", "Search for packages"), |
| 28 | + ("clean", "Clean package cache"), |
| 29 | + ("show", "Show package information"), |
| 30 | + ("hold", "Prevent a package from being upgraded"), |
| 31 | + ("unhold", "Allow a package to be upgraded"), |
| 32 | + ("repolist", "List enabled repositories"), |
| 33 | + ("check", "Check for broken dependencies"), |
| 34 | + ("entry", "Launch HackerOS cybersecurity container"), |
| 35 | + ("version", "Show tool version"), |
| 36 | + ("?", "Show this help message"), |
| 37 | + ]; |
| 38 | + for (cmd, desc) in commands.iter() { |
| 39 | + println!(" {:<16} {}", cmd.bold().cyan(), desc); |
| 40 | + } |
| 41 | + println!("\n{}", "Note:".bold()); |
| 42 | + println!(" Use 'hacker-update' for system updates and upgrades."); |
| 43 | + println!(" Run commands with '--help' for detailed usage (e.g., 'hacker install --help')."); |
| 44 | +} |
| 45 | + |
| 46 | +fn print_progress(message: &str) { |
| 47 | + print!("{}", message); |
| 48 | + io::stdout().flush().unwrap(); |
| 49 | + for _ in 0..3 { |
| 50 | + thread::sleep(Duration::from_millis(500)); |
| 51 | + print!("{}", ".".yellow()); |
| 52 | + io::stdout().flush().unwrap(); |
| 53 | + } |
| 54 | + println!(); |
| 55 | +} |
| 56 | + |
| 57 | +fn execute_apt(args: Vec<&str>, use_sudo: bool) -> Result<ExitStatus, String> { |
| 58 | + let mut command = if use_sudo { |
| 59 | + let mut cmd = Command::new("sudo"); |
| 60 | + cmd.arg(APT_PATH); |
| 61 | + cmd |
| 62 | + } else { |
| 63 | + Command::new(APT_PATH) |
| 64 | + }; |
| 65 | + let output = command |
| 66 | + .args(&args) |
| 67 | + .status() |
| 68 | + .map_err(|e| format!("Failed to execute apt: {}", e))?; |
| 69 | + Ok(output) |
| 70 | +} |
| 71 | + |
| 72 | +fn execute_entry() -> Result<ExitStatus, String> { |
| 73 | + let output = Command::new("podman") |
| 74 | + .args(["start", "-ai", "hackeros-cybersecurity"]) |
| 75 | + .status() |
| 76 | + .map_err(|e| format!("Failed to execute podman: {}", e))?; |
| 77 | + Ok(output) |
| 78 | +} |
| 79 | + |
| 80 | +fn can_run_without_sudo() -> bool { |
| 81 | + if let Ok(metadata) = std::fs::metadata(APT_PATH) { |
| 82 | + let permissions = metadata.permissions(); |
| 83 | + let mode = permissions.mode(); |
| 84 | + (mode & 0o111) != 0 && (mode & 0o600) != 0 |
| 85 | + } else { |
| 86 | + false |
| 87 | + } |
| 88 | +} |
| 89 | + |
| 90 | +fn main() { |
| 91 | + let args: Vec<String> = env::args().collect(); |
| 92 | + if args.len() < 2 { |
| 93 | + println!("{}", "Error: No command provided".red()); |
| 94 | + print_help(); |
| 95 | + std::process::exit(1); |
| 96 | + } |
| 97 | + let command = &args[1]; |
| 98 | + let use_sudo = !can_run_without_sudo(); |
| 99 | + match command.as_str() { |
| 100 | + "autoremove" => { |
| 101 | + print_progress("Running autoremove"); |
| 102 | + match execute_apt(vec!["autoremove", "-y"], use_sudo) { |
| 103 | + Ok(status) if status.success() => println!("{}", "Autoremove completed successfully".green()), |
| 104 | + Ok(_) => println!("{}", "Autoremove failed".red()), |
| 105 | + Err(e) => println!("{} {}", "Error:".red(), e), |
| 106 | + } |
| 107 | + } |
| 108 | + "install" => { |
| 109 | + if args.len() < 3 { |
| 110 | + println!("{}", "Error: At least one package name required for install".red()); |
| 111 | + println!("Usage: hacker install <package1> [package2 ...]"); |
| 112 | + std::process::exit(1); |
| 113 | + } |
| 114 | + let packages = &args[2..]; |
| 115 | + let mut apt_args = vec!["install", "-y"]; |
| 116 | + apt_args.extend(packages.iter().map(|s| s.as_str())); |
| 117 | + print_progress(&format!("Installing {} ", packages.join(" "))); |
| 118 | + match execute_apt(apt_args, use_sudo) { |
| 119 | + Ok(status) if status.success() => println!("{}", format!("Package(s) {} installed successfully", packages.join(" ")).green()), |
| 120 | + Ok(_) => println!("{}", format!("Failed to install package(s) {}", packages.join(" ")).red()), |
| 121 | + Err(e) => println!("{} {}", "Error:".red(), e), |
| 122 | + } |
| 123 | + } |
| 124 | + "remove" => { |
| 125 | + if args.len() < 3 { |
| 126 | + println!("{}", "Error: At least one package name required for remove".red()); |
| 127 | + println!("Usage: hacker remove <package1> [package2 ...]"); |
| 128 | + std::process::exit(1); |
| 129 | + } |
| 130 | + let packages = &args[2..]; |
| 131 | + let mut apt_args = vec!["remove", "-y"]; |
| 132 | + apt_args.extend(packages.iter().map(|s| s.as_str())); |
| 133 | + print_progress(&format!("Removing {} ", packages.join(" "))); |
| 134 | + match execute_apt(apt_args, use_sudo) { |
| 135 | + Ok(status) if status.success() => println!("{}", format!("Package(s) {} removed successfully", packages.join(" ")).green()), |
| 136 | + Ok(_) => println!("{}", format!("Failed to remove package(s) {}", packages.join(" ")).red()), |
| 137 | + Err(e) => println!("{} {}", "Error:".red(), e), |
| 138 | + } |
| 139 | + } |
| 140 | + "purge" => { |
| 141 | + if args.len() < 3 { |
| 142 | + println!("{}", "Error: At least one package name required for purge".red()); |
| 143 | + println!("Usage: hacker purge <package1> [package2 ...]"); |
| 144 | + std::process::exit(1); |
| 145 | + } |
| 146 | + let packages = &args[2..]; |
| 147 | + let mut apt_args = vec!["purge", "-y"]; |
| 148 | + apt_args.extend(packages.iter().map(|s| s.as_str())); |
| 149 | + print_progress(&format!("Purging {} ", packages.join(" "))); |
| 150 | + match execute_apt(apt_args, use_sudo) { |
| 151 | + Ok(status) if status.success() => println!("{}", format!("Package(s) {} purged successfully", packages.join(" ")).green()), |
| 152 | + Ok(_) => println!("{}", format!("Failed to purge package(s) {}", packages.join(" ")).red()), |
| 153 | + Err(e) => println!("{} {}", "Error:".red(), e), |
| 154 | + } |
| 155 | + } |
| 156 | + "list" => { |
| 157 | + print_progress("Listing installed packages"); |
| 158 | + match execute_apt(vec!["list", "--installed"], use_sudo) { |
| 159 | + Ok(status) if status.success() => println!("{}", "Listed installed packages".green()), |
| 160 | + Ok(_) => println!("{}", "Failed to list packages".red()), |
| 161 | + Err(e) => println!("{} {}", "Error:".red(), e), |
| 162 | + } |
| 163 | + } |
| 164 | + "list-available" => { |
| 165 | + print_progress("Listing available packages"); |
| 166 | + match execute_apt(vec!["list"], use_sudo) { |
| 167 | + Ok(status) if status.success() => println!("{}", "Listed available packages".green()), |
| 168 | + Ok(_) => println!("{}", "Failed to list available packages".red()), |
| 169 | + Err(e) => println!("{} {}", "Error:".red(), e), |
| 170 | + } |
| 171 | + } |
| 172 | + "list-upgradable" => { |
| 173 | + print_progress("Listing upgradable packages"); |
| 174 | + match execute_apt(vec!["list", "--upgradable"], use_sudo) { |
| 175 | + Ok(status) if status.success() => println!("{}", "Listed upgradable packages".green()), |
| 176 | + Ok(_) => println!("{}", "Failed to list upgradable packages".red()), |
| 177 | + Err(e) => println!("{} {}", "Error:".red(), e), |
| 178 | + } |
| 179 | + } |
| 180 | + "search" => { |
| 181 | + if args.len() < 3 { |
| 182 | + println!("{}", "Error: Search term required".red()); |
| 183 | + println!("Usage: hacker search <term>"); |
| 184 | + std::process::exit(1); |
| 185 | + } |
| 186 | + let term = &args[2]; |
| 187 | + print_progress(&format!("Searching for {}", term)); |
| 188 | + match execute_apt(vec!["search", term], use_sudo) { |
| 189 | + Ok(status) if status.success() => println!("{}", "Search completed".green()), |
| 190 | + Ok(_) => println!("{}", "Search failed".red()), |
| 191 | + Err(e) => println!("{} {}", "Error:".red(), e), |
| 192 | + } |
| 193 | + } |
| 194 | + "clean" => { |
| 195 | + print_progress("Cleaning package cache"); |
| 196 | + match execute_apt(vec!["clean"], use_sudo) { |
| 197 | + Ok(status) if status.success() => println!("{}", "Package cache cleaned successfully".green()), |
| 198 | + Ok(_) => println!("{}", "Failed to clean package cache".red()), |
| 199 | + Err(e) => println!("{} {}", "Error:".red(), e), |
| 200 | + } |
| 201 | + } |
| 202 | + "show" => { |
| 203 | + if args.len() < 3 { |
| 204 | + println!("{}", "Error: Package name required for show".red()); |
| 205 | + println!("Usage: hacker show <package>"); |
| 206 | + std::process::exit(1); |
| 207 | + } |
| 208 | + let package = &args[2]; |
| 209 | + print_progress(&format!("Showing info for {}", package)); |
| 210 | + match execute_apt(vec!["show", package], use_sudo) { |
| 211 | + Ok(status) if status.success() => println!("{}", "Package information displayed".green()), |
| 212 | + Ok(_) => println!("{}", "Failed to display package information".red()), |
| 213 | + Err(e) => println!("{} {}", "Error:".red(), e), |
| 214 | + } |
| 215 | + } |
| 216 | + "hold" => { |
| 217 | + if args.len() < 3 { |
| 218 | + println!("{}", "Error: Package name required for hold".red()); |
| 219 | + println!("Usage: hacker hold <package>"); |
| 220 | + std::process::exit(1); |
| 221 | + } |
| 222 | + let package = &args[2]; |
| 223 | + print_progress(&format!("Holding package {}", package)); |
| 224 | + match execute_apt(vec!["hold", package], use_sudo) { |
| 225 | + Ok(status) if status.success() => println!("{}", format!("Package {} set to hold", package).green()), |
| 226 | + Ok(_) => println!("{}", format!("Failed to hold package {}", package).red()), |
| 227 | + Err(e) => println!("{} {}", "Error:".red(), e), |
| 228 | + } |
| 229 | + } |
| 230 | + "unhold" => { |
| 231 | + if args.len() < 3 { |
| 232 | + println!("{}", "Error: Package name required for unhold".red()); |
| 233 | + println!("Usage: hacker unhold <package>"); |
| 234 | + std::process::exit(1); |
| 235 | + } |
| 236 | + let package = &args[2]; |
| 237 | + print_progress(&format!("Unholding package {}", package)); |
| 238 | + match execute_apt(vec!["unhold", package], use_sudo) { |
| 239 | + Ok(status) if status.success() => println!("{}", format!("Package {} set to unhold", package).green()), |
| 240 | + Ok(_) => println!("{}", format!("Failed to unhold package {}", package).red()), |
| 241 | + Err(e) => println!("{} {}", "Error:".red(), e), |
| 242 | + } |
| 243 | + } |
| 244 | + "repolist" => { |
| 245 | + print_progress("Refreshing repository list"); |
| 246 | + match execute_apt(vec!["-o", "Debug::pkgProblemResolver=yes", "update"], use_sudo) { |
| 247 | + Ok(status) if status.success() => println!("{}", "Repository list refreshed (use 'less /etc/apt/sources.list' for details)".green()), |
| 248 | + Ok(_) => println!("{}", "Failed to refresh repository list".red()), |
| 249 | + Err(e) => println!("{} {}", "Error:".red(), e), |
| 250 | + } |
| 251 | + } |
| 252 | + "check" => { |
| 253 | + print_progress("Checking for broken dependencies"); |
| 254 | + match execute_apt(vec!["check"], use_sudo) { |
| 255 | + Ok(status) if status.success() => println!("{}", "Dependency check completed successfully".green()), |
| 256 | + Ok(_) => println!("{}", "Dependency check found issues".red()), |
| 257 | + Err(e) => println!("{} {}", "Error:".red(), e), |
| 258 | + } |
| 259 | + } |
| 260 | + "entry" => { |
| 261 | + print_progress("Launching HackerOS cybersecurity container"); |
| 262 | + match execute_entry() { |
| 263 | + Ok(status) if status.success() => println!("{}", "HackerOS cybersecurity container launched successfully".green()), |
| 264 | + Ok(_) => println!("{}", "Failed to launch HackerOS cybersecurity container".red()), |
| 265 | + Err(e) => println!("{} {}", "Error:".red(), e), |
| 266 | + } |
| 267 | + } |
| 268 | + "version" => { |
| 269 | + println!("{}", format!("HackerOS Package Manager v{}", VERSION).bold().green()); |
| 270 | + } |
| 271 | + "update" | "upgrade" => { |
| 272 | + println!("{}", "Error: Use 'hacker-update' for system updates and upgrades.".red()); |
| 273 | + std::process::exit(1); |
| 274 | + } |
| 275 | + "?" => { |
| 276 | + print_help(); |
| 277 | + } |
| 278 | + _ => { |
| 279 | + println!("{}", format!("Error: Unknown command '{}'", command).red()); |
| 280 | + print_help(); |
| 281 | + std::process::exit(1); |
| 282 | + } |
| 283 | + } |
| 284 | +} |
0 commit comments