Răsfoiți Sursa

an early version.

ZRY 11 luni în urmă
părinte
comite
23ee3ad68f
21 a modificat fișierele cu 2121 adăugiri și 26 ștergeri
  1. 5 0
      .cargo/config.toml
  2. 1 26
      .gitignore
  3. 8 0
      .idea/.gitignore
  4. 8 0
      .idea/modules.xml
  5. 6 0
      .idea/vcs.xml
  6. 12 0
      .idea/yukari.iml
  7. 1376 0
      Cargo.lock
  8. 18 0
      Cargo.toml
  9. 14 0
      src/cfg/boot.rs
  10. 38 0
      src/cfg/etc.rs
  11. 125 0
      src/cfg/mod.rs
  12. 111 0
      src/logger/mod.rs
  13. 96 0
      src/main.rs
  14. 73 0
      src/reaper/mod.rs
  15. 40 0
      src/shell/mgrsh.rs
  16. 100 0
      src/shell/mod.rs
  17. 2 0
      src/syscall/mod.rs
  18. 33 0
      src/syscall/power.rs
  19. 27 0
      src/syscall/proc.rs
  20. 24 0
      src/sysinit/mod.rs
  21. 4 0
      src/tty/mod.rs

+ 5 - 0
.cargo/config.toml

@@ -0,0 +1,5 @@
+[build]
+target = "armv7-unknown-linux-musleabihf"
+
+[target.armv7-unknown-linux-musleabihf]
+linker = "armv7l-linux-musleabihf-ld"

+ 1 - 26
.gitignore

@@ -1,26 +1 @@
-# ---> Go
-# Compiled Object files, Static and Dynamic libs (Shared Objects)
-*.o
-*.a
-*.so
-
-# Folders
-_obj
-_test
-
-# Architecture specific extensions/prefixes
-*.[568vq]
-[568vq].out
-
-*.cgo1.go
-*.cgo2.c
-_cgo_defun.c
-_cgo_gotypes.go
-_cgo_export.*
-
-_testmain.go
-
-*.exe
-*.test
-*.prof
-
+/target

+ 8 - 0
.idea/.gitignore

@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml

+ 8 - 0
.idea/modules.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/yukari.iml" filepath="$PROJECT_DIR$/.idea/yukari.iml" />
+    </modules>
+  </component>
+</project>

+ 6 - 0
.idea/vcs.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="" vcs="Git" />
+  </component>
+</project>

+ 12 - 0
.idea/yukari.iml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="WEB_MODULE" version="4">
+  <component name="Go" enabled="true" />
+  <component name="NewModuleRootManager">
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+      <excludeFolder url="file://$MODULE_DIR$/target" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>

+ 1376 - 0
Cargo.lock

@@ -0,0 +1,1376 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "ahash"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
+dependencies = [
+ "getrandom",
+ "once_cell",
+ "version_check",
+]
+
+[[package]]
+name = "aho-corasick"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.71"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
+
+[[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"
+checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270"
+
+[[package]]
+name = "base64"
+version = "0.21.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d"
+
+[[package]]
+name = "bcrypt"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9df288bec72232f78c1ec5fe4e8f1d108aa0265476e93097593c803c8c02062a"
+dependencies = [
+ "base64",
+ "blowfish",
+ "getrandom",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "blowfish"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7"
+dependencies = [
+ "byteorder",
+ "cipher",
+]
+
+[[package]]
+name = "bumpalo"
+version = "3.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
+
+[[package]]
+name = "byteorder"
+version = "1.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+
+[[package]]
+name = "bytes"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
+
+[[package]]
+name = "cc"
+version = "1.0.79"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "cipher"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
+dependencies = [
+ "crypto-common",
+ "inout",
+]
+
+[[package]]
+name = "clipboard-win"
+version = "4.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7191c27c2357d9b7ef96baac1773290d4ca63b24205b82a3fd8a0637afcf0362"
+dependencies = [
+ "error-code",
+ "str-buf",
+ "winapi",
+]
+
+[[package]]
+name = "common_macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3f6d59c71e7dc3af60f0af9db32364d96a16e9310f3f5db2b55ed642162dd35"
+
+[[package]]
+name = "const_fn"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fbdcdcb6d86f71c5e97409ad45898af11cbc995b4ee8112d59095a28d376c935"
+
+[[package]]
+name = "crossbeam-channel"
+version = "0.5.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
+dependencies = [
+ "cfg-if",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-deque"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
+dependencies = [
+ "cfg-if",
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695"
+dependencies = [
+ "autocfg",
+ "cfg-if",
+ "crossbeam-utils",
+ "memoffset 0.8.0",
+ "scopeguard",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "crypto-common"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
+dependencies = [
+ "generic-array",
+ "typenum",
+]
+
+[[package]]
+name = "dirs-next"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
+dependencies = [
+ "cfg-if",
+ "dirs-sys-next",
+]
+
+[[package]]
+name = "dirs-sys-next"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
+dependencies = [
+ "libc",
+ "redox_users",
+ "winapi",
+]
+
+[[package]]
+name = "discard"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
+
+[[package]]
+name = "easy-repl"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81d0001ed25c451c57f8d6724d448a6546a5d78bbac77a63a22e32c735b7ea16"
+dependencies = [
+ "anyhow",
+ "rustyline",
+ "rustyline-derive",
+ "shell-words",
+ "textwrap",
+ "thiserror",
+ "trie-rs",
+]
+
+[[package]]
+name = "either"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
+
+[[package]]
+name = "endian-type"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d"
+
+[[package]]
+name = "errno"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
+dependencies = [
+ "errno-dragonfly",
+ "libc",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "errno-dragonfly"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
+dependencies = [
+ "cc",
+ "libc",
+]
+
+[[package]]
+name = "error-code"
+version = "2.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64f18991e7bf11e7ffee451b5318b5c1a73c52d0d0ada6e5a3017c8c1ced6a21"
+dependencies = [
+ "libc",
+ "str-buf",
+]
+
+[[package]]
+name = "fd-lock"
+version = "3.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "39ae6b3d9530211fb3b12a95374b8b0823be812f53d09e18c5675c0146b09642"
+dependencies = [
+ "cfg-if",
+ "rustix",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "fid-rs"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c28658c0c3420305705adde833a0d2d614207507d013a5f25707553fb2ae2cd"
+dependencies = [
+ "rayon",
+]
+
+[[package]]
+name = "generic-array"
+version = "0.14.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
+dependencies = [
+ "typenum",
+ "version_check",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
+dependencies = [
+ "ahash",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
+
+[[package]]
+name = "indexmap"
+version = "1.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
+dependencies = [
+ "autocfg",
+ "hashbrown",
+]
+
+[[package]]
+name = "inout"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
+dependencies = [
+ "generic-array",
+]
+
+[[package]]
+name = "io-lifetimes"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
+dependencies = [
+ "hermit-abi 0.3.1",
+ "libc",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "libc"
+version = "0.2.144"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
+
+[[package]]
+name = "lock_api"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
+dependencies = [
+ "autocfg",
+ "scopeguard",
+]
+
+[[package]]
+name = "log"
+version = "0.4.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "louds-rs"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e16a91fb20f74b6d9a758a0103a2884af525a2fa34fbfe19f4b3c5482a4a54e9"
+dependencies = [
+ "fid-rs",
+]
+
+[[package]]
+name = "memchr"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
+
+[[package]]
+name = "memoffset"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "memoffset"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "memoffset"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "mio"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9"
+dependencies = [
+ "libc",
+ "log",
+ "wasi",
+ "windows-sys 0.45.0",
+]
+
+[[package]]
+name = "nibble_vec"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43"
+dependencies = [
+ "smallvec",
+]
+
+[[package]]
+name = "nix"
+version = "0.23.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c"
+dependencies = [
+ "bitflags",
+ "cc",
+ "cfg-if",
+ "libc",
+ "memoffset 0.6.5",
+]
+
+[[package]]
+name = "nix"
+version = "0.26.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a"
+dependencies = [
+ "bitflags",
+ "cfg-if",
+ "libc",
+ "memoffset 0.7.1",
+ "pin-utils",
+ "static_assertions",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
+dependencies = [
+ "hermit-abi 0.2.6",
+ "libc",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.17.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
+
+[[package]]
+name = "parking_lot"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
+dependencies = [
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.9.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "windows-sys 0.45.0",
+]
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
+
+[[package]]
+name = "pin-utils"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+
+[[package]]
+name = "pkg_compile_time"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8970e7dfe13374320bfa3b2acc21e0c0f0e01ad7e8c140dd4882e21c7caf993"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "time",
+]
+
+[[package]]
+name = "proc-macro-hack"
+version = "0.5.20+deprecated"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.58"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa1fb82fc0c281dd9671101b66b771ebbe1eaf967b96ac8740dcba4b70005ca8"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "radix_trie"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd"
+dependencies = [
+ "endian-type",
+ "nibble_vec",
+]
+
+[[package]]
+name = "rayon"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
+dependencies = [
+ "either",
+ "rayon-core",
+]
+
+[[package]]
+name = "rayon-core"
+version = "1.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
+dependencies = [
+ "crossbeam-channel",
+ "crossbeam-deque",
+ "crossbeam-utils",
+ "num_cpus",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "redox_users"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
+dependencies = [
+ "getrandom",
+ "redox_syscall",
+ "thiserror",
+]
+
+[[package]]
+name = "regex"
+version = "1.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d1a59b5d8e97dee33696bf13c5ba8ab85341c002922fba050069326b9c498974"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
+
+[[package]]
+name = "rustc_version"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
+dependencies = [
+ "semver",
+]
+
+[[package]]
+name = "rustix"
+version = "0.37.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d"
+dependencies = [
+ "bitflags",
+ "errno",
+ "io-lifetimes",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "rustyline"
+version = "9.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db7826789c0e25614b03e5a54a0717a86f9ff6e6e5247f92b369472869320039"
+dependencies = [
+ "bitflags",
+ "cfg-if",
+ "clipboard-win",
+ "dirs-next",
+ "fd-lock",
+ "libc",
+ "log",
+ "memchr",
+ "nix 0.23.2",
+ "radix_trie",
+ "scopeguard",
+ "smallvec",
+ "unicode-segmentation",
+ "unicode-width",
+ "utf8parse",
+ "winapi",
+]
+
+[[package]]
+name = "rustyline-derive"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb35a55ab810b5c0fe31606fe9b47d1354e4dc519bec0a102655f78ea2b38057"
+dependencies = [
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "ryu"
+version = "1.0.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
+
+[[package]]
+name = "scopeguard"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+
+[[package]]
+name = "semver"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
+dependencies = [
+ "semver-parser",
+]
+
+[[package]]
+name = "semver-parser"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
+
+[[package]]
+name = "serde"
+version = "1.0.163"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.163"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.16",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.96"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "serde_spanned"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93107647184f6027e3b7dcb2e11034cf95ffa1e3a682c67951963ac69c1c007d"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "sha1"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770"
+dependencies = [
+ "sha1_smol",
+]
+
+[[package]]
+name = "sha1_smol"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012"
+
+[[package]]
+name = "shell-words"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde"
+
+[[package]]
+name = "signal-hook-registry"
+version = "1.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "simple-rw-global"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d7dcb8c9e89265f47231a034abfe881421993530f338d13fafa9be9e5a319026"
+dependencies = [
+ "tokio",
+]
+
+[[package]]
+name = "smallvec"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
+
+[[package]]
+name = "smawk"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f67ad224767faa3c7d8b6d91985b78e70a1324408abcb1cfcc2be4c06bc06043"
+
+[[package]]
+name = "socket2"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662"
+dependencies = [
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "standback"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e113fb6f3de07a243d434a56ec6f186dfd51cb08448239fe7bcae73f87ff28ff"
+dependencies = [
+ "version_check",
+]
+
+[[package]]
+name = "static_assertions"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
+[[package]]
+name = "stdweb"
+version = "0.4.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5"
+dependencies = [
+ "discard",
+ "rustc_version",
+ "stdweb-derive",
+ "stdweb-internal-macros",
+ "stdweb-internal-runtime",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "stdweb-derive"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "serde",
+ "serde_derive",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "stdweb-internal-macros"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11"
+dependencies = [
+ "base-x",
+ "proc-macro2",
+ "quote",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "sha1",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "stdweb-internal-runtime"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0"
+
+[[package]]
+name = "str-buf"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0"
+
+[[package]]
+name = "subtle"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
+
+[[package]]
+name = "syn"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "textwrap"
+version = "0.15.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7b3e525a49ec206798b40326a44121291b530c963cfb01018f63e135bac543d"
+dependencies = [
+ "smawk",
+ "unicode-linebreak",
+ "unicode-width",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.16",
+]
+
+[[package]]
+name = "time"
+version = "0.2.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4752a97f8eebd6854ff91f1c1824cd6160626ac4bd44287f7f4ea2035a02a242"
+dependencies = [
+ "const_fn",
+ "libc",
+ "standback",
+ "stdweb",
+ "time-macros",
+ "version_check",
+ "winapi",
+]
+
+[[package]]
+name = "time-macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1"
+dependencies = [
+ "proc-macro-hack",
+ "time-macros-impl",
+]
+
+[[package]]
+name = "time-macros-impl"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f"
+dependencies = [
+ "proc-macro-hack",
+ "proc-macro2",
+ "quote",
+ "standback",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "tokio"
+version = "1.28.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0aa32867d44e6f2ce3385e89dceb990188b8bb0fb25b0cf576647a6f98ac5105"
+dependencies = [
+ "autocfg",
+ "bytes",
+ "libc",
+ "mio",
+ "num_cpus",
+ "parking_lot",
+ "pin-project-lite",
+ "signal-hook-registry",
+ "socket2",
+ "tokio-macros",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "tokio-macros"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.16",
+]
+
+[[package]]
+name = "toml"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d6135d499e69981f9ff0ef2167955a5333c35e36f6937d382974566b3d5b94ec"
+dependencies = [
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "toml_edit",
+]
+
+[[package]]
+name = "toml_datetime"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a76a9312f5ba4c2dec6b9161fdf25d87ad8a09256ccea5a556fef03c706a10f"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "toml_edit"
+version = "0.19.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2380d56e8670370eee6566b0bfd4265f65b3f432e8c6d85623f728d4fa31f739"
+dependencies = [
+ "indexmap",
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "winnow",
+]
+
+[[package]]
+name = "trie-rs"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5096c019d49566aff57593a06e401c7f588da84e9a575d0ed2ac0913f51928c0"
+dependencies = [
+ "louds-rs",
+]
+
+[[package]]
+name = "typenum"
+version = "1.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0"
+
+[[package]]
+name = "unicode-linebreak"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c5faade31a542b8b35855fff6e8def199853b2da8da256da52f52f1316ee3137"
+dependencies = [
+ "hashbrown",
+ "regex",
+]
+
+[[package]]
+name = "unicode-segmentation"
+version = "1.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
+
+[[package]]
+name = "unicode-width"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
+
+[[package]]
+name = "utf8parse"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
+
+[[package]]
+name = "version_check"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.86"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73"
+dependencies = [
+ "cfg-if",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.86"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb"
+dependencies = [
+ "bumpalo",
+ "log",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.16",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.86"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.86"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.16",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.86"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+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-sys"
+version = "0.45.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
+dependencies = [
+ "windows-targets 0.42.2",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+dependencies = [
+ "windows-targets 0.48.0",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
+dependencies = [
+ "windows_aarch64_gnullvm 0.42.2",
+ "windows_aarch64_msvc 0.42.2",
+ "windows_i686_gnu 0.42.2",
+ "windows_i686_msvc 0.42.2",
+ "windows_x86_64_gnu 0.42.2",
+ "windows_x86_64_gnullvm 0.42.2",
+ "windows_x86_64_msvc 0.42.2",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
+dependencies = [
+ "windows_aarch64_gnullvm 0.48.0",
+ "windows_aarch64_msvc 0.48.0",
+ "windows_i686_gnu 0.48.0",
+ "windows_i686_msvc 0.48.0",
+ "windows_x86_64_gnu 0.48.0",
+ "windows_x86_64_gnullvm 0.48.0",
+ "windows_x86_64_msvc 0.48.0",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
+
+[[package]]
+name = "winnow"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61de7bac303dc551fe038e2b3cef0f571087a47571ea6e79a87692ac99b99699"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "yukari"
+version = "0.1.0"
+dependencies = [
+ "bcrypt",
+ "common_macros",
+ "easy-repl",
+ "lazy_static",
+ "nix 0.26.2",
+ "pkg_compile_time",
+ "serde",
+ "simple-rw-global",
+ "tokio",
+ "toml",
+]
+
+[[package]]
+name = "zeroize"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9"

+ 18 - 0
Cargo.toml

@@ -0,0 +1,18 @@
+[package]
+name = "yukari"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+nix = "0.26.2"
+easy-repl = "0.2.1"
+tokio = { version = "1.28.1", features = ["full"] }
+lazy_static = "1.4.0"
+simple-rw-global = { version="0.4.0", features=["tokio"] }
+toml = "0.7.4"
+serde = { version = "1.0", features = ["derive"] }
+common_macros = "0.1.1"
+bcrypt = "0.14.0"
+pkg_compile_time = "0.1.3"

+ 14 - 0
src/cfg/boot.rs

@@ -0,0 +1,14 @@
+use serde::Deserialize;
+
+#[derive(Deserialize, Clone)]
+pub struct BootConfigDef{
+    pub hostname: String,
+}
+
+impl BootConfigDef {
+    pub fn default() -> BootConfigDef {
+        BootConfigDef{
+            hostname: "ELIP4NG-Default-Hostname".to_string(),
+        }
+    }
+}

+ 38 - 0
src/cfg/etc.rs

@@ -0,0 +1,38 @@
+use std::collections::HashMap;
+use serde::Deserialize;
+use common_macros::hash_map;
+use crate::cfg::boot::BootConfigDef;
+
+#[derive(Deserialize, Clone)]
+pub struct EtcConfigDef{
+    pub sys: SysCfg,
+    pub boot_default: BootConfigDef,
+    pub secure: SecureCfg,
+}
+
+impl EtcConfigDef {
+    pub fn default() -> EtcConfigDef {
+        EtcConfigDef{
+            boot_default: BootConfigDef::default(),
+            secure: SecureCfg{
+                bcrypt_password: "$2a$10$9Nk9um4osOsdDPw.NjgBx.0qbQ/5H/qLXplaNjBeKKj6N13.PE3YK".to_string(),
+            }
+        }
+    }
+
+    pub fn get_boot_default_clone(&self) -> BootConfigDef{
+        self.boot_default.clone()
+    }
+}
+
+#[derive(Deserialize, Clone)]
+pub struct SecureCfg {
+    pub bcrypt_password: String,
+}
+
+#[derive(Deserialize, Clone)]
+pub struct SysCfg {
+    pub admin_shell: String,
+    pub sys_loader: String,
+    pub service_mgr: String,
+}

+ 125 - 0
src/cfg/mod.rs

@@ -0,0 +1,125 @@
+mod etc;
+mod boot;
+
+use std::fmt::{Debug, Display, Formatter};
+use std::fs::File;
+use std::io::{Read};
+use std::path::Path;
+use lazy_static::lazy_static;
+use serde::de::DeserializeOwned;
+use simple_rw_global::tokio::AsyncGlobalContainer;
+use crate::cfg::boot::BootConfigDef;
+use crate::cfg::etc::EtcConfigDef;
+
+const INIT_ETC_CFG_FILENAME:&str = "/etc/init.toml";
+const INIT_BOOT_CFG_FILENAME:&str = "/boot/config/init.toml";
+
+lazy_static! {
+    pub static ref CFG : AsyncGlobalContainer<ConfigManager> = AsyncGlobalContainer::new();
+}
+
+pub struct ConfigManager {
+    boot_cfg: BootConfigDef,
+    etc_cfg: EtcConfigDef,
+}
+
+impl ConfigManager {
+    pub fn empty() -> ConfigManager{
+        let etc_cfg = EtcConfigDef::default();
+        let boot_cfg = etc_cfg.get_boot_default_clone();
+        ConfigManager{ etc_cfg, boot_cfg }
+    }
+
+    pub fn load() -> ConfigManager{
+        println!("Loading config from '{}'...", INIT_ETC_CFG_FILENAME);
+        let etc_res = ConfigManager::load_file::<EtcConfigDef>(INIT_ETC_CFG_FILENAME);
+        let etc_cfg = match etc_res {
+            Ok(s) => {s}
+            Err(err) => {
+                ConfigManager::print_cfg_fail_info(INIT_ETC_CFG_FILENAME, err);
+                EtcConfigDef::default()
+            }
+        };
+        println!("Loading config from '{}'...", INIT_BOOT_CFG_FILENAME);
+        let boot_res = ConfigManager::load_file::<BootConfigDef>(INIT_BOOT_CFG_FILENAME);
+        let boot_cfg = match boot_res {
+            Ok(s) => {s}
+            Err(err) => {
+                ConfigManager::print_cfg_fail_info(INIT_BOOT_CFG_FILENAME, err);
+                etc_cfg.get_boot_default_clone()
+            }
+        };
+        ConfigManager{etc_cfg, boot_cfg}
+    }
+
+    fn load_file<T>(fname: &str) -> Result<T, CfgError>
+        where T: DeserializeOwned,
+    {
+        let fpath = Path::new(fname);
+        let mut file = File::open(fpath)?;
+        let mut toml_str = String::new();
+        file.read_to_string(&mut toml_str)?;
+        let etc = toml::from_str(&toml_str)?;
+        Ok(etc)
+    }
+
+    fn print_cfg_fail_info(cfgname: &str, err: CfgError) {
+        println!("[ERROR] config '{}' load failed: {:?}", cfgname, err);
+        println!("Use default setting instead, but some functions may not be available.");
+        println!("If you are a user:\n\tPlease contact the device manufacturer for help.");
+        println!("If you are the manufacturer:\n\tPlease use maintenance shell looking for detail.");
+    }
+
+    pub fn get_etc_cfg(&self) -> &EtcConfigDef {
+        &self.etc_cfg
+    }
+
+    pub fn get_boot_cfg(&self) -> &BootConfigDef {
+        &self.boot_cfg
+    }
+}
+
+pub async fn init_config_manager() {
+    let cm = ConfigManager::load();
+    //let cm = ConfigManager::empty();
+    CFG.set(cm).await;
+}
+
+pub enum CfgError{
+    IOError(std::io::Error),
+    DeserializeError(toml::de::Error),
+}
+
+impl Debug for CfgError {
+    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+        match self {
+            CfgError::IOError(e) => {
+                write!(f, "IOError: {:?}", e)
+            }
+            CfgError::DeserializeError(e) => {
+                write!(f, "DeserializeError: {:?}", e)
+            }
+        }
+    }
+}
+
+impl Display for CfgError {
+    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+        (self as &dyn Debug).fmt(f)
+    }
+}
+
+impl std::error::Error for CfgError {
+}
+
+impl From<std::io::Error> for CfgError {
+    fn from(value: std::io::Error) -> Self {
+        CfgError::IOError(value)
+    }
+}
+
+impl From<toml::de::Error> for CfgError {
+    fn from(value: toml::de::Error) -> Self {
+        CfgError::DeserializeError(value)
+    }
+}

+ 111 - 0
src/logger/mod.rs

@@ -0,0 +1,111 @@
+use std::fmt::{Display, Formatter};
+use tokio::io::{AsyncWriteExt, Stderr};
+use tokio::sync::mpsc::{channel, Sender, Receiver};
+
+use std::sync::atomic::{AtomicBool, Ordering};
+use lazy_static::lazy_static;
+
+lazy_static!{
+    static ref DEBUG_MODE: AtomicBool = AtomicBool::new(false);
+}
+
+pub struct Logger {
+    tx: Sender<String>,
+    rx: Receiver<String>,
+    out: Stderr
+}
+
+impl Logger {
+    pub fn new() -> Logger {
+        let (tx, rx) = channel(1);
+        let out = tokio::io::stderr();
+        Logger{
+            tx,
+            rx,
+            out,
+        }
+    }
+
+    pub async fn printing(&mut self) {
+        loop {
+            let s = self.rx.recv().await;
+            match s {
+                None => {}
+                Some(t) => {
+                    let _ = self.out.write_all(t.as_bytes()).await;
+                }
+            }
+        }
+    }
+
+    pub fn get_writer(&mut self, prefix: String) -> LogWriter {
+        LogWriter{tx: self.tx.clone(), prefix }
+    }
+}
+
+pub struct LogWriter {
+    prefix: String,
+    tx: Sender<String>,
+}
+
+impl LogWriter {
+    async fn log(&self, lv: LogLevel, msg: &str) {
+        let _ = self.tx.send(format!("[LOG] <{}> ({}) {}\n", lv, self.prefix.as_str(), msg)).await;
+    }
+
+    #[inline]
+    pub async fn info(&self, msg: &str) {
+        self.log(LogLevel::Info, msg).await;
+    }
+
+    #[inline]
+    pub async fn warn(&self, msg: &str) {
+        self.log(LogLevel::Warn, msg).await;
+    }
+
+    #[inline]
+    pub async fn error(&self, msg: &str) {
+        self.log(LogLevel::Error, msg).await;
+    }
+
+    #[inline]
+    pub async fn fatal(&self, msg: &str) {
+        self.log(LogLevel::Fatal, msg).await;
+    }
+
+    #[inline]
+    pub async fn debug(&self, msg: &str) {
+        if DEBUG_MODE.load(Ordering::Relaxed) {
+            self.log(LogLevel::Debug, msg).await;
+        }
+    }
+
+    pub fn is_debug_mode() -> bool {
+        DEBUG_MODE.load(Ordering::Relaxed)
+    }
+}
+
+enum LogLevel {
+    Debug,
+    Info,
+    Warn,
+    Error,
+    Fatal,
+}
+
+impl Display for LogLevel {
+    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+        let s = match self {
+            LogLevel::Info => "I",
+            LogLevel::Warn => "W",
+            LogLevel::Error => "E",
+            LogLevel::Fatal => "F",
+            LogLevel::Debug => "D",
+        };
+        write!(f, "{}", s)
+    }
+}
+
+pub fn set_debug_mode(mode: bool) {
+    DEBUG_MODE.store(mode, Ordering::Relaxed);
+}

+ 96 - 0
src/main.rs

@@ -0,0 +1,96 @@
+use std::{process, thread};
+use std::time::Duration;
+use tokio::task::JoinSet;
+use crate::reaper::Reaper;
+use pkg_compile_time::{pkg_compile_date, pkg_compile_time};
+
+mod shell;
+mod syscall;
+mod reaper;
+mod logger;
+mod sysinit;
+mod cfg;
+mod tty;
+
+#[tokio::main(flavor = "multi_thread", worker_threads = 2)]
+async fn main() {
+
+    println!("==== yukari - ELIP4NG Init Process. ====");
+    println!();
+
+    let pid = process::id();
+
+    if pid != 1 {
+        panic!("yukari must run as PID 1.");
+    }
+
+    println!("load config...");
+    cfg::init_config_manager().await;
+
+    println!("spawning tty...");
+    tty::spawn_tty().await;
+
+    println!("hello, this is No.1 process (as sysinit) '/usr/sbin/yukari'.");
+    println!("this program is compile at {} {}", pkg_compile_date!(), pkg_compile_time!());
+    println!();
+    println!("you can < PRESS ENTER > at any time to enter maintenance shell.");
+    println!();
+    println!("---- yukari sysinit phase ----");
+
+    let mut logmux = logger::Logger::new();
+    let logger_reaper = logmux.get_writer(String::from("reaper"));
+    let logger_sysinit = logmux.get_writer(String::from("sysinit"));
+
+    let zombie_reaper_res = Reaper::new(logger_reaper);
+    let mut zombie_reaper = match zombie_reaper_res {
+        Ok(r) => {r}
+        Err(err) => {
+            panic!("zombie reaper system sysinit failed: {:?}", err);
+        }
+    };
+
+    let mut sys_init = sysinit::SysInit::new(logger_sysinit);
+
+    let mut task_set = JoinSet::new();
+
+    task_set.spawn(async move {
+        logmux.printing().await;
+    });
+
+    task_set.spawn(async move {
+        let res = sys_init.prepare().await;
+        println!("---- yukari sysinit phase end ----");
+        match res {
+            None => {
+                println!("service management handover to supervisor");
+                println!();
+                println!("< PRESS ENTER > to enter maintenance shell.");
+                sys_init.run().await;
+            }
+            Some(err) => {
+                println!("[Error] error in sysinit phase: {:?}", err);
+                println!();
+                println!("< PRESS ENTER > to enter maintenance shell.");
+                loop{
+                    let _ = tokio::time::sleep(Duration::from_secs(10));
+                }
+            }
+        }
+    });
+
+    task_set.spawn_blocking(move || {
+        //shell::shell_wait_enter();
+        shell::shell_repl();
+    });
+
+    task_set.spawn( async move {
+        zombie_reaper.reap().await;
+    });
+
+    task_set.join_next().await;
+    println!("[FATAL] one of task exited. No.1 process will quit.");
+    task_set.abort_all();
+    println!("No.1 process quit. system will reboot after 5 seconds...");
+    let _ = tokio::time::sleep(Duration::from_secs(5));
+    syscall::power::safe_reboot();
+}

+ 73 - 0
src/reaper/mod.rs

@@ -0,0 +1,73 @@
+use nix::sys::wait::{WaitPidFlag, WaitStatus};
+use tokio::signal::unix::{signal, SignalKind, Signal};
+use crate::logger::LogWriter;
+
+use std::sync::atomic::{AtomicU64, Ordering};
+use lazy_static::lazy_static;
+
+lazy_static!{
+    static ref REAP_COUNTER: AtomicU64 = AtomicU64::new(0);
+}
+
+pub struct Reaper {
+    sig_stream: Signal,
+    logger: LogWriter,
+}
+
+impl Reaper {
+    pub fn new(logger: LogWriter) -> Result<Self, std::io::Error> {
+        let stream = signal(SignalKind::child())?;
+        Ok(Reaper { sig_stream: stream, logger })
+    }
+
+    pub async fn reap(&mut self) -> ! {
+        loop {
+            self.sig_stream.recv().await;
+            loop {
+                let wstat = nix::sys::wait::waitpid(nix::unistd::Pid::from_raw(-1), Some(WaitPidFlag::WNOHANG));
+                match wstat {
+                    Ok(ws) => {
+                        if LogWriter::is_debug_mode() {
+                            let msg = match ws {
+                                WaitStatus::Exited(pid, ec) => {
+                                    Some(format!("{}: WIFEXITED ExitCode={}", pid, ec))
+                                }
+                                WaitStatus::Signaled(pid, sig, t) => {
+                                    Some(format!("{}: WIFSIGNALED Signal={}, IsCoreDump={}", pid, sig, t))
+                                }
+                                WaitStatus::Stopped(pid, c) => {
+                                    Some(format!("{}: WIFSTOPPED Code={}", pid, c))
+                                }
+                                WaitStatus::PtraceEvent(pid, sig, c) => {
+                                    Some(format!("{}: PTRACE_EVENT Signal={}, Value={}", pid, sig, c))
+                                }
+                                WaitStatus::PtraceSyscall(pid) => {
+                                    Some(format!("{}: PTRACE_SYSCALL", pid))
+                                }
+                                WaitStatus::Continued(pid) => {
+                                    Some(format!("{}: WCONTINUED", pid))
+                                }
+                                WaitStatus::StillAlive => {
+                                    None
+                                }
+                            };
+                            if let Some(v) = msg {
+                                REAP_COUNTER.fetch_add(1, Ordering::Relaxed);
+                                self.logger.error(format!("reap zombie child {}", v).as_str()).await;
+                            }
+                        }else{
+                            if ws != WaitStatus::StillAlive {
+                                REAP_COUNTER.fetch_add(1, Ordering::Relaxed);
+                            }
+                        }
+                    }
+                    Err(_) => {}
+                };
+            }
+        };
+    }
+}
+
+pub fn get_count() -> u64 {
+    REAP_COUNTER.load(Ordering::Relaxed)
+}

+ 40 - 0
src/shell/mgrsh.rs

@@ -0,0 +1,40 @@
+use easy_repl::{command, CommandStatus, Repl};
+use crate::syscall;
+
+pub fn mgr_shell() {
+    let repl_bresult = Repl::builder()
+        .description("admin shell")
+        .prompt("[ M-Admin-Sh ] ")
+        .add("hello", command! {
+            "print hello",
+            () => || {
+                println!("hello!");
+                Ok(CommandStatus::Done)
+            }
+        })
+        .add("exec", command! {
+            "run a command, without arguments",
+            (shell: String) => |shell:String| {
+                syscall::proc::run(shell);
+                Ok(CommandStatus::Done)
+            }
+        })
+        .build();
+    let mut repl = match repl_bresult {
+        Ok(t) => t,
+        Err(err) => {
+            println!("[ERROR] admin Shell Init Fatal Error: {:?}", err);
+            return;
+        }
+    };
+    let repl_run_result = repl.run();
+    match repl_run_result {
+        Ok(_) => {
+            println!("Back to maintenance shell.");
+        }
+        Err(err) => {
+            println!("[ERROR] admin shell crash by error: {:?}", err);
+            println!("Back to maintenance shell.");
+        }
+    };
+}

+ 100 - 0
src/shell/mod.rs

@@ -0,0 +1,100 @@
+mod mgrsh;
+
+use std::io;
+use easy_repl::{command, CommandStatus, Repl};
+use crate::{cfg, logger, syscall};
+use crate::reaper;
+
+pub fn shell_wait_enter() {
+    let stdin = io::stdin();
+    let mut sbuf = String::new();
+    let _ = stdin.read_line(&mut sbuf);
+}
+
+pub fn shell_repl() {
+    println!("---- yukari maintenance shell ----");
+    let repl_bresult = Repl::builder()
+        .description("    -- yukari maintenance shell --")
+        .prompt("< Maintenance Shell > ")
+        .add("print", command! {
+            "print what input",
+            (msg: String) => |msg:String| {
+                println!("{}", msg.as_str());
+                Ok(CommandStatus::Done)
+            }
+        })
+        .add("reboot", command! {
+            "reboot system",
+            () => || {
+                syscall::power::safe_reboot();
+            }
+        })
+        .add("shutdown", command! {
+            "shutdown system",
+            () => || {
+                syscall::power::safe_shutdown();
+            }
+        })
+        .add("debug-on", command! {
+            "turn on debug printing for yukari",
+            () => || {
+                logger::set_debug_mode(true);
+                Ok(CommandStatus::Done)
+            }
+        })
+        .add("debug-off", command! {
+            "turn off debug printing for yukari",
+            () => || {
+                logger::set_debug_mode(false);
+                Ok(CommandStatus::Done)
+            }
+        })
+        .add("get-reaper-counter", command! {
+            "print the zombie child reaper working counter",
+            () => || {
+                println!("{} zombie child reaped.", reaper::get_count());
+                Ok(CommandStatus::Done)
+            }
+        })
+        .add("login", command! {
+            "login to admin shell",
+            (password: String) => |password:String| {
+                let bhash = cfg::CFG.blocking_get().get_etc_cfg().secure.bcrypt_password.clone();
+                let res = bcrypt::verify(password, &bhash);
+                match res {
+                    Ok(b) => {
+                        if b {
+                            mgrsh::mgr_shell();
+                        }else{
+                            println!("incorrect password.")
+                        }
+                    }
+                    Err(err) => {
+                        println!("failed verify password: {:?}", err)
+                    }
+                }
+                Ok(CommandStatus::Done)
+            }
+        })
+        .build();
+    let mut repl = match repl_bresult {
+        Ok(t) => t,
+        Err(err) => {
+            println!("Maintenance Shell Init Fatal Error: {:?}", err);
+            return;
+        }
+    };
+    loop {
+        let repl_run_result = repl.run();
+        match repl_run_result {
+            Ok(_) => {
+                println!("[WARN] shouldn't quit this shell");
+                println!("shell will restart");
+            }
+            Err(err) => {
+                println!("[ERROR] shell crash by error: {:?}", err);
+                println!("shell will restart");
+            }
+        };
+    }
+}

+ 2 - 0
src/syscall/mod.rs

@@ -0,0 +1,2 @@
+pub mod power;
+pub mod proc;

+ 33 - 0
src/syscall/power.rs

@@ -0,0 +1,33 @@
+use nix::sys::reboot::RebootMode;
+
+pub fn shutdown()  -> !{
+    println!("system shutting down...");
+    let _ = nix::sys::reboot::reboot(RebootMode::RB_POWER_OFF);
+    loop {
+    }
+}
+
+pub fn reboot() -> ! {
+    println!("system rebooting...");
+    let _ = nix::sys::reboot::reboot(RebootMode::RB_AUTOBOOT);
+    loop {
+    }
+}
+
+pub fn safe_shutdown() -> ! {
+    sync();
+    sync();
+    sync();
+    shutdown()
+}
+
+pub fn safe_reboot() -> ! {
+    sync();
+    sync();
+    sync();
+    reboot()
+}
+
+pub fn sync() {
+    nix::unistd::sync();
+}

+ 27 - 0
src/syscall/proc.rs

@@ -0,0 +1,27 @@
+use std::process::{Command};
+
+pub fn run(program: String) {
+    let p = Command::new(program.clone()).spawn();
+    match p {
+        Ok(mut ch) => {
+            let res = ch.wait();
+            match res {
+                Ok(es) => {
+                    match es.code() {
+                        None => {
+                            println!("exited with no code");
+                        }
+                        Some(code) => {
+                            println!("exited with code {}", code);
+                        }
+                    };
+                }
+                Err(_) => {}
+            }
+        }
+        Err(err) => {
+            println!("failed run command {}: {:?}", program.as_str(), err);
+            return;
+        }
+    }
+}

+ 24 - 0
src/sysinit/mod.rs

@@ -0,0 +1,24 @@
+use std::io::Error;
+use std::time::Duration;
+use crate::logger::LogWriter;
+
+pub struct SysInit {
+    logger: LogWriter,
+    is_ready: bool,
+}
+
+impl SysInit {
+    pub fn new(logger: LogWriter) ->SysInit {
+        SysInit{logger, is_ready: false}
+    }
+
+    pub async fn prepare(&mut self) -> Option<Error> {
+        None
+    }
+
+    pub async fn run(&mut self) {
+        loop {
+            let _ = tokio::time::sleep(Duration::from_secs(10));
+        }
+    }
+}

+ 4 - 0
src/tty/mod.rs

@@ -0,0 +1,4 @@
+
+pub async fn spawn_tty() {
+
+}