Implement ctrlaltdel (#31)

* Implement ctrlaltdel

* Add tests for `ctrlaltdel`

* Bless the unit tests on unsupported platforms
This commit is contained in:
sisungo
2024-05-12 19:37:17 +08:00
committed by GitHub
parent 572f84b1f3
commit c9ee7d6447
8 changed files with 191 additions and 0 deletions

9
Cargo.lock generated
View File

@@ -641,12 +641,21 @@ dependencies = [
"rlimit",
"tempfile",
"textwrap",
"uu_ctrlaltdel",
"uu_lscpu",
"uu_mountpoint",
"uucore",
"xattr",
]
[[package]]
name = "uu_ctrlaltdel"
version = "0.0.1"
dependencies = [
"clap",
"uucore",
]
[[package]]
name = "uu_lscpu"
version = "0.0.1"

View File

@@ -27,6 +27,7 @@ default = ["feat_common_core"]
feat_common_core = [
"mountpoint",
"lscpu",
"ctrlaltdel",
]
[workspace.dependencies]
@@ -56,6 +57,7 @@ textwrap = { workspace = true }
#
lscpu = { optional = true, version = "0.0.1", package = "uu_lscpu", path = "src/uu/lscpu" }
mountpoint = { optional = true, version = "0.0.1", package = "uu_mountpoint", path = "src/uu/mountpoint" }
ctrlaltdel = { optional = true, version = "0.0.1", package = "uu_ctrlaltdel", path = "src/uu/ctrlaltdel" }
[dev-dependencies]
pretty_assertions = "1"

View File

@@ -0,0 +1,15 @@
[package]
name = "uu_ctrlaltdel"
version = "0.0.1"
edition = "2021"
[lib]
path = "src/ctrlaltdel.rs"
[[bin]]
name = "ctrlaltdel"
path = "src/main.rs"
[dependencies]
uucore = { workspace = true }
clap = { workspace = true }

View File

@@ -0,0 +1,7 @@
# ctrlaltdel
```
ctrlaltdel hard|soft
```
set the function of the ctrl-alt-del combination

View File

@@ -0,0 +1,139 @@
// This file is part of the uutils util-linux package.
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
use clap::{crate_version, Arg, ArgAction, Command};
use uucore::{error::UResult, format_usage, help_about, help_usage};
const ABOUT: &str = help_about!("ctrlaltdel.md");
const USAGE: &str = help_usage!("ctrlaltdel.md");
#[cfg(target_os = "linux")]
const CTRL_ALT_DEL_PATH: &str = "/proc/sys/kernel/ctrl-alt-del";
#[cfg(target_os = "linux")]
#[uucore::main]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let matches: clap::ArgMatches = uu_app().try_get_matches_from(args)?;
let pattern = matches.get_one::<String>("pattern");
match pattern {
Some(x) if x == "hard" => {
set_ctrlaltdel(CtrlAltDel::Hard)?;
}
Some(x) if x == "soft" => {
set_ctrlaltdel(CtrlAltDel::Soft)?;
}
Some(x) => {
Err(Error::UnknownArgument(x.clone()))?;
}
None => {
println!("{}", get_ctrlaltdel()?);
}
}
Ok(())
}
#[cfg(not(target_os = "linux"))]
#[uucore::main]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let _matches: clap::ArgMatches = uu_app().try_get_matches_from(args)?;
Err(uucore::error::USimpleError::new(
1,
"`ctrlaltdel` is unavailable on current platform.",
))
}
#[cfg(target_os = "linux")]
fn get_ctrlaltdel() -> UResult<CtrlAltDel> {
let value: i32 = std::fs::read_to_string(CTRL_ALT_DEL_PATH)?
.trim()
.parse()
.map_err(|_| Error::UnknownData)?;
Ok(CtrlAltDel::from_sysctl(value))
}
#[cfg(target_os = "linux")]
fn set_ctrlaltdel(ctrlaltdel: CtrlAltDel) -> UResult<()> {
std::fs::write(CTRL_ALT_DEL_PATH, format!("{}\n", ctrlaltdel.to_sysctl()))
.map_err(|_| Error::NotRoot)?;
Ok(())
}
#[cfg(target_os = "linux")]
#[derive(Clone, Copy)]
enum CtrlAltDel {
Soft,
Hard,
}
#[cfg(target_os = "linux")]
impl CtrlAltDel {
/// # Panics
/// Panics if value of the parameter `value` is neither `0` nor `1`.
fn from_sysctl(value: i32) -> Self {
match value {
0 => Self::Soft,
1 => Self::Hard,
_ => unreachable!(),
}
}
fn to_sysctl(self) -> i32 {
match self {
Self::Soft => 0,
Self::Hard => 1,
}
}
}
#[cfg(target_os = "linux")]
impl std::fmt::Display for CtrlAltDel {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Soft => write!(f, "soft"),
Self::Hard => write!(f, "hard"),
}
}
}
#[cfg(target_os = "linux")]
#[derive(Debug)]
enum Error {
NotRoot,
UnknownArgument(String),
UnknownData,
}
#[cfg(target_os = "linux")]
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::NotRoot => write!(f, "You must be root to set the Ctrl-Alt-Del behavior"),
Self::UnknownArgument(x) => write!(f, "unknown argument: {x}"),
Self::UnknownData => write!(f, "unknown data"),
}
}
}
#[cfg(target_os = "linux")]
impl std::error::Error for Error {}
#[cfg(target_os = "linux")]
impl uucore::error::UError for Error {
fn code(&self) -> i32 {
1
}
fn usage(&self) -> bool {
false
}
}
pub fn uu_app() -> Command {
Command::new(uucore::util_name())
.version(crate_version!())
.about(ABOUT)
.override_usage(format_usage(USAGE))
.infer_long_args(true)
.arg(Arg::new("pattern").action(ArgAction::Set))
}

View File

@@ -0,0 +1 @@
uucore::bin!(uu_ctrlaltdel);

View File

@@ -0,0 +1,14 @@
// This file is part of the uutils util-linux package.
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
// spell-checker:ignore (words) symdir somefakedir
#[cfg(target_os = "linux")]
use crate::common::util::TestScenario;
#[test]
#[cfg(target_os = "linux")]
fn test_invalid_arg() {
new_ucmd!().arg("--definitely-invalid").fails().code_is(1);
}

View File

@@ -12,3 +12,7 @@ mod test_lscpu;
#[cfg(feature = "mountpoint")]
#[path = "by-util/test_mountpoint.rs"]
mod test_mountpoint;
#[cfg(feature = "ctrlaltdel")]
#[path = "by-util/test_ctrlaltdel.rs"]
mod test_ctrlaltdel;