utmp-classic-raw-0.1.3/.cargo_vcs_info.json0000644000000001410000000000100142240ustar { "git": { "sha1": "98ba8e7df49e9ec6df11290b926c1a971ebaf943" }, "path_in_vcs": "raw" }utmp-classic-raw-0.1.3/Cargo.toml0000644000000017210000000000100122270ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" name = "utmp-classic-raw" version = "0.1.3" authors = ["Jadi "] description = "Provides raw types for parsing login records in classic utmp (UNIXv1 & OpenBSD) file" readme = "README.md" keywords = [ "utmp", "openbsd", "unix", "login", ] categories = ["os::unix-apis"] license = "MIT" repository = "https://github.com/jadijadi/utmp-classic" [dependencies.cfg-if] version = "1.0.0" [dependencies.zerocopy] version = "0.7.34" features = ["derive"] utmp-classic-raw-0.1.3/Cargo.toml.orig000064400000000000000000000007301046102023000157070ustar 00000000000000[package] name = "utmp-classic-raw" edition = "2021" description = "Provides raw types for parsing login records in classic utmp (UNIXv1 & OpenBSD) file" keywords = ["utmp", "openbsd", "unix", "login"] categories = ["os::unix-apis"] authors = ["Jadi "] repository = "https://github.com/jadijadi/utmp-classic" license = "MIT" version = "0.1.3" readme = "README.md" [dependencies] cfg-if = "1.0.0" zerocopy = {version = "0.7.34", features = ["derive"]} utmp-classic-raw-0.1.3/LICENSE000064400000000000000000000020451046102023000140260ustar 00000000000000MIT License Copyright (c) 2024 Jadi Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. utmp-classic-raw-0.1.3/README.md000064400000000000000000000016021046102023000142760ustar 00000000000000# utmp-classic Rust library for reading utmp files. Please note that all Unix like systems (Including all GNU/Linuxes, MacOS and all BSDs except OpenBSD) use the newer `utmpx` file format, even if they still call it `utmp`. This library works only for original Unix `utmp` files which is only used in OpenBSD as far as I know. If you are looking for a lib to be used on anything other than OpenBSD; you might be looking for a `utmpx` library, although most of them calls themselves `utmp`; not sure why :D # sample run A sample `utmp` file is included in the root directory, you can run a sample by issuing: ``` cargo run --package utmp-classic --example dump-utmp tests/samples/basic.utmp ``` # history This library is a modification ofn `[utmp-rs](https://github.com/upsuper/utmp-rs)` by *upsuper*. It is updated to work on the classic AT&T Unix v1 style `utmp` files still used by OpenBSD.utmp-classic-raw-0.1.3/src/dump_utmp.rs000064400000000000000000000015651046102023000161760ustar 00000000000000use std::env; use std::fs::File; use std::io; use std::io::Read; use std::mem; use std::path::PathBuf; use std::process; use utmp_classic::utmp; use zerocopy::Ref; const SIZE: usize = mem::size_of::(); #[repr(align(8))] struct Buffer([u8; SIZE]); fn main() -> io::Result<()> { let mut args = env::args_os(); let program_name = PathBuf::from(args.next().unwrap()); let path = match args.next() { Some(path) => PathBuf::from(path), None => { eprintln!("Usage: {} ", program_name.display()); process::exit(2); } }; let mut f = File::open(&path)?; let mut buffer = Buffer([0; SIZE]); while let Ok(()) = f.read_exact(&mut buffer.0) { let buffer = buffer.0.as_ref(); let record = Ref::<_, utmp>::new(buffer).unwrap().into_ref(); println!("{:#?}", record); } Ok(()) } utmp-classic-raw-0.1.3/src/lib.rs000064400000000000000000000043621046102023000147300ustar 00000000000000#![allow(non_camel_case_types)] use cfg_if::cfg_if; use std::ffi::CStr; use std::os::raw::c_short; pub mod x32; pub mod x64; /// Record does not contain valid info (formerly known as `UT_UNKNOWN` on Linux) pub const EMPTY: c_short = 0; /// Change in system run-level (see `init(8)`) pub const RUN_LVL: c_short = 1; /// Time of system boot (in `ut_tv`) pub const BOOT_TIME: c_short = 2; /// Time after system clock change (in `ut_tv`) pub const NEW_TIME: c_short = 3; /// Time before system clock change (in `ut_tv`) pub const OLD_TIME: c_short = 4; /// Process spawned by `init(8)` pub const INIT_PROCESS: c_short = 5; /// Session leader process for user login pub const LOGIN_PROCESS: c_short = 6; /// Normal process pub const USER_PROCESS: c_short = 7; /// Terminated process pub const DEAD_PROCESS: c_short = 8; /// Not implemented pub const ACCOUNTING: c_short = 9; pub const UTMP: c_short = 10; pub const UT_LINESIZE: usize = 8; pub const UT_NAMESIZE: usize = 32; pub const UT_HOSTSIZE: usize = 256; /// Type for `ut_exit`, below #[repr(C)] #[derive(Clone, Copy, Debug)] pub struct exit_status { /// Process termination status pub e_termination: c_short, /// Process exit status pub e_exit: c_short, } cfg_if! { if #[cfg(any( target_arch = "x86", target_arch = "x86_64", target_arch = "arm", target_arch = "mips", target_arch = "mips64", target_arch = "powerpc", target_arch = "powerpc64", target_arch = "riscv32", target_arch = "riscv64", target_arch = "sparc", target_arch = "sparc64", target_arch = "aarch64", ))] { pub use x32::*; } else if #[cfg(any( target_arch = "s390x", ))] { pub use x64::*; } else { compile_error!("The target platform is not supported, please help us add it."); } } fn cstr_from_bytes(bytes: &[u8]) -> &CStr { match bytes.iter().position(|b| *b == 0) { // This is safe because we manually located the first zero byte above. Some(pos) => unsafe { CStr::from_bytes_with_nul_unchecked(&bytes[..=pos]) }, // This is safe because we manually generated this string. None => unsafe { CStr::from_bytes_with_nul_unchecked("???\0".as_bytes()) }, } } utmp-classic-raw-0.1.3/src/x32.rs000064400000000000000000000021601046102023000145700ustar 00000000000000use super::{cstr_from_bytes, UT_HOSTSIZE, UT_LINESIZE, UT_NAMESIZE}; use std::fmt; use zerocopy::{FromZeroes, FromBytes}; #[derive(FromZeroes, FromBytes, Clone, Copy, Debug)] #[repr(C)] pub struct timeval { /// Seconds pub tv_sec: i32, /// Microseconds pub tv_usec: i32, } #[derive(FromZeroes, Clone, Copy, FromBytes)] #[repr(C)] pub struct utmp { /// Device name of tty - `"/dev/"` pub ut_line: [u8; UT_LINESIZE], /// Username pub ut_user: [u8; UT_NAMESIZE], /// Hostname for remote login, or kernel version for run-level message pub ut_host: [u8; UT_HOSTSIZE], /// Time entry was made pub ut_tv: timeval, } impl fmt::Debug for utmp { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct("utmp") .field("ut_line", &cstr_from_bytes(&self.ut_line)) .field("ut_user", &cstr_from_bytes(&self.ut_user)) .field("ut_host", &cstr_from_bytes(&self.ut_host)) .field("ut_tv", &self.ut_tv) .finish() } } #[test] fn test_size_of_utmp_x32() { assert_eq!(std::mem::size_of::(), 304); } utmp-classic-raw-0.1.3/src/x64.rs000064400000000000000000000021571046102023000146030ustar 00000000000000use super::{cstr_from_bytes, UT_HOSTSIZE, UT_LINESIZE, UT_NAMESIZE}; use std::fmt; use zerocopy::{FromZeroes, FromBytes}; #[repr(C)] #[derive(Clone, Copy, Debug, FromZeroes, FromBytes)] pub struct timeval { /// Seconds pub tv_sec: i64, /// Microseconds pub tv_usec: i64, } #[repr(C)] #[derive(Clone, Copy, FromZeroes, FromBytes)] pub struct utmp { /// Device name of tty - `"/dev/"` pub ut_line: [u8; UT_LINESIZE], /// Username pub ut_user: [u8; UT_NAMESIZE], /// Hostname for remote login, or kernel version for run-level message pub ut_host: [u8; UT_HOSTSIZE], /// Time entry was made pub ut_tv: timeval, } impl fmt::Debug for utmp { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct("utmp") .field("ut_line", &cstr_from_bytes(&self.ut_line)) .field("ut_user", &cstr_from_bytes(&self.ut_user)) .field("ut_host", &cstr_from_bytes(&self.ut_host)) .field("ut_tv", &self.ut_tv) .finish() } } #[test] fn test_size_of_utmp_x64() { assert_eq!(std::mem::size_of::(), 312); }