Progress towards implementing the rwho server
This commit is contained in:
9
.gitignore
vendored
9
.gitignore
vendored
@@ -1,12 +1,3 @@
|
||||
/target
|
||||
result
|
||||
result-*
|
||||
|
||||
Cargo.lock
|
||||
|
||||
|
||||
# Added by cargo
|
||||
#
|
||||
# already existing elements were commented out
|
||||
|
||||
#/target
|
||||
|
||||
881
Cargo.lock
generated
881
Cargo.lock
generated
@@ -2,6 +2,15 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[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 = "anstream"
|
||||
version = "0.6.21"
|
||||
@@ -38,7 +47,7 @@ version = "1.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -49,14 +58,74 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"once_cell_polyfill",
|
||||
"windows-sys",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.19.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a0aeaff4ff1a90589618835a598e545176939b97874f7abc7851caa0618f203"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "cfg_aliases"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2"
|
||||
dependencies = [
|
||||
"iana-time-zone",
|
||||
"js-sys",
|
||||
"num-traits",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.53"
|
||||
version = "4.5.54"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c9e340e012a1bf4935f5282ed1436d1489548e8f72308207ea5df0e23d2d03f8"
|
||||
checksum = "c6e6ff9dcd79cff5cd969a17a545d79e84ab086e444102a591e288a8aa3ce394"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
@@ -64,14 +133,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.53"
|
||||
version = "4.5.54"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d76b5d13eaa18c901fd2f7fca939fefe3a0727a953561fefdf3b2922b8569d00"
|
||||
checksum = "fa42cf4d2b7a41bc8f663a7cab4031ebafa1bf3875705bfaf8466dc60ab52c00"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
"strsim",
|
||||
"terminal_size",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -98,12 +168,160 @@ version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587"
|
||||
dependencies = [
|
||||
"powerfmt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "displaydoc"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dns-lookup"
|
||||
version = "3.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e39034cee21a2f5bbb66ba0e3689819c4bb5d00382a282006e802a7ffa6c41d"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"socket2",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "645cbb3a84e60b7531617d5ae4e57f7e27308f6445f5abf653209ea76dec8dff"
|
||||
|
||||
[[package]]
|
||||
name = "fluent"
|
||||
version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8137a6d5a2c50d6b0ebfcb9aaa91a28154e0a70605f112d30cb0cd4a78670477"
|
||||
dependencies = [
|
||||
"fluent-bundle",
|
||||
"unic-langid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fluent-bundle"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "01203cb8918f5711e73891b347816d932046f95f54207710bda99beaeb423bf4"
|
||||
dependencies = [
|
||||
"fluent-langneg",
|
||||
"fluent-syntax",
|
||||
"intl-memoizer",
|
||||
"intl_pluralrules",
|
||||
"rustc-hash",
|
||||
"self_cell",
|
||||
"smallvec",
|
||||
"unic-langid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fluent-langneg"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7eebbe59450baee8282d71676f3bfed5689aeab00b27545e83e5f14b1195e8b0"
|
||||
dependencies = [
|
||||
"unic-langid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fluent-syntax"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54f0d287c53ffd184d04d8677f590f4ac5379785529e5e08b1c8083acdd5c198"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.64"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"log",
|
||||
"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 = "intl-memoizer"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "310da2e345f5eb861e7a07ee182262e94975051db9e4223e909ba90f392f163f"
|
||||
dependencies = [
|
||||
"type-map",
|
||||
"unic-langid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "intl_pluralrules"
|
||||
version = "7.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "078ea7b7c29a2b4df841a7f6ac8775ff6074020c6776d48491ce2268e068f972"
|
||||
dependencies = [
|
||||
"unic-langid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is_terminal_polyfill"
|
||||
version = "1.70.2"
|
||||
@@ -111,10 +329,148 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.178"
|
||||
name = "itoa"
|
||||
version = "1.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091"
|
||||
checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2"
|
||||
|
||||
[[package]]
|
||||
name = "jiff"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a87d9b8105c23642f50cbbae03d1f75d8422c5cb98ce7ee9271f7ff7505be6b8"
|
||||
dependencies = [
|
||||
"jiff-static",
|
||||
"jiff-tzdb-platform",
|
||||
"log",
|
||||
"portable-atomic",
|
||||
"portable-atomic-util",
|
||||
"serde_core",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jiff-static"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b787bebb543f8969132630c51fd0afab173a86c6abae56ff3b9e5e3e3f9f6e58"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jiff-tzdb"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68971ebff725b9e2ca27a601c5eb38a4c5d64422c4cbab0c535f248087eda5c2"
|
||||
|
||||
[[package]]
|
||||
name = "jiff-tzdb-platform"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8"
|
||||
dependencies = [
|
||||
"jiff-tzdb",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.179"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c5a2d376baa530d1238d133232d15e239abad80d05838b4b59354e5268af431f"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.30.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
"memoffset",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-conv"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_threads"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell_polyfill"
|
||||
@@ -122,6 +478,61 @@ version = "1.70.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
|
||||
|
||||
[[package]]
|
||||
name = "os_display"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad5fd71b79026fb918650dde6d125000a233764f1c2f1659a1c71118e33ea08f"
|
||||
dependencies = [
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf"
|
||||
dependencies = [
|
||||
"phf_shared",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266"
|
||||
dependencies = [
|
||||
"siphasher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
|
||||
|
||||
[[package]]
|
||||
name = "portable-atomic"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f89776e4d69bb58bc6993e99ffa1d11f228b839984854c7daeb5d37f87cbe950"
|
||||
|
||||
[[package]]
|
||||
name = "portable-atomic-util"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507"
|
||||
dependencies = [
|
||||
"portable-atomic",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "powerfmt"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.104"
|
||||
@@ -144,17 +555,101 @@ dependencies = [
|
||||
name = "roowho2"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"chrono",
|
||||
"clap",
|
||||
"sd-notify",
|
||||
"nix",
|
||||
"tokio",
|
||||
"uucore",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sd-notify"
|
||||
version = "0.4.5"
|
||||
name = "rustc-hash"
|
||||
version = "2.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b943eadf71d8b69e661330cb0e2656e31040acf21ee7708e2c238a0ec6af2bf4"
|
||||
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
||||
|
||||
[[package]]
|
||||
name = "self_cell"
|
||||
version = "1.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b12e76d157a900eb52e81bc6e9f3069344290341720e9178cde2407113ac8d89"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_core"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.15.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -165,33 +660,308 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.112"
|
||||
version = "2.0.113"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21f182278bf2d2bcb3c88b1b08a37df029d71ce3d3ae26168e3c653b213b99d4"
|
||||
checksum = "678faa00651c9eb72dd2020cbdf275d92eccb2400d568e419efdd64838145cb4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "terminal_size"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60b8cb979cb11c32ce1603f8137b22262a9d131aaa5c37b5678025f22b8becd0"
|
||||
dependencies = [
|
||||
"rustix",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "2.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "2.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d"
|
||||
dependencies = [
|
||||
"deranged",
|
||||
"itoa",
|
||||
"libc",
|
||||
"num-conv",
|
||||
"num_threads",
|
||||
"powerfmt",
|
||||
"serde",
|
||||
"time-core",
|
||||
"time-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-core"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b"
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3"
|
||||
dependencies = [
|
||||
"num-conv",
|
||||
"time-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinystr"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"serde_core",
|
||||
"zerovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.49.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"mio",
|
||||
"pin-project-lite",
|
||||
"socket2",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "type-map"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb30dbbd9036155e74adad6812e9898d03ec374946234fbcebd5dfc7b9187b90"
|
||||
dependencies = [
|
||||
"rustc-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unic-langid"
|
||||
version = "0.9.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a28ba52c9b05311f4f6e62d5d9d46f094bd6e84cb8df7b3ef952748d752a7d05"
|
||||
dependencies = [
|
||||
"unic-langid-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unic-langid-impl"
|
||||
version = "0.9.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dce1bf08044d4b7a94028c93786f8566047edc11110595914de93362559bc658"
|
||||
dependencies = [
|
||||
"tinystr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
|
||||
[[package]]
|
||||
name = "uucore"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5eddd390f3fdef74f104a948559e6de29203f60f8f563c8c9f528cd4c88ee78"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"dns-lookup",
|
||||
"fluent",
|
||||
"fluent-bundle",
|
||||
"fluent-syntax",
|
||||
"jiff",
|
||||
"libc",
|
||||
"nix",
|
||||
"os_display",
|
||||
"phf",
|
||||
"thiserror",
|
||||
"time",
|
||||
"unic-langid",
|
||||
"uucore_procs",
|
||||
"wild",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uucore_procs"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47148309a1f7a989d165dabbbc7f2bf156d7ff6affe7d69c1c5bfb822e663ae6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.1+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
"rustversion",
|
||||
"wasm-bindgen-macro",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wild"
|
||||
version = "2.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3131afc8c575281e1e80f36ed6a092aa502c08b18ed7524e86fbbb12bb410e1"
|
||||
dependencies = [
|
||||
"glob",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.62.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
|
||||
dependencies = [
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
"windows-link",
|
||||
"windows-result",
|
||||
"windows-strings",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.60.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.59.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.60.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.61.2"
|
||||
@@ -200,3 +970,84 @@ checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.53.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
|
||||
|
||||
[[package]]
|
||||
name = "zerofrom"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
|
||||
|
||||
[[package]]
|
||||
name = "zerovec"
|
||||
version = "0.11.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"zerofrom",
|
||||
]
|
||||
|
||||
10
Cargo.toml
10
Cargo.toml
@@ -14,8 +14,16 @@ autobins = false
|
||||
autolib = false
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.100"
|
||||
chrono = { version = "0.4.42", features = ["serde"] }
|
||||
clap = { version = "4.5.53", features = ["derive"] }
|
||||
sd-notify = "0.4.5"
|
||||
nix = { version = "0.30.1", features = ["hostname", "net"] }
|
||||
tokio = { version = "1.49.0", features = ["net", "rt-multi-thread"] }
|
||||
# onc-rpc = "0.3.2"
|
||||
# sd-notify = "0.4.5"
|
||||
# serde = { version = "1.0.228", features = ["derive"] }
|
||||
# serde_json = "1.0.148"
|
||||
uucore = { version = "0.5.0", features = ["utmpx"] }
|
||||
|
||||
[lib]
|
||||
name = "roowho2_lib"
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
fn main() {
|
||||
unimplemented!()
|
||||
println!(
|
||||
"{:#?}",
|
||||
roowho2_lib::server::rwhod::generate_rwhod_status_update(),
|
||||
);
|
||||
println!(
|
||||
"{:#?}",
|
||||
roowho2_lib::server::rwhod::determine_relevant_interfaces(),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
pub mod proto;
|
||||
pub mod server;
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
pub mod finger_protocol;
|
||||
pub mod rusers_protocol;
|
||||
pub mod rwhod_protocol;
|
||||
pub mod write_protocol;
|
||||
|
||||
pub use finger_protocol::*;
|
||||
pub use rusers_protocol::*;
|
||||
pub use rwhod_protocol::*;
|
||||
pub use write_protocol::*;
|
||||
|
||||
334
src/proto/rwhod_protocol.rs
Normal file
334
src/proto/rwhod_protocol.rs
Normal file
@@ -0,0 +1,334 @@
|
||||
use std::array;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[repr(C)]
|
||||
pub struct Outmp {
|
||||
/// tty name
|
||||
pub out_line: [u8; Self::MAX_TTY_NAME_LEN],
|
||||
/// user id
|
||||
pub out_name: [u8; Self::MAX_USER_ID_LEN],
|
||||
/// time on
|
||||
pub out_time: i32,
|
||||
}
|
||||
|
||||
impl Outmp {
|
||||
pub const MAX_TTY_NAME_LEN: usize = 8;
|
||||
pub const MAX_USER_ID_LEN: usize = 8;
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[repr(C)]
|
||||
pub struct Whoent {
|
||||
/// active tty info
|
||||
pub we_utmp: Outmp,
|
||||
/// tty idle time
|
||||
pub we_idle: i32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[repr(C)]
|
||||
pub struct Whod {
|
||||
/// protocol version
|
||||
pub wd_vers: u8,
|
||||
/// packet type, see below
|
||||
pub wd_type: u8,
|
||||
pub wd_pad: [u8; 2],
|
||||
/// time stamp by sender
|
||||
pub wd_sendtime: i32,
|
||||
/// time stamp applied by receiver
|
||||
pub wd_recvtime: i32,
|
||||
/// host's name
|
||||
pub wd_hostname: [u8; Self::MAX_HOSTNAME_LEN],
|
||||
/// load average as in uptime
|
||||
pub wd_loadav: [i32; 3],
|
||||
/// time system booted
|
||||
pub wd_boottime: i32,
|
||||
pub wd_we: [Whoent; Self::MAX_WHOENTRIES],
|
||||
}
|
||||
|
||||
impl Whod {
|
||||
pub const SIZE: usize = std::mem::size_of::<Whod>();
|
||||
pub const MAX_HOSTNAME_LEN: usize = 32;
|
||||
pub const MAX_WHOENTRIES: usize = 1024 / std::mem::size_of::<Whoent>();
|
||||
|
||||
pub const WHODVERSION: u8 = 1;
|
||||
|
||||
// NOTE: there was probably meant to be more packet types, but only status is defined.
|
||||
pub const WHODTYPE_STATUS: u8 = 1;
|
||||
|
||||
pub fn to_bytes(&self) -> [u8; std::mem::size_of::<Whod>()] {
|
||||
unsafe { std::mem::transmute_copy(self) }
|
||||
}
|
||||
|
||||
// TODO: we should probably make a safer parser.
|
||||
pub fn from_bytes(bytes: &[u8; std::mem::size_of::<Whod>()]) -> Self {
|
||||
unsafe { std::mem::transmute_copy(bytes) }
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct WhodStatusUpdate {
|
||||
// NOTE: there is only one defined packet type, so we just omit it here
|
||||
/// Timestamp by sender
|
||||
sendtime: chrono::DateTime<chrono::Utc>,
|
||||
|
||||
/// Timestamp applied by receiver
|
||||
recvtime: Option<chrono::DateTime<chrono::Utc>>,
|
||||
|
||||
/// Name of the host sending the status update (max 32 characters)
|
||||
hostname: String,
|
||||
|
||||
/// load average over 5 minutes multiplied by 100
|
||||
load_average_5_min: i32,
|
||||
/// load average over 10 minutes multiplied by 100
|
||||
load_average_10_min: i32,
|
||||
/// load average over 15 minutes multiplied by 100
|
||||
load_average_15_min: i32,
|
||||
|
||||
/// Which time the system was booted
|
||||
boot_time: chrono::DateTime<chrono::Utc>,
|
||||
|
||||
/// List of users currently logged in to the host (max 42 entries)
|
||||
users: Vec<WhodUserEntry>,
|
||||
}
|
||||
|
||||
impl WhodStatusUpdate {
|
||||
pub fn new(
|
||||
sendtime: chrono::DateTime<chrono::Utc>,
|
||||
recvtime: Option<chrono::DateTime<chrono::Utc>>,
|
||||
hostname: String,
|
||||
load_average_5_min: i32,
|
||||
load_average_10_min: i32,
|
||||
load_average_15_min: i32,
|
||||
boot_time: chrono::DateTime<chrono::Utc>,
|
||||
users: Vec<WhodUserEntry>,
|
||||
) -> Self {
|
||||
Self {
|
||||
sendtime,
|
||||
recvtime,
|
||||
hostname,
|
||||
load_average_5_min,
|
||||
load_average_10_min,
|
||||
load_average_15_min,
|
||||
boot_time,
|
||||
users,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct WhodUserEntry {
|
||||
/// TTY name (max 8 characters)
|
||||
tty: String,
|
||||
|
||||
/// User ID (max 8 characters)
|
||||
user_id: String,
|
||||
|
||||
/// Time when the user logged in
|
||||
login_time: chrono::DateTime<chrono::Utc>,
|
||||
|
||||
/// Idle time in seconds
|
||||
idle_time_seconds: i32,
|
||||
}
|
||||
|
||||
impl WhodUserEntry {
|
||||
pub fn new(
|
||||
tty: String,
|
||||
user_id: String,
|
||||
login_time: chrono::DateTime<chrono::Utc>,
|
||||
idle_time_seconds: i32,
|
||||
) -> Self {
|
||||
Self {
|
||||
tty,
|
||||
user_id,
|
||||
login_time,
|
||||
idle_time_seconds,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Whoent> for WhodUserEntry {
|
||||
type Error = String;
|
||||
|
||||
fn try_from(value: Whoent) -> Result<Self, Self::Error> {
|
||||
let tty_end = value
|
||||
.we_utmp
|
||||
.out_line
|
||||
.iter()
|
||||
.position(|&c| c == 0)
|
||||
.unwrap_or(value.we_utmp.out_line.len());
|
||||
let tty = String::from_utf8(value.we_utmp.out_line[..tty_end].to_vec())
|
||||
.map_err(|e| format!("Invalid UTF-8 in TTY name: {}", e))?;
|
||||
|
||||
let user_id_end = value
|
||||
.we_utmp
|
||||
.out_name
|
||||
.iter()
|
||||
.position(|&c| c == 0)
|
||||
.unwrap_or(value.we_utmp.out_name.len());
|
||||
let user_id = String::from_utf8(value.we_utmp.out_name[..user_id_end].to_vec())
|
||||
.map_err(|e| format!("Invalid UTF-8 in user ID: {}", e))?;
|
||||
|
||||
let login_time = chrono::DateTime::from_timestamp_secs(value.we_utmp.out_time as i64)
|
||||
.ok_or(format!(
|
||||
"Invalid login time timestamp: {}",
|
||||
value.we_utmp.out_time
|
||||
))?;
|
||||
|
||||
Ok(WhodUserEntry {
|
||||
tty,
|
||||
user_id,
|
||||
login_time,
|
||||
idle_time_seconds: value.we_idle,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Whod> for WhodStatusUpdate {
|
||||
type Error = String;
|
||||
|
||||
fn try_from(value: Whod) -> Result<Self, Self::Error> {
|
||||
if value.wd_vers != Whod::WHODVERSION {
|
||||
return Err(format!(
|
||||
"Unsupported whod protocol version: {}",
|
||||
value.wd_vers
|
||||
));
|
||||
}
|
||||
|
||||
let sendtime = chrono::DateTime::from_timestamp_secs(value.wd_sendtime as i64).ok_or(
|
||||
format!("Invalid send time timestamp: {}", value.wd_sendtime),
|
||||
)?;
|
||||
|
||||
let recvtime = if value.wd_recvtime == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(
|
||||
chrono::DateTime::from_timestamp_secs(value.wd_recvtime as i64).ok_or(format!(
|
||||
"Invalid receive time timestamp: {}",
|
||||
value.wd_recvtime
|
||||
))?,
|
||||
)
|
||||
};
|
||||
|
||||
let hostname_end = value
|
||||
.wd_hostname
|
||||
.iter()
|
||||
.position(|&c| c == 0)
|
||||
.unwrap_or(value.wd_hostname.len());
|
||||
let hostname = String::from_utf8(value.wd_hostname[..hostname_end].to_vec())
|
||||
.map_err(|e| format!("Invalid UTF-8 in hostname: {}", e))?;
|
||||
|
||||
let boot_time = chrono::DateTime::from_timestamp_secs(value.wd_boottime as i64).ok_or(
|
||||
format!("Invalid boot time timestamp: {}", value.wd_boottime),
|
||||
)?;
|
||||
|
||||
let mut users = Vec::new();
|
||||
for whoent in &value.wd_we {
|
||||
let user_entry = WhodUserEntry::try_from(whoent.clone())?;
|
||||
users.push(user_entry);
|
||||
}
|
||||
|
||||
Ok(WhodStatusUpdate {
|
||||
sendtime,
|
||||
recvtime,
|
||||
hostname,
|
||||
load_average_5_min: value.wd_loadav[0],
|
||||
load_average_10_min: value.wd_loadav[1],
|
||||
load_average_15_min: value.wd_loadav[2],
|
||||
boot_time,
|
||||
users,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: support less strict conversions with truncation
|
||||
|
||||
impl TryFrom<WhodUserEntry> for Whoent {
|
||||
type Error = String;
|
||||
|
||||
fn try_from(value: WhodUserEntry) -> Result<Self, Self::Error> {
|
||||
let mut out_line = [0u8; 8];
|
||||
let tty_bytes = value.tty.as_bytes();
|
||||
if tty_bytes.len() > out_line.len() {
|
||||
return Err(format!(
|
||||
"TTY name too long: {} (max {})",
|
||||
value.tty,
|
||||
out_line.len()
|
||||
));
|
||||
}
|
||||
out_line[..tty_bytes.len()].copy_from_slice(tty_bytes);
|
||||
|
||||
let mut out_name = [0u8; 8];
|
||||
let user_id_bytes = value.user_id.as_bytes();
|
||||
if user_id_bytes.len() > out_name.len() {
|
||||
return Err(format!(
|
||||
"User ID too long: {} (max {})",
|
||||
value.user_id,
|
||||
out_name.len()
|
||||
));
|
||||
}
|
||||
out_name[..user_id_bytes.len()].copy_from_slice(user_id_bytes);
|
||||
|
||||
Ok(Whoent {
|
||||
we_utmp: Outmp {
|
||||
out_line,
|
||||
out_name,
|
||||
out_time: value.login_time.timestamp() as i32,
|
||||
},
|
||||
we_idle: value.idle_time_seconds,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: support less strict conversions with truncation
|
||||
|
||||
impl TryFrom<WhodStatusUpdate> for Whod {
|
||||
type Error = String;
|
||||
|
||||
fn try_from(value: WhodStatusUpdate) -> Result<Self, Self::Error> {
|
||||
let mut wd_hostname = [0u8; Whod::MAX_HOSTNAME_LEN];
|
||||
let hostname_bytes = value.hostname.as_bytes();
|
||||
if hostname_bytes.len() > wd_hostname.len() {
|
||||
return Err(format!(
|
||||
"Hostname too long: {} (max {})",
|
||||
value.hostname,
|
||||
wd_hostname.len()
|
||||
));
|
||||
}
|
||||
wd_hostname[..hostname_bytes.len()].copy_from_slice(hostname_bytes);
|
||||
|
||||
let mut wd_we = array::from_fn(|_| Whoent {
|
||||
we_utmp: Outmp {
|
||||
out_line: [0u8; Outmp::MAX_TTY_NAME_LEN],
|
||||
out_name: [0u8; Outmp::MAX_USER_ID_LEN],
|
||||
out_time: 0,
|
||||
},
|
||||
we_idle: 0,
|
||||
});
|
||||
|
||||
for (i, user_entry) in value.users.into_iter().enumerate() {
|
||||
if i >= Whod::MAX_WHOENTRIES {
|
||||
break;
|
||||
}
|
||||
wd_we[i] = Whoent::try_from(user_entry)?;
|
||||
}
|
||||
|
||||
Ok(Whod {
|
||||
wd_vers: Whod::WHODVERSION,
|
||||
wd_type: Whod::WHODTYPE_STATUS,
|
||||
wd_pad: [0u8; 2],
|
||||
wd_sendtime: value.sendtime.timestamp() as i32,
|
||||
wd_recvtime: value.recvtime.map_or(0, |dt| dt.timestamp() as i32),
|
||||
wd_hostname,
|
||||
wd_loadav: [
|
||||
value.load_average_5_min,
|
||||
value.load_average_10_min,
|
||||
value.load_average_15_min,
|
||||
],
|
||||
wd_boottime: value.boot_time.timestamp() as i32,
|
||||
wd_we,
|
||||
})
|
||||
}
|
||||
}
|
||||
1
src/server.rs
Normal file
1
src/server.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub mod rwhod;
|
||||
138
src/server/rwhod.rs
Normal file
138
src/server/rwhod.rs
Normal file
@@ -0,0 +1,138 @@
|
||||
use std::{collections::HashSet, net::IpAddr, path::Path};
|
||||
|
||||
use nix::{ifaddrs::getifaddrs, net::if_::InterfaceFlags, sys::stat::stat};
|
||||
use uucore::utmpx::Utmpx;
|
||||
|
||||
use crate::proto::{Whod, WhodStatusUpdate, WhodUserEntry};
|
||||
|
||||
/// Reads utmp entries to determine currently logged-in users.
|
||||
pub fn generate_rwhod_user_entries() -> anyhow::Result<Vec<WhodUserEntry>> {
|
||||
Utmpx::iter_all_records()
|
||||
.filter(|entry| entry.is_user_process())
|
||||
.map(|entry| {
|
||||
let login_time = entry
|
||||
.login_time()
|
||||
.checked_to_utc()
|
||||
.and_then(|t| {
|
||||
chrono::DateTime::<chrono::Utc>::from_timestamp_secs(t.unix_timestamp())
|
||||
})
|
||||
.ok_or_else(|| anyhow::anyhow!("Failed to convert login time to UTC"))?;
|
||||
|
||||
let idle_time = stat(&Path::new("/dev").join(entry.tty_device()))
|
||||
.map(|st| (chrono::Utc::now().timestamp() - st.st_atime) as i32)
|
||||
.unwrap_or(0);
|
||||
|
||||
Ok(WhodUserEntry::new(
|
||||
entry.tty_device(),
|
||||
entry.user(),
|
||||
login_time,
|
||||
idle_time,
|
||||
))
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Generate a rwhod status update packet representing the current system state.
|
||||
pub fn generate_rwhod_status_update() -> anyhow::Result<Whod> {
|
||||
let sysinfo = nix::sys::sysinfo::sysinfo().unwrap();
|
||||
let load_average = sysinfo.load_average();
|
||||
let uptime = sysinfo.uptime();
|
||||
let hostname = nix::unistd::gethostname()?.to_str().unwrap().to_string();
|
||||
|
||||
let result = WhodStatusUpdate::new(
|
||||
chrono::Utc::now(),
|
||||
None,
|
||||
hostname,
|
||||
(load_average.0 * 100.0).abs() as i32,
|
||||
(load_average.1 * 100.0).abs() as i32,
|
||||
(load_average.2 * 100.0).abs() as i32,
|
||||
chrono::Utc::now() - uptime,
|
||||
generate_rwhod_user_entries()?,
|
||||
)
|
||||
.try_into()
|
||||
.map_err(|e| anyhow::anyhow!("{}", e))?;
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RwhodSendTarget {
|
||||
/// Name of the network interface.
|
||||
pub name: String,
|
||||
|
||||
/// Address to send rwhod packets to.
|
||||
/// This is either the broadcast address (for broadcast interfaces)
|
||||
/// or the point-to-point destination address (for point-to-point interfaces).
|
||||
pub addr: IpAddr,
|
||||
}
|
||||
|
||||
/// Find all networks network interfaces suitable for rwhod communication.
|
||||
pub fn determine_relevant_interfaces() -> anyhow::Result<Vec<RwhodSendTarget>> {
|
||||
getifaddrs().map_err(|e| e.into()).map(|ifaces| {
|
||||
ifaces
|
||||
// interface must be up
|
||||
.filter(|iface| iface.flags.contains(InterfaceFlags::IFF_UP))
|
||||
// interface must be broadcast or point-to-point
|
||||
.filter(|iface| {
|
||||
iface
|
||||
.flags
|
||||
.intersects(InterfaceFlags::IFF_BROADCAST | InterfaceFlags::IFF_POINTOPOINT)
|
||||
})
|
||||
.filter_map(|iface| {
|
||||
let neighbor_addr = if iface.flags.contains(InterfaceFlags::IFF_BROADCAST) {
|
||||
iface.broadcast
|
||||
} else if iface.flags.contains(InterfaceFlags::IFF_POINTOPOINT) {
|
||||
iface.destination
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
match neighbor_addr {
|
||||
Some(addr) => addr
|
||||
.as_sockaddr_in()
|
||||
.map(|sa| IpAddr::V4(sa.ip().into()))
|
||||
.or_else(|| addr.as_sockaddr_in6().map(|sa| IpAddr::V6(sa.ip().into())))
|
||||
.map(|ip_addr| RwhodSendTarget {
|
||||
name: iface.interface_name,
|
||||
addr: ip_addr,
|
||||
}),
|
||||
None => None,
|
||||
}
|
||||
})
|
||||
/* keep first occurrence per interface name */
|
||||
.scan(HashSet::new(), |seen, n| {
|
||||
if seen.insert(n.name.clone()) {
|
||||
Some(n)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<RwhodSendTarget>>()
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn send_rwhod_packet_to_interface(
|
||||
socket: &mut tokio::net::UdpSocket,
|
||||
interface: &RwhodSendTarget,
|
||||
packet: &Whod,
|
||||
) -> anyhow::Result<()> {
|
||||
let serialized_packet = packet.to_bytes();
|
||||
|
||||
let target_addr = match interface.addr {
|
||||
IpAddr::V4(addr) => std::net::SocketAddr::new(IpAddr::V4(addr), 0),
|
||||
IpAddr::V6(addr) => std::net::SocketAddr::new(IpAddr::V6(addr), 0),
|
||||
};
|
||||
|
||||
socket
|
||||
.send_to(&serialized_packet, &target_addr)
|
||||
.await
|
||||
.map_err(|e| anyhow::anyhow!("Failed to send rwhod packet: {}", e))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// TODO: implement receiving rwhod packets from other hosts
|
||||
|
||||
// TODO: implement storing and loading rwhod packets to/from file
|
||||
|
||||
// TODO: implement protocol for cli - daemon communication
|
||||
Reference in New Issue
Block a user