diff options
Diffstat (limited to 'shell/src/lib.rs')
| -rw-r--r-- | shell/src/lib.rs | 64 |
1 files changed, 49 insertions, 15 deletions
diff --git a/shell/src/lib.rs b/shell/src/lib.rs index cf46cb0..ddd8688 100644 --- a/shell/src/lib.rs +++ b/shell/src/lib.rs | |||
| @@ -28,7 +28,7 @@ use alloc::collections::VecDeque; | |||
| 28 | use alloc::string::{String, ToString}; | 28 | use alloc::string::{String, ToString}; |
| 29 | use alloc::vec::Vec; | 29 | use alloc::vec::Vec; |
| 30 | use rsnix::tty::{self, LineInput}; | 30 | use rsnix::tty::{self, LineInput}; |
| 31 | use rsnix::{gop_print, gop_println, serial_print, serial_println}; | 31 | use rsnix::{gop_print, gop_println}; |
| 32 | 32 | ||
| 33 | /// Run the shell forever. | 33 | /// Run the shell forever. |
| 34 | pub fn run() -> ! { | 34 | pub fn run() -> ! { |
| @@ -36,18 +36,17 @@ pub fn run() -> ! { | |||
| 36 | "rs-dos v{} — type 'help' for commands", | 36 | "rs-dos v{} — type 'help' for commands", |
| 37 | env!("CARGO_PKG_VERSION") | 37 | env!("CARGO_PKG_VERSION") |
| 38 | ); | 38 | ); |
| 39 | serial_println!( | 39 | term_println(&alloc::format!( |
| 40 | "========== rs-dos v{} ==========", | 40 | "========== rs-dos v{} ==========", |
| 41 | env!("CARGO_PKG_VERSION") | 41 | env!("CARGO_PKG_VERSION") |
| 42 | ); | 42 | )); |
| 43 | 43 | ||
| 44 | loop { | 44 | loop { |
| 45 | // Push any deferred scrolls so the prompt renders on a current | 45 | // Push any deferred scrolls so the prompt renders on a current |
| 46 | // framebuffer (e.g. after a streaming command's batch of output). | 46 | // framebuffer (e.g. after a streaming command's batch of output). |
| 47 | rsnix::vt::sync_scroll(); | 47 | rsnix::vt::sync_scroll(); |
| 48 | // Print prompt | 48 | // Print prompt |
| 49 | gop_print!("> "); | 49 | term_print("> "); |
| 50 | serial_print!("> "); | ||
| 51 | 50 | ||
| 52 | // Read one line from keyboard (tty canonical mode) | 51 | // Read one line from keyboard (tty canonical mode) |
| 53 | match tty::read_line() { | 52 | match tty::read_line() { |
| @@ -65,13 +64,26 @@ pub fn run() -> ! { | |||
| 65 | } | 64 | } |
| 66 | 65 | ||
| 67 | // --------------------------------------------------------------------------- | 66 | // --------------------------------------------------------------------------- |
| 68 | // Diagnostics go straight to terminal + serial, never through the filter | 67 | // Diagnostics and command output go straight to terminal + serial, never |
| 69 | // pipeline and never into a file sink. | 68 | // through the filter pipeline and never into a file sink. These helpers |
| 69 | // write to the serial port directly — NOT via `serial_println!`, which | ||
| 70 | // feeds the klog ring — so user-facing shell output (prompts, echoes, | ||
| 71 | // command results) never lands in the boot log. | ||
| 70 | // --------------------------------------------------------------------------- | 72 | // --------------------------------------------------------------------------- |
| 71 | 73 | ||
| 74 | fn term_print(s: &str) { | ||
| 75 | gop_print!("{}", s); | ||
| 76 | rsnix::serial::write_str(s); | ||
| 77 | } | ||
| 78 | |||
| 79 | fn term_println(s: &str) { | ||
| 80 | term_print(s); | ||
| 81 | gop_println!(); | ||
| 82 | rsnix::serial::write_str("\r\n"); | ||
| 83 | } | ||
| 84 | |||
| 72 | fn term_err(msg: &str) { | 85 | fn term_err(msg: &str) { |
| 73 | gop_println!("{}", msg); | 86 | term_println(msg); |
| 74 | serial_println!("{}", msg); | ||
| 75 | } | 87 | } |
| 76 | 88 | ||
| 77 | // --------------------------------------------------------------------------- | 89 | // --------------------------------------------------------------------------- |
| @@ -541,8 +553,7 @@ impl Pipeline { | |||
| 541 | fn emit(&mut self, l: &str) { | 553 | fn emit(&mut self, l: &str) { |
| 542 | match &self.sink { | 554 | match &self.sink { |
| 543 | OutSink::Term => { | 555 | OutSink::Term => { |
| 544 | gop_println!("{}", l); | 556 | term_println(l); |
| 545 | serial_println!("{}", l); | ||
| 546 | } | 557 | } |
| 547 | OutSink::File { .. } => {} | 558 | OutSink::File { .. } => {} |
| 548 | } | 559 | } |
| @@ -672,6 +683,7 @@ write `{} <path> TIL <marker>`", | |||
| 672 | "pci" => cmd_pci(&parsed), | 683 | "pci" => cmd_pci(&parsed), |
| 673 | "ls" => cmd_ls(&parsed), | 684 | "ls" => cmd_ls(&parsed), |
| 674 | "cat" => cmd_cat(&parsed), | 685 | "cat" => cmd_cat(&parsed), |
| 686 | "klog" => cmd_klog(&parsed), | ||
| 675 | "hexdump" => cmd_hexdump(&parsed), | 687 | "hexdump" => cmd_hexdump(&parsed), |
| 676 | "mkdir" => cmd_mkdir(&parsed), | 688 | "mkdir" => cmd_mkdir(&parsed), |
| 677 | "touch" => cmd_touch(&parsed), | 689 | "touch" => cmd_touch(&parsed), |
| @@ -700,6 +712,7 @@ fn cmd_help(_p: &Parsed) { | |||
| 700 | pci — list PCI devices | 712 | pci — list PCI devices |
| 701 | ls — list a directory | 713 | ls — list a directory |
| 702 | cat — print files (cat USE a TO b copies a→b; cat TIL END is a heredoc) | 714 | cat — print files (cat USE a TO b copies a→b; cat TIL END is a heredoc) |
| 715 | klog — kernel boot log (cat /dev/klog; WRITING <dst> persists it) | ||
| 703 | hexdump — hex-dump a file or input stream | 716 | hexdump — hex-dump a file or input stream |
| 704 | mkdir — create a directory | 717 | mkdir — create a directory |
| 705 | touch — create an empty file | 718 | touch — create an empty file |
| @@ -789,6 +802,29 @@ fn cmd_ls(p: &Parsed) { | |||
| 789 | } | 802 | } |
| 790 | 803 | ||
| 791 | // --------------------------------------------------------------------------- | 804 | // --------------------------------------------------------------------------- |
| 805 | // klog — kernel log (thin alias for `cat /dev/klog`) | ||
| 806 | // --------------------------------------------------------------------------- | ||
| 807 | |||
| 808 | fn cmd_klog(p: &Parsed) { | ||
| 809 | if !p.args.is_empty() { | ||
| 810 | term_err("klog: usage: klog [-h N] [-t N] [-g PAT] [-p] [WRITING <dst> | TO <dst>]"); | ||
| 811 | return; | ||
| 812 | } | ||
| 813 | // Alias for `cat /dev/klog` — same filters and redirection, so | ||
| 814 | // `klog -t 5` shows the last 5 log lines and `klog WRITING | ||
| 815 | // /disk/.../boot.log` persists the boot log. Input keywords were | ||
| 816 | // already rejected (klog does not accept input). | ||
| 817 | let q = Parsed { | ||
| 818 | cmd: alloc::string::String::from("klog"), | ||
| 819 | args: alloc::vec!["/dev/klog".into()], | ||
| 820 | input: Input::None, | ||
| 821 | filters: p.filters.clone(), | ||
| 822 | output: p.output.clone(), | ||
| 823 | }; | ||
| 824 | cmd_cat(&q); | ||
| 825 | } | ||
| 826 | |||
| 827 | // --------------------------------------------------------------------------- | ||
| 792 | // cat — file and stream consumers | 828 | // cat — file and stream consumers |
| 793 | // --------------------------------------------------------------------------- | 829 | // --------------------------------------------------------------------------- |
| 794 | 830 | ||
| @@ -1471,8 +1507,7 @@ fn cmd_stress(p: &Parsed) { | |||
| 1471 | } | 1507 | } |
| 1472 | 1508 | ||
| 1473 | fn cmd_halt() -> ! { | 1509 | fn cmd_halt() -> ! { |
| 1474 | gop_println!("halting..."); | 1510 | term_println("halting..."); |
| 1475 | serial_println!("halting..."); | ||
| 1476 | rsnix::power::halt() | 1511 | rsnix::power::halt() |
| 1477 | } | 1512 | } |
| 1478 | 1513 | ||
| @@ -1515,7 +1550,6 @@ fn cmd_pci(p: &Parsed) { | |||
| 1515 | } | 1550 | } |
| 1516 | 1551 | ||
| 1517 | fn cmd_poweroff() -> ! { | 1552 | fn cmd_poweroff() -> ! { |
| 1518 | gop_println!("shutting down..."); | 1553 | term_println("shutting down..."); |
| 1519 | serial_println!("shutting down..."); | ||
| 1520 | rsnix::power::poweroff() | 1554 | rsnix::power::poweroff() |
| 1521 | } | 1555 | } |
