Skip to content

Commit 28a9bed

Browse files
authored
Update main.rs
1 parent 757609b commit 28a9bed

File tree

1 file changed

+107
-23
lines changed

1 file changed

+107
-23
lines changed

src/main.rs

Lines changed: 107 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,104 @@
11
use std::process::{Command, ExitStatus};
22
use std::env;
3+
use std::os::unix::fs::PermissionsExt;
34

45
const DNF_PATH: &str = "/usr/lib/HackerOS/dnf";
56

67
fn print_help() {
78
println!("hacker: A simple package management tool");
89
println!("Usage: hacker <command> [arguments]");
910
println!("\nAvailable commands:");
10-
println!(" autoremove Remove unneeded packages");
11-
println!(" install <package> Install a package");
12-
println!(" remove <package> Remove a package");
13-
println!(" list List installed packages");
14-
println!(" search <term> Search for packages");
15-
println!(" ? Show this help message");
16-
println!("\nNote: Use 'hacker-update' for updates and upgrades.");
11+
println!(" autoremove Remove unneeded packages");
12+
println!(" install <packages> Install one or more packages");
13+
println!(" remove <packages> Remove one or more packages");
14+
println!(" list List installed packages");
15+
println!(" search <term> Search for packages");
16+
println!(" clean Clean package cache");
17+
println!(" info <package> Show package information");
18+
println!(" repolist List enabled repositories");
19+
println!(" copr-enable <repo> Enable a COPR repository");
20+
println!(" copr-disable <repo> Disable a COPR repository");
21+
println!(" ? Show this help message");
22+
println!("\nNote: Use 'hacker-update' for system updates and upgrades.");
1723
}
1824

19-
fn execute_dnf(args: Vec<&str>) -> Result<ExitStatus, String> {
20-
let output = Command::new(DNF_PATH)
25+
fn execute_dnf(args: Vec<&str>, use_sudo: bool) -> Result<ExitStatus, String> {
26+
let mut command = if use_sudo {
27+
let mut cmd = Command::new("sudo");
28+
cmd.arg(DNF_PATH);
29+
cmd
30+
} else {
31+
Command::new(DNF_PATH)
32+
};
33+
34+
let output = command
2135
.args(&args)
2236
.status()
2337
.map_err(|e| format!("Failed to execute dnf: {}", e))?;
2438
Ok(output)
2539
}
2640

41+
fn can_run_without_sudo() -> bool {
42+
// Check if user has write permissions to /usr/lib/HackerOS/dnf
43+
if let Ok(metadata) = std::fs::metadata(DNF_PATH) {
44+
let permissions = metadata.permissions();
45+
let mode = permissions.mode();
46+
// Check if executable and writable by user or group
47+
(mode & 0o111) != 0 && (mode & 0o600) != 0
48+
} else {
49+
false
50+
}
51+
}
52+
2753
fn main() {
2854
let args: Vec<String> = env::args().collect();
29-
3055
if args.len() < 2 {
3156
println!("Error: No command provided");
3257
print_help();
3358
std::process::exit(1);
3459
}
3560

3661
let command = &args[1];
62+
let use_sudo = !can_run_without_sudo();
3763

3864
match command.as_str() {
3965
"autoremove" => {
40-
match execute_dnf(vec!["autoremove", "-y"]) {
66+
match execute_dnf(vec!["autoremove", "-y"], use_sudo) {
4167
Ok(status) if status.success() => println!("Autoremove completed successfully"),
4268
Ok(_) => println!("Autoremove failed"),
4369
Err(e) => println!("Error: {}", e),
4470
}
4571
}
4672
"install" => {
4773
if args.len() < 3 {
48-
println!("Error: Package name required for install");
74+
println!("Error: At least one package name required for install");
4975
std::process::exit(1);
5076
}
51-
let package = &args[2];
52-
match execute_dnf(vec!["install", "-y", package]) {
53-
Ok(status) if status.success() => println!("Package {} installed successfully", package),
54-
Ok(_) => println!("Failed to install package {}", package),
77+
let packages = &args[2..];
78+
let mut dnf_args = vec!["install", "-y"];
79+
dnf_args.extend(packages.iter().map(|s| s.as_str()));
80+
match execute_dnf(dnf_args, use_sudo) {
81+
Ok(status) if status.success() => println!("Package(s) {} installed successfully", packages.join(" ")),
82+
Ok(_) => println!("Failed to install package(s) {}", packages.join(" ")),
5583
Err(e) => println!("Error: {}", e),
5684
}
5785
}
5886
"remove" => {
5987
if args.len() < 3 {
60-
println!("Error: Package name required for remove");
88+
println!("Error: At least one package name required for remove");
6189
std::process::exit(1);
6290
}
63-
let package = &args[2];
64-
match execute_dnf(vec!["remove", "-y", package]) {
65-
Ok(status) if status.success() => println!("Package {} removed successfully", package),
66-
Ok(_) => println!("Failed to remove package {}", package),
91+
let packages = &args[2..];
92+
let mut dnf_args = vec!["remove", "-y"];
93+
dnf_args.extend(packages.iter().map(|s| s.as_str()));
94+
match execute_dnf(dnf_args, use_sudo) {
95+
Ok(status) if status.success() => println!("Package(s) {} removed successfully", packages.join(" ")),
96+
Ok(_) => println!("Failed to remove package(s) {}", packages.join(" ")),
6797
Err(e) => println!("Error: {}", e),
6898
}
6999
}
70100
"list" => {
71-
match execute_dnf(vec!["list", "installed"]) {
101+
match execute_dnf(vec!["list", "installed"], use_sudo) {
72102
Ok(status) if status.success() => println!("Listed installed packages"),
73103
Ok(_) => println!("Failed to list packages"),
74104
Err(e) => println!("Error: {}", e),
@@ -80,12 +110,66 @@ fn main() {
80110
std::process::exit(1);
81111
}
82112
let term = &args[2];
83-
match execute_dnf(vec!["search", term]) {
113+
match execute_dnf(vec!["search", term], use_sudo) {
84114
Ok(status) if status.success() => println!("Search completed"),
85115
Ok(_) => println!("Search failed"),
86116
Err(e) => println!("Error: {}", e),
87117
}
88118
}
119+
"clean" => {
120+
match execute_dnf(vec!["clean", "all"], use_sudo) {
121+
Ok(status) if status.success() => println!("Package cache cleaned successfully"),
122+
Ok(_) => println!("Failed to clean package cache"),
123+
Err(e) => println!("Error: {}", e),
124+
}
125+
}
126+
"info" => {
127+
if args.len() < 3 {
128+
println!("Error: Package name required for info");
129+
std::process::exit(1);
130+
}
131+
let package = &args[2];
132+
match execute_dnf(vec!["info", package], use_sudo) {
133+
Ok(status) if status.success() => println!("Package information displayed"),
134+
Ok(_) => println!("Failed to display package information"),
135+
Err(e) => println!("Error: {}", e),
136+
}
137+
}
138+
"repolist" => {
139+
match execute_dnf(vec!["repolist"], use_sudo) {
140+
Ok(status) if status.success() => println!("Repository list displayed"),
141+
Ok(_) => println!("Failed to display repository list"),
142+
Err(e) => println!("Error: {}", e),
143+
}
144+
}
145+
"copr-enable" => {
146+
if args.len() < 3 {
147+
println!("Error: COPR repository name required");
148+
std::process::exit(1);
149+
}
150+
let repo = &args[2];
151+
match execute_dnf(vec!["copr", "enable", repo], use_sudo) {
152+
Ok(status) if status.success() => println!("COPR repository {} enabled", repo),
153+
Ok(_) => println!("Failed to enable COPR repository {}", repo),
154+
Err(e) => println!("Error: {}", e),
155+
}
156+
}
157+
"copr-disable" => {
158+
if args.len() < 3 {
159+
println!("Error: COPR repository name required");
160+
std::process::exit(1);
161+
}
162+
let repo = &args[2];
163+
match execute_dnf(vec!["copr", "disable", repo], use_sudo) {
164+
Ok(status) if status.success() => println!("COPR repository {} disabled", repo),
165+
Ok(_) => println!("Failed to disable COPR repository {}", repo),
166+
Err(e) => println!("Error: {}", e),
167+
}
168+
}
169+
"update" | "upgrade" => {
170+
println!("Error: Use 'hacker-update' for system updates and upgrades.");
171+
std::process::exit(1);
172+
}
89173
"?" => {
90174
print_help();
91175
}

0 commit comments

Comments
 (0)