diff --git a/Cargo.lock b/Cargo.lock index 5168b8cfc9..f843fd90dd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2449,6 +2449,30 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +[[package]] +name = "utmp-classic" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e24c654e19afaa6b8f3877ece5d3bed849c2719c56f6752b18ca7da4fcc6e85a" +dependencies = [ + "cfg-if", + "libc", + "thiserror", + "time", + "utmp-classic-raw", + "zerocopy", +] + +[[package]] +name = "utmp-classic-raw" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22c226537a3d6e01c440c1926ca0256dbee2d19b2229ede6fc4863a6493dd831" +dependencies = [ + "cfg-if", + "zerocopy", +] + [[package]] name = "uu_arch" version = "0.0.27" @@ -3390,6 +3414,7 @@ name = "uu_users" version = "0.0.27" dependencies = [ "clap", + "utmp-classic", "uucore", ] @@ -3897,18 +3922,19 @@ checksum = "2a599daf1b507819c1121f0bf87fa37eb19daac6aff3aefefd4e6e2e0f2020fc" [[package]] name = "zerocopy" -version = "0.7.33" +version = "0.7.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "087eca3c1eaf8c47b94d02790dd086cd594b912d2043d4de4bfdd466b3befb7c" +checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" dependencies = [ + "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.33" +version = "0.7.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f4b6c273f496d8fd4eaf18853e6b448760225dc030ff2c485a786859aea6393" +checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index ba43dfac7b..e7080a1e75 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -334,6 +334,7 @@ time = { version = "0.3.36" } unicode-segmentation = "1.11.0" unicode-width = "0.1.12" utf-8 = "0.7.6" +utmp-classic = "0.1.6" walkdir = "2.5" winapi-util = "0.1.8" windows-sys = { version = "0.48.0", default-features = false } diff --git a/src/uu/users/Cargo.toml b/src/uu/users/Cargo.toml index 8b280c7a6d..9625bbf502 100644 --- a/src/uu/users/Cargo.toml +++ b/src/uu/users/Cargo.toml @@ -18,6 +18,9 @@ path = "src/users.rs" clap = { workspace = true } uucore = { workspace = true, features = ["utmpx"] } +[target.'cfg(target_os = "openbsd")'.dependencies] +utmp-classic = { workspace = true } + [[bin]] name = "users" path = "src/main.rs" diff --git a/src/uu/users/src/platform/mod.rs b/src/uu/users/src/platform/mod.rs deleted file mode 100644 index e0e87dca1b..0000000000 --- a/src/uu/users/src/platform/mod.rs +++ /dev/null @@ -1,14 +0,0 @@ -// This file is part of the uutils coreutils package. -// -// For the full copyright and license information, please view the LICENSE -// file that was distributed with this source code. - -#[cfg(not(target_os = "openbsd"))] -mod unix; -#[cfg(not(target_os = "openbsd"))] -pub use self::unix::*; - -#[cfg(target_os = "openbsd")] -mod openbsd; -#[cfg(target_os = "openbsd")] -pub use self::openbsd::*; diff --git a/src/uu/users/src/platform/openbsd.rs b/src/uu/users/src/platform/openbsd.rs deleted file mode 100644 index 7e6970c1f0..0000000000 --- a/src/uu/users/src/platform/openbsd.rs +++ /dev/null @@ -1,17 +0,0 @@ -// This file is part of the uutils coreutils package. -// -// For the full copyright and license information, please view the LICENSE -// file that was distributed with this source code. - -// Specific implementation for OpenBSD: tool unsupported (utmpx not supported) - -use crate::uu_app; - -use uucore::error::UResult; - -pub fn uumain(args: impl uucore::Args) -> UResult<()> { - let _matches = uu_app().try_get_matches_from(args)?; - - println!("unsupported command on OpenBSD"); - Ok(()) -} diff --git a/src/uu/users/src/platform/unix.rs b/src/uu/users/src/platform/unix.rs deleted file mode 100644 index 99c9ce776b..0000000000 --- a/src/uu/users/src/platform/unix.rs +++ /dev/null @@ -1,53 +0,0 @@ -// This file is part of the uutils coreutils package. -// -// For the full copyright and license information, please view the LICENSE -// file that was distributed with this source code. - -// spell-checker:ignore (paths) wtmp - -use crate::uu_app; - -use std::ffi::OsString; -use std::path::Path; - -use uucore::error::UResult; -use uucore::utmpx::{self, Utmpx}; - -static ARG_FILES: &str = "files"; - -fn get_long_usage() -> String { - format!( - "Output who is currently logged in according to FILE. -If FILE is not specified, use {}. /var/log/wtmp as FILE is common.", - utmpx::DEFAULT_FILE - ) -} - -pub fn uumain(args: impl uucore::Args) -> UResult<()> { - let matches = uu_app() - .after_help(get_long_usage()) - .try_get_matches_from(args)?; - - let files: Vec<&Path> = matches - .get_many::(ARG_FILES) - .map(|v| v.map(AsRef::as_ref).collect()) - .unwrap_or_default(); - - let filename = if files.is_empty() { - utmpx::DEFAULT_FILE.as_ref() - } else { - files[0] - }; - - let mut users = Utmpx::iter_all_records_from(filename) - .filter(Utmpx::is_user_process) - .map(|ut| ut.user()) - .collect::>(); - - if !users.is_empty() { - users.sort(); - println!("{}", users.join(" ")); - } - - Ok(()) -} diff --git a/src/uu/users/src/users.rs b/src/uu/users/src/users.rs index d299399f31..a6978a8d94 100644 --- a/src/uu/users/src/users.rs +++ b/src/uu/users/src/users.rs @@ -5,19 +5,97 @@ // spell-checker:ignore (paths) wtmp +use std::ffi::OsString; +use std::path::Path; + use clap::builder::ValueParser; use clap::{crate_version, Arg, Command}; +use uucore::error::UResult; use uucore::{format_usage, help_about, help_usage}; -mod platform; +#[cfg(target_os = "openbsd")] +use utmp_classic::{parse_from_path, UtmpEntry}; +#[cfg(not(target_os = "openbsd"))] +use uucore::utmpx::{self, Utmpx}; const ABOUT: &str = help_about!("users.md"); const USAGE: &str = help_usage!("users.md"); +#[cfg(target_os = "openbsd")] +const OPENBSD_UTMP_FILE: &str = "/var/run/utmp"; + static ARG_FILES: &str = "files"; +fn get_long_usage() -> String { + #[cfg(not(target_os = "openbsd"))] + let default_path: &str = utmpx::DEFAULT_FILE; + #[cfg(target_os = "openbsd")] + let default_path: &str = OPENBSD_UTMP_FILE; + format!( + "Output who is currently logged in according to FILE. +If FILE is not specified, use {}. /var/log/wtmp as FILE is common.", + default_path + ) +} + #[uucore::main] -use platform::uumain; +pub fn uumain(args: impl uucore::Args) -> UResult<()> { + let matches = uu_app() + .after_help(get_long_usage()) + .try_get_matches_from(args)?; + + let files: Vec<&Path> = matches + .get_many::(ARG_FILES) + .map(|v| v.map(AsRef::as_ref).collect()) + .unwrap_or_default(); + + let mut users: Vec; + + // OpenBSD uses the Unix version 1 UTMP, all other Unixes use the newer UTMPX + #[cfg(target_os = "openbsd")] + { + let filename = if files.is_empty() { + Path::new(OPENBSD_UTMP_FILE) + } else { + files[0] + }; + let entries = parse_from_path(&filename).unwrap_or(Vec::new()); + users = Vec::new(); + for entry in entries { + if let UtmpEntry::UTMP { + line: _, + user, + host: _, + time: _, + } = entry + { + if !user.is_empty() { + users.push(user); + } + } + } + }; + #[cfg(not(target_os = "openbsd"))] + { + let filename = if files.is_empty() { + utmpx::DEFAULT_FILE.as_ref() + } else { + files[0] + }; + + users = Utmpx::iter_all_records_from(filename) + .filter(Utmpx::is_user_process) + .map(|ut| ut.user()) + .collect::>(); + }; + + if !users.is_empty() { + users.sort(); + println!("{}", users.join(" ")); + } + + Ok(()) +} pub fn uu_app() -> Command { Command::new(uucore::util_name()) diff --git a/tests/by-util/test_users.rs b/tests/by-util/test_users.rs index 3d87aa9d06..9ca548fb94 100644 --- a/tests/by-util/test_users.rs +++ b/tests/by-util/test_users.rs @@ -31,3 +31,12 @@ fn test_users_check_name() { new_ucmd!().succeeds().stdout_is(&expected); } + +#[test] +#[cfg(target_os = "openbsd")] +fn test_users_check_name_openbsd() { + new_ucmd!() + .args(&["openbsd_utmp"]) + .run() + .stdout_contains("test"); +} diff --git a/tests/fixtures/users/openbsd_utmp b/tests/fixtures/users/openbsd_utmp new file mode 100644 index 0000000000..958d7510c3 Binary files /dev/null and b/tests/fixtures/users/openbsd_utmp differ