diff options
Diffstat (limited to 'shell/src')
| -rw-r--r-- | shell/src/lib.rs | 67 |
1 files changed, 57 insertions, 10 deletions
diff --git a/shell/src/lib.rs b/shell/src/lib.rs index bb048d8..f1addd9 100644 --- a/shell/src/lib.rs +++ b/shell/src/lib.rs | |||
| @@ -53,14 +53,15 @@ pub fn run() -> ! { | |||
| 53 | term_println("!!! PREVIOUS CRASH REPORT:"); | 53 | term_println("!!! PREVIOUS CRASH REPORT:"); |
| 54 | let mut buf = [0u8; 256]; | 54 | let mut buf = [0u8; 256]; |
| 55 | if let Ok(n) = rsnix::fs::read(h, &mut buf, 0) | 55 | if let Ok(n) = rsnix::fs::read(h, &mut buf, 0) |
| 56 | && n > 0 { | 56 | && n > 0 |
| 57 | let s = core::str::from_utf8(&buf[..n]).unwrap_or("?"); | 57 | { |
| 58 | for line in s.split('\n') { | 58 | let s = core::str::from_utf8(&buf[..n]).unwrap_or("?"); |
| 59 | if !line.is_empty() { | 59 | for line in s.split('\n') { |
| 60 | term_println(line); | 60 | if !line.is_empty() { |
| 61 | } | 61 | term_println(line); |
| 62 | } | 62 | } |
| 63 | } | 63 | } |
| 64 | } | ||
| 64 | term_println("!!! end of crash report"); | 65 | term_println("!!! end of crash report"); |
| 65 | } | 66 | } |
| 66 | 67 | ||
| @@ -739,6 +740,9 @@ write `{} <path> TIL <marker>`", | |||
| 739 | "touch" => cmd_touch(&parsed), | 740 | "touch" => cmd_touch(&parsed), |
| 740 | "rm" => cmd_rm(&parsed), | 741 | "rm" => cmd_rm(&parsed), |
| 741 | "edit" => cmd_edit(&parsed), | 742 | "edit" => cmd_edit(&parsed), |
| 743 | "draw" => cmd_draw(&parsed), | ||
| 744 | "windows" => cmd_windows(&parsed), | ||
| 745 | "restore" => cmd_restore(&parsed), | ||
| 742 | "bg" => cmd_bg(&parsed), | 746 | "bg" => cmd_bg(&parsed), |
| 743 | "jobs" => cmd_jobs(&parsed), | 747 | "jobs" => cmd_jobs(&parsed), |
| 744 | "msgrecv" => cmd_msgrecv(&parsed), | 748 | "msgrecv" => cmd_msgrecv(&parsed), |
| @@ -1387,6 +1391,40 @@ fn cmd_edit(p: &Parsed) { | |||
| 1387 | rsnix::gop::clear_screen(); | 1391 | rsnix::gop::clear_screen(); |
| 1388 | } | 1392 | } |
| 1389 | 1393 | ||
| 1394 | fn cmd_draw(_p: &Parsed) { | ||
| 1395 | match rsnix::sched::spawn(rspaint::run, "paint") { | ||
| 1396 | Some(id) => term_println(&alloc::format!( | ||
| 1397 | "draw: paint task {} — F4 or the close button to close", | ||
| 1398 | id | ||
| 1399 | )), | ||
| 1400 | None => term_err("draw: task table full"), | ||
| 1401 | } | ||
| 1402 | } | ||
| 1403 | |||
| 1404 | fn cmd_windows(_p: &Parsed) { | ||
| 1405 | let list = rsnix::wm::list(); | ||
| 1406 | if list.is_empty() { | ||
| 1407 | term_println("windows: none (console only)"); | ||
| 1408 | return; | ||
| 1409 | } | ||
| 1410 | for (id, title, minimized) in list { | ||
| 1411 | term_println(&alloc::format!( | ||
| 1412 | " {} {}{}", | ||
| 1413 | id, | ||
| 1414 | title, | ||
| 1415 | if minimized { " (minimized)" } else { "" } | ||
| 1416 | )); | ||
| 1417 | } | ||
| 1418 | } | ||
| 1419 | |||
| 1420 | fn cmd_restore(p: &Parsed) { | ||
| 1421 | let Some(id) = p.args.first().and_then(|s| s.parse::<usize>().ok()) else { | ||
| 1422 | term_err("usage: restore <id>"); | ||
| 1423 | return; | ||
| 1424 | }; | ||
| 1425 | rsnix::wm::restore(id); | ||
| 1426 | } | ||
| 1427 | |||
| 1390 | fn cmd_mem(p: &Parsed) { | 1428 | fn cmd_mem(p: &Parsed) { |
| 1391 | let (map, key) = rsnix::memory::get_map(); | 1429 | let (map, key) = rsnix::memory::get_map(); |
| 1392 | 1430 | ||
| @@ -1602,14 +1640,19 @@ fn cmd_heapdbg(_p: &Parsed) { | |||
| 1602 | let ov = h.heap_start < fb.saturating_add(fsz) && fb < h.heap_end; | 1640 | let ov = h.heap_start < fb.saturating_add(fsz) && fb < h.heap_end; |
| 1603 | term_println(&alloc::format!( | 1641 | term_println(&alloc::format!( |
| 1604 | "fb {:#x} size={:#x} overlap-heap={}", | 1642 | "fb {:#x} size={:#x} overlap-heap={}", |
| 1605 | fb, fsz, ov | 1643 | fb, |
| 1644 | fsz, | ||
| 1645 | ov | ||
| 1606 | )); | 1646 | )); |
| 1607 | } | 1647 | } |
| 1608 | let probe = h.heap_start.wrapping_add(0x443e0); // historical crash offset | 1648 | let probe = h.heap_start.wrapping_add(0x443e0); // historical crash offset |
| 1609 | match rsnix::memory::freelist_contains(probe) { | 1649 | match rsnix::memory::freelist_contains(probe) { |
| 1610 | Some((b, s, off)) => term_println(&alloc::format!( | 1650 | Some((b, s, off)) => term_println(&alloc::format!( |
| 1611 | "probe {:#x} (+0x443e0) IN free blk {:#x} size={:#x} off={:#x}", | 1651 | "probe {:#x} (+0x443e0) IN free blk {:#x} size={:#x} off={:#x}", |
| 1612 | probe, b, s, off | 1652 | probe, |
| 1653 | b, | ||
| 1654 | s, | ||
| 1655 | off | ||
| 1613 | )), | 1656 | )), |
| 1614 | None => term_println(&alloc::format!("probe {:#x} (+0x443e0) NOT free", probe)), | 1657 | None => term_println(&alloc::format!("probe {:#x} (+0x443e0) NOT free", probe)), |
| 1615 | } | 1658 | } |
| @@ -1682,7 +1725,9 @@ fn cmd_heapdbg(_p: &Parsed) { | |||
| 1682 | let (rc, rr) = rsnix::vt::cell_raw(tr, tc); | 1725 | let (rc, rr) = rsnix::vt::cell_raw(tr, tc); |
| 1683 | term_println(&alloc::format!( | 1726 | term_println(&alloc::format!( |
| 1684 | "shadow@{:x} cell={:08x} rendered={:08x}", | 1727 | "shadow@{:x} cell={:08x} rendered={:08x}", |
| 1685 | f, rc, rr | 1728 | f, |
| 1729 | rc, | ||
| 1730 | rr | ||
| 1686 | )); | 1731 | )); |
| 1687 | } | 1732 | } |
| 1688 | } | 1733 | } |
| @@ -1697,7 +1742,9 @@ fn cmd_heapdbg(_p: &Parsed) { | |||
| 1697 | match rsnix::memory::freelist_contains(b) { | 1742 | match rsnix::memory::freelist_contains(b) { |
| 1698 | Some((fb, fs, fo)) => term_println(&alloc::format!( | 1743 | Some((fb, fs, fo)) => term_println(&alloc::format!( |
| 1699 | "shadow base IN free list: blk {:#x} size={:#x} off={:#x}", | 1744 | "shadow base IN free list: blk {:#x} size={:#x} off={:#x}", |
| 1700 | fb, fs, fo | 1745 | fb, |
| 1746 | fs, | ||
| 1747 | fo | ||
| 1701 | )), | 1748 | )), |
| 1702 | None => term_println("shadow base NOT in free list"), | 1749 | None => term_println("shadow base NOT in free list"), |
| 1703 | } | 1750 | } |
