mod.rs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. mod mgrsh;
  2. mod prepare;
  3. use std::{thread, time};
  4. use easy_repl::{command, Repl, CommandStatus};
  5. use easy_repl::repl::BuilderError;
  6. use lazy_static::lazy_static;
  7. use nonblock::NonBlockingReader;
  8. use crate::{cfg, log};
  9. use crate::repl::mgrsh::mgr_shell;
  10. use crate::power;
  11. use std::sync::atomic::{AtomicBool, Ordering};
  12. use crate::swroot::switch_root;
  13. lazy_static!{
  14. static ref DO_SWITCH_ROOT_AFTER_QUIT: AtomicBool = AtomicBool::new(false);
  15. }
  16. pub fn build_repl_shell<'a>() -> Result<Repl<'a>, BuilderError> {
  17. Repl::builder()
  18. .description("rumia-cli operator view")
  19. .prompt("< rumia-cli > ")
  20. .add("print", command! {
  21. "print what input",
  22. (msg: String) => |msg:String| {
  23. println!("{}", msg.as_str());
  24. Ok(CommandStatus::Done)
  25. }
  26. })
  27. .add("reboot", command! {
  28. "reboot system",
  29. () => || {
  30. power::safe_reboot();
  31. }
  32. })
  33. .add("shutdown", command! {
  34. "shutdown system",
  35. () => || {
  36. power::safe_shutdown();
  37. }
  38. })
  39. .add("debug-on", command! {
  40. "turn on debug printing for rumia",
  41. () => || {
  42. log::set_debug_mode(true);
  43. Ok(CommandStatus::Done)
  44. }
  45. })
  46. .add("debug-off", command! {
  47. "turn off debug printing for rumia",
  48. () => || {
  49. log::set_debug_mode(false);
  50. Ok(CommandStatus::Done)
  51. }
  52. })
  53. .add("sys", command! {
  54. "login to system view",
  55. (password: String) => |password:String| {
  56. let bhash = cfg::CFG.get().get_rumia_con_cfg().get_password_bcrypt();
  57. let res = bcrypt::verify(password, &bhash);
  58. match res {
  59. Ok(b) => {
  60. if b {
  61. mgr_shell();
  62. }else{
  63. println!("incorrect password.")
  64. }
  65. }
  66. Err(err) => {
  67. println!("failed verify password: {:?}", err)
  68. }
  69. }
  70. if DO_SWITCH_ROOT_AFTER_QUIT.load(Ordering::Relaxed) {
  71. Ok(CommandStatus::Quit)
  72. }else{
  73. Ok(CommandStatus::Done)
  74. }
  75. }
  76. })
  77. .build()
  78. }
  79. pub fn fatal_to_shell() {
  80. DO_SWITCH_ROOT_AFTER_QUIT.store(false, Ordering::Relaxed);
  81. let repl_bresult= build_repl_shell();
  82. let mut repl = match repl_bresult {
  83. Ok(t) => t,
  84. Err(err) => {
  85. panic!("rumia shell init panic: {:?}", err);
  86. }
  87. };
  88. println!("Pre-init process aborted by fatal error.");
  89. println!("Now entering into the rumia shell...");
  90. loop {
  91. log::set_in_repl(true);
  92. let repl_run_result = repl.run();
  93. log::set_in_repl(false);
  94. match repl_run_result {
  95. Ok(_) => {
  96. if DO_SWITCH_ROOT_AFTER_QUIT.load(Ordering::Relaxed) {
  97. switch_root();
  98. }else{
  99. println!("[WARN] You shouldn't quit this shell now,\
  100. because of pre-init process aborted by fatal error. \
  101. You may need to fix some problems or you can just use \
  102. reboot or shutdown command to exit this shell.");
  103. println!("shell will restart");
  104. }
  105. }
  106. Err(err) => {
  107. println!("[ERROR] shell crash by error: {:?}", err);
  108. println!("shell will restart");
  109. }
  110. };
  111. }
  112. }
  113. pub fn user_pause_to_shell() {
  114. DO_SWITCH_ROOT_AFTER_QUIT.store(false, Ordering::Relaxed);
  115. let repl_bresult= build_repl_shell();
  116. let mut repl = match repl_bresult {
  117. Ok(t) => t,
  118. Err(err) => {
  119. panic!("rumia shell init panic: {:?}", err);
  120. }
  121. };
  122. println!("Pre-init process paused by user press <Enter>.");
  123. println!("Now entering into the rumia shell...");
  124. log::set_in_repl(true);
  125. let repl_run_result = repl.run();
  126. log::set_in_repl(false);
  127. match repl_run_result {
  128. Ok(_) => {
  129. if DO_SWITCH_ROOT_AFTER_QUIT.load(Ordering::Relaxed) {
  130. switch_root();
  131. }else {
  132. println!("continue pre-init process...");
  133. }
  134. }
  135. Err(err) => {
  136. println!("[ERROR] shell crash by error: {:?}", err);
  137. println!("system will restart");
  138. thread::sleep(time::Duration::from_secs(2));
  139. power::safe_reboot();
  140. }
  141. };
  142. }
  143. pub fn check_user_pause() -> bool {
  144. let nb_reader_res = NonBlockingReader::from_fd(std::io::stdin());
  145. let mut nb_reader = match nb_reader_res {
  146. Ok(r) => {r}
  147. Err(err) => {
  148. panic!("failed make stdin unblocking: {:?}", err)
  149. }
  150. };
  151. let mut rstr = String::new();
  152. let read_res = nb_reader.read_available_to_string(&mut rstr);
  153. nb_reader.into_blocking().expect("failed turn stdin into blocking mode.");
  154. match read_res {
  155. Ok(len) => {
  156. if len > 0 {
  157. true
  158. }else{
  159. false
  160. }
  161. }
  162. Err(_) => {
  163. false
  164. }
  165. }
  166. }
  167. pub fn check_enter_pause_to_shell() {
  168. let r = check_user_pause();
  169. if r {
  170. user_pause_to_shell();
  171. }
  172. }
  173. pub fn schedule_switch_root() {
  174. DO_SWITCH_ROOT_AFTER_QUIT.store(true, Ordering::Relaxed);
  175. }