summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--Cargo.lock156
-rw-r--r--Cargo.toml2
-rw-r--r--where-rs/Cargo.toml2
-rw-r--r--where-rs/src/main.rs84
-rw-r--r--where-shared/Cargo.toml2
-rw-r--r--where-shared/src/error.rs2
-rw-r--r--where-shared/src/lib.rs27
-rw-r--r--whered/Cargo.toml2
-rw-r--r--whered/src/main.rs2
10 files changed, 262 insertions, 19 deletions
diff --git a/.gitignore b/.gitignore
index 1edb211..6abfe1b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,2 @@
/target
-/.direnv \ No newline at end of file
+/.direnv
diff --git a/Cargo.lock b/Cargo.lock
index 86d2aea..392ca06 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -12,6 +12,27 @@ dependencies = [
]
[[package]]
+name = "android-tzdata"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
+
+[[package]]
+name = "android_system_properties"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+
+[[package]]
name = "base-x"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -35,18 +56,44 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea184aa71bb362a1157c896979544cc23974e08fd265f29ea96b59f0b4a555b"
[[package]]
+name = "cc"
+version = "1.0.90"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5"
+
+[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
+name = "chrono"
+version = "0.4.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a"
+dependencies = [
+ "android-tzdata",
+ "iana-time-zone",
+ "js-sys",
+ "num-traits",
+ "wasm-bindgen",
+ "windows-targets",
+]
+
+[[package]]
name = "const_fn"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbdcdcb6d86f71c5e97409ad45898af11cbc995b4ee8112d59095a28d376c935"
[[package]]
+name = "core-foundation-sys"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
+
+[[package]]
name = "coreutils_core"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -65,12 +112,44 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
[[package]]
+name = "iana-time-zone"
+version = "0.1.60"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
+dependencies = [
+ "android_system_properties",
+ "core-foundation-sys",
+ "iana-time-zone-haiku",
+ "js-sys",
+ "wasm-bindgen",
+ "windows-core",
+]
+
+[[package]]
+name = "iana-time-zone-haiku"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
+dependencies = [
+ "cc",
+]
+
+[[package]]
name = "itoa"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
[[package]]
+name = "js-sys"
+version = "0.3.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
+dependencies = [
+ "wasm-bindgen",
+]
+
+[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -95,6 +174,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
[[package]]
+name = "num-traits"
+version = "0.2.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
name = "once_cell"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -423,7 +511,7 @@ checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
name = "where-rs"
version = "0.1.0"
dependencies = [
- "coreutils_core",
+ "chrono",
"where-shared",
]
@@ -462,3 +550,69 @@ name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "windows-core"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
diff --git a/Cargo.toml b/Cargo.toml
index 0af0e97..6c79092 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,3 +1,3 @@
[workspace]
members = [ "where-rs", "whered", "where-shared"]
-resolver = "2" \ No newline at end of file
+resolver = "2"
diff --git a/where-rs/Cargo.toml b/where-rs/Cargo.toml
index 06cb9e1..42604ab 100644
--- a/where-rs/Cargo.toml
+++ b/where-rs/Cargo.toml
@@ -11,4 +11,4 @@ path = "src/main.rs"
[dependencies]
where-shared = { path = "../where-shared" }
-coreutils_core = "0.1.1"
+chrono = "0.4.35"
diff --git a/where-rs/src/main.rs b/where-rs/src/main.rs
index ba846a5..9bbfce5 100644
--- a/where-rs/src/main.rs
+++ b/where-rs/src/main.rs
@@ -1,8 +1,10 @@
+use std::cmp::max;
use std::net::UdpSocket;
use std::io::ErrorKind;
use std::time::Duration;
use where_shared::error::{WhereError, WhereResult};
use where_shared::{MAX_PAYLOAD_LENGTH, SessionCollection, WHERED_MAGIC};
+use chrono::prelude::*;
pub const TIMEOUT: Duration = Duration::from_millis(2000);
pub const MAX_SEND_RETRIES: usize = 3;
@@ -15,7 +17,85 @@ fn main() {
}
fn start_client() -> WhereResult<()> {
- println!("{:?}", process_server("127.0.0.1:15")?);
+ let servers = ["127.0.0.1:15"];
+ let mut entries = vec![];
+
+ for server in servers {
+ entries.extend(process_server(server)?.into_vec());
+ }
+
+ entries.sort_by_key(|s| s.login_time);
+ entries.sort_by_key(|s| !s.active);
+
+ let max_host_length = entries.iter()
+ .max_by_key(|s| match &s.host {
+ Some(remote) => remote,
+ None => ""
+ })
+ .unwrap()
+ .host.clone().unwrap().len();
+ let max_username_length = entries.iter()
+ .max_by_key(|s| s.user.as_str())
+ .unwrap()
+ .user.len();
+ let max_tty_length = entries.iter()
+ .max_by_key(|s| s.tty.as_str())
+ .unwrap()
+ .tty.len();
+ let max_pid_length = entries.iter()
+ .max_by_key(|s| s.pid.to_string())
+ .unwrap()
+ .pid.to_string().len();
+ let max_remote_length = entries.iter()
+ .max_by_key(|s| match &s.remote {
+ Some(remote) => remote,
+ None => "Local"
+ })
+ .unwrap()
+ .remote.clone().unwrap_or("Local".to_string()).len();
+
+ let max_host_length = max(max_host_length, 4);
+ let max_remote_length = max(max_remote_length, 6);
+ let max_username_length = max(max_username_length, 4);
+ let max_tty_length = max(max_tty_length, 3);
+ let max_pid_length = max(max_pid_length, 3);
+
+ println!("Act Host{} Source{} User{} TTY{} PID{} Since",
+ " ".repeat(max_host_length - 4),
+ " ".repeat(max_remote_length - 6),
+ " ".repeat(max_username_length - 4),
+ " ".repeat(max_tty_length - 3),
+ " ".repeat(max_pid_length - 3),
+ );
+
+ for session in entries {
+ let active_str = if session.active {
+ "*"
+ } else {
+ " "
+ };
+ let host_str = session.host.unwrap_or("".to_string());
+ let remote_str = session.remote.unwrap_or("Local".to_string());
+
+ let datetime = DateTime::from_timestamp(session.login_time, 0).unwrap();
+ let time_str = datetime.format("%Y-%m-%d %H:%M:%S");
+
+ println!(" {} {}{} {}{} {}{} {}{} {}{} {}",
+ active_str,
+ host_str,
+ " ".repeat(max(max_host_length, host_str.len()) - host_str.len()),
+ remote_str,
+ " ".repeat(max(max_remote_length, remote_str.len()) - remote_str.len()),
+ session.user,
+ " ".repeat(max(max_username_length, session.user.len()) - session.user.len()),
+ session.tty,
+ " ".repeat(max(max_tty_length, session.tty.len()) - session.tty.len()),
+ session.pid,
+ " ".repeat(max(max_pid_length, session.pid.to_string().len()) - session.pid.to_string().len()),
+ time_str
+ );
+ }
+
Ok(())
}
@@ -30,7 +110,7 @@ fn process_server(server: &str) -> WhereResult<SessionCollection> {
match socket.recv_from(&mut buf) {
Ok(_) => {
- return Ok(SessionCollection::from_udp_payload(buf)?);
+ return Ok(SessionCollection::from_udp_payload(buf, "My Computer")?);
},
Err(e) if e.kind() == ErrorKind::TimedOut || e.kind() == ErrorKind::WouldBlock => continue,
Err(e) => return Err(WhereError::from(e)),
diff --git a/where-shared/Cargo.toml b/where-shared/Cargo.toml
index 1f5507b..5bfeff2 100644
--- a/where-shared/Cargo.toml
+++ b/where-shared/Cargo.toml
@@ -6,4 +6,4 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-coreutils_core = "0.1.1" \ No newline at end of file
+coreutils_core = "0.1.1"
diff --git a/where-shared/src/error.rs b/where-shared/src/error.rs
index e94b042..5908077 100644
--- a/where-shared/src/error.rs
+++ b/where-shared/src/error.rs
@@ -64,4 +64,4 @@ impl Display for WhereError {
Self::TimedOut(server, max_retry, timeout) => write!(f, "Timed out waiting for data from {server} after {max_retry} attempts every {} ms", timeout.as_millis())
}
}
-} \ No newline at end of file
+}
diff --git a/where-shared/src/lib.rs b/where-shared/src/lib.rs
index d64b284..06cc5ba 100644
--- a/where-shared/src/lib.rs
+++ b/where-shared/src/lib.rs
@@ -14,12 +14,13 @@ pub const MAX_PAYLOAD_ENTRIES: usize = MAX_PAYLOAD_LENGTH / MAX_ENTRY_LENGTH;
#[derive(Debug)]
pub struct Session {
- user: String,
- pid: i32,
- tty: String,
- remote: Option<String>,
- active: bool,
- login_time: i64
+ pub host: Option<String>,
+ pub user: String,
+ pub pid: i32,
+ pub tty: String,
+ pub remote: Option<String>,
+ pub active: bool,
+ pub login_time: i64
}
#[derive(Debug)]
@@ -40,6 +41,10 @@ impl SessionCollection {
}
}
+ pub fn into_vec(self) -> Vec<Session> {
+ self.inner
+ }
+
pub fn to_udp_payload(self) -> EncodeDecodeResult<Vec<u8>> {
println!("Encoding payload with {} entries", self.inner.len());
@@ -66,7 +71,7 @@ impl SessionCollection {
}
}
- pub fn from_udp_payload(buffer: [u8; MAX_PAYLOAD_LENGTH]) -> EncodeDecodeResult<Self> {
+ pub fn from_udp_payload(buffer: [u8; MAX_PAYLOAD_LENGTH], host: &str) -> EncodeDecodeResult<Self> {
let mut buf = Cursor::new(buffer);
let mut inner = vec![];
let mut magic = [0u8; 4];
@@ -81,7 +86,7 @@ impl SessionCollection {
}
for _ in 0..entry_count {
- inner.push(Session::from_udp_payload(&mut buf)?);
+ inner.push(Session::from_udp_payload(&mut buf, &host)?);
}
if inner.len() != entry_count as usize {
@@ -95,7 +100,7 @@ impl SessionCollection {
}
impl Session {
- pub fn from_udp_payload(cursor: &mut Cursor<[u8; MAX_PAYLOAD_LENGTH]>) -> EncodeDecodeResult<Self> {
+ pub fn from_udp_payload(cursor: &mut Cursor<[u8; MAX_PAYLOAD_LENGTH]>, host: &str) -> EncodeDecodeResult<Self> {
let mut username_length = [0u8; 4];
let mut pid = [0u8; 4];
let mut tty_length = [0u8; 4];
@@ -162,7 +167,10 @@ impl Session {
let active = active[0] == 1;
let login_time = i64::from_be_bytes(login_time);
+ let host = Some(host.to_string());
+
Ok(Self {
+ host,
user,
pid,
tty,
@@ -247,6 +255,7 @@ impl From<Utmpx> for Session {
let login_time = utmpx.timeval().tv_sec;
Self {
+ host: None,
user,
pid,
tty,
diff --git a/whered/Cargo.toml b/whered/Cargo.toml
index 5e9d438..0bce8bf 100644
--- a/whered/Cargo.toml
+++ b/whered/Cargo.toml
@@ -6,4 +6,4 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-where-shared = { path = "../where-shared" } \ No newline at end of file
+where-shared = { path = "../where-shared" }
diff --git a/whered/src/main.rs b/whered/src/main.rs
index 6990dd6..47e97de 100644
--- a/whered/src/main.rs
+++ b/whered/src/main.rs
@@ -33,4 +33,4 @@ fn handle_request(socket: &UdpSocket) -> WhereResult<()> {
println!("{src}: Completed request within {} bytes", buf.len());
Ok(())
-} \ No newline at end of file
+}