buninu-linux 0.13.56 → 0.15.58

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/LICENSES/linux-firmware/LICENCE.nvidia +131 -0
  2. package/LICENSES/linux-firmware/LICENSE.amdgpu +51 -0
  3. package/LICENSES/linux-firmware/LICENSE.amdisp +31 -0
  4. package/LICENSES/linux-firmware/LICENSE.i915 +39 -0
  5. package/LICENSES/linux-firmware/LICENSE.radeon +51 -0
  6. package/LICENSES/linux-firmware/LICENSE.xe +39 -0
  7. package/LICENSES/linux-firmware/WHENCE +10280 -0
  8. package/NOTICE.md +64 -46
  9. package/README.md +410 -96
  10. package/README.zh.md +2034 -0
  11. package/build-image.sh +10 -1
  12. package/build-uki.sh +3 -1
  13. package/fetch-alpine.sh +15 -1
  14. package/graphics.md +31 -0
  15. package/index.js +28 -11
  16. package/initramfs/bin/buninu-browser +4 -1
  17. package/initramfs/bin/buninu-land +1 -1
  18. package/initramfs/bin/bunterm +3 -3
  19. package/initramfs/bin/chroot +13 -0
  20. package/initramfs/bin/chvt +11 -0
  21. package/initramfs/bin/dhclient +8 -0
  22. package/initramfs/bin/mount +4 -0
  23. package/initramfs/bin/ping +8 -0
  24. package/initramfs/bin/umount +6 -0
  25. package/initramfs/bin/xdg-open +33 -0
  26. package/initramfs/buninu/CHANGELOG.md +19 -0
  27. package/initramfs/buninu/apps/bunmsh/CHANGELOG.md +4 -0
  28. package/initramfs/buninu/apps/bunmsh/package.json +1 -1
  29. package/initramfs/buninu/apps/bunmsh/src/main.js +1 -1
  30. package/initramfs/buninu/apps/jsgotty/README.en.md +40 -0
  31. package/initramfs/buninu/apps/jsgotty/README.md +40 -0
  32. package/initramfs/buninu/apps/jsgotty/package-lock.json +2 -2
  33. package/initramfs/buninu/apps/jsgotty/package.json +1 -1
  34. package/initramfs/buninu/apps/jsgotty/static/index.html +1 -0
  35. package/initramfs/buninu/apps/jsgotty/static/js/gotty.js +82 -17
  36. package/initramfs/buninu/apps/jsgotty/static/js/kitty-keyboard.js +193 -0
  37. package/initramfs/buninu/apps/jsgotty/tests/android-alt.test.js +115 -0
  38. package/initramfs/buninu/apps/jsgotty/tests/arrow-modifiers.test.js +80 -0
  39. package/initramfs/buninu/apps/jsgotty/tests/kitty-keyboard-browser.test.js +53 -0
  40. package/initramfs/buninu/apps/jsgotty/tests/kitty-keyboard.test.js +102 -0
  41. package/initramfs/buninu/apps/jsgotty/tests/manual/README.md +20 -0
  42. package/initramfs/buninu/apps/jsgotty/tests/manual/keyboard-collector.cjs +55 -0
  43. package/initramfs/buninu/apps/jsgotty/tests/manual/keyboard-debug.js +74 -0
  44. package/initramfs/buninu/apps/jsgotty/tests/manual/kitty-keyboard.js +80 -0
  45. package/initramfs/buninu/package.json +1 -1
  46. package/initramfs/init.js +27 -10
  47. package/initramfs/lib/bunterm/clipboard.js +14 -0
  48. package/initramfs/lib/bunterm/commands.js +37 -0
  49. package/initramfs/lib/bunterm/fps.js +38 -0
  50. package/initramfs/lib/bunterm/images.js +9 -5
  51. package/initramfs/lib/bunterm/input.js +58 -15
  52. package/initramfs/lib/bunterm/keyboard.js +62 -0
  53. package/initramfs/lib/bunterm/keycodes.js +104 -0
  54. package/initramfs/lib/bunterm/kitty-keyboard.cjs +195 -0
  55. package/initramfs/lib/bunterm/raw-protocol.js +33 -0
  56. package/initramfs/lib/bunterm/renderer.js +90 -21
  57. package/initramfs/lib/bunterm/selection.js +60 -0
  58. package/initramfs/lib/bunterm/terminal.js +147 -12
  59. package/initramfs/lib/bunterm/vt-menu.js +181 -0
  60. package/initramfs/lib/bunterm/vt.js +27 -1
  61. package/initramfs/lib/canvas.js +99 -0
  62. package/initramfs/lib/chvt.js +31 -0
  63. package/initramfs/lib/dhclient.js +135 -0
  64. package/initramfs/lib/dhcp-start.js +85 -0
  65. package/initramfs/lib/dhcp-transport.js +44 -0
  66. package/initramfs/lib/dhcp.js +124 -0
  67. package/initramfs/lib/dlopen.js +58 -11
  68. package/initramfs/lib/fbdev.js +21 -3
  69. package/initramfs/lib/gpu.js +77 -0
  70. package/initramfs/lib/ping.js +110 -0
  71. package/initramfs/lib/raw-image.js +47 -0
  72. package/initramfs/lib/xdg-open.js +42 -0
  73. package/initramfs/usr/share/doc/buninu-linux/bunterm.md +86 -12
  74. package/initramfs/usr/share/doc/buninu-linux/chvt.md +34 -0
  75. package/initramfs/usr/share/doc/buninu-linux/dhclient.md +82 -0
  76. package/initramfs/usr/share/doc/buninu-linux/ping.md +91 -0
  77. package/initramfs/usr/share/doc/buninu-linux/xdg-open.md +43 -0
  78. package/package.json +2 -2
  79. package/scripts/arch.js +7 -5
  80. package/scripts/arch.sh +5 -5
  81. package/scripts/build.js +16 -3
  82. package/scripts/fetch-gpu.js +105 -0
  83. package/scripts/fetch.js +11 -1
  84. package/scripts/gpu-firmware.json +22 -0
  85. package/scripts/modules.js +5 -1
  86. package/scripts/npm-packages.md +17 -17
  87. package/test/bunterm-fps.test.js +17 -0
  88. package/test/bunterm-keyboard.test.js +116 -0
  89. package/test/bunterm-next-vt.test.js +9 -0
  90. package/test/bunterm-raw-protocol.test.js +19 -0
  91. package/test/bunterm-renderer.test.js +158 -0
  92. package/test/bunterm-selection.test.js +38 -0
  93. package/test/bunterm-vt-menu.test.js +178 -0
  94. package/test/chroot-bind.test.js +40 -2
  95. package/test/chvt.test.js +46 -0
  96. package/test/dhcp-start.test.js +67 -0
  97. package/test/dhcp.test.js +99 -0
  98. package/test/fbdev-sync.test.js +33 -0
  99. package/test/fetch-npm.test.js +1 -1
  100. package/test/gpu.test.js +155 -0
  101. package/test/image-size.test.js +17 -0
  102. package/test/libc.test.js +41 -0
  103. package/test/manual-bunterm-image-paths.js +31 -0
  104. package/test/mount-libc-lifetime.test.js +50 -0
  105. package/test/no-gpu.test.js +43 -0
  106. package/test/ping.test.js +80 -0
  107. package/test/readme-cli.test.js +29 -0
  108. package/test/stage-npm.test.js +11 -4
  109. package/test/xdg-open.test.js +55 -0
@@ -8,7 +8,7 @@ box drawing and kitty graphics protocol images — no X11, Wayland or GPU.
8
8
  ```sh
9
9
  bunterm 2 # start a detached bunterm on /dev/tty2
10
10
  bunterm /dev/tty2 # the full virtual-console spelling also works
11
- bunterm # take over the console you are on (on tty1 that hides the bun-repl)
11
+ bunterm # open a new VT after the last session; first is tty2
12
12
  bunterm -s 20 # short for --font-size 20
13
13
  bunterm -e bun /buninu/apps/jsmdcui/src/index.js --demo
14
14
  bunterm --no-mouse # keyboard only
@@ -16,14 +16,19 @@ bunterm --no-clipboard # ignore OSC 52 copy and paste
16
16
  bunterm -h
17
17
  ```
18
18
 
19
+ Use `chvt 1` inside bunterm to return to tty1 without stopping it, and
20
+ `chvt 2` from a shell to return to a bunterm started on tty2. See `chvt --help`
21
+ for use from the init REPL.
22
+
19
23
  The program's `TERM` is `xterm-256color`, `COLORTERM=truecolor`,
20
24
  `TERM_PROGRAM=bunterm` and `JSMDCUI_KITTY_MODE=extended` (so `jsmdcui` shows
21
25
  Markdown images without `--kitty`). When it exits, the console returns to
22
26
  text mode and `bunterm` exits with its status.
23
27
 
24
28
  Every live session has a canonical `/bin/bunterm /dev/ttyN ...` command line.
25
- When no console is named, the currently active VT is used in the foreground.
26
- Naming a different VT starts bunterm as a detached session and returns
29
+ When no console is named, a new VT after the last known session is selected,
30
+ starting at tty2 and keeping tty1 for hardware setup.
31
+ Using a VT other than the active one starts bunterm as a detached session and returns
27
32
  immediately to the calling shell. Only one bunterm may control a given VT;
28
33
  ownership is
29
34
  identified from the process task name and its open console descriptor under
@@ -33,14 +38,14 @@ identified from the process task name and its open console descriptor under
33
38
 
34
39
  | Option | Meaning |
35
40
  | --- | --- |
36
- | `N`, `/dev/ttyN` | The virtual console to use for graphics and the keyboard; for example, `2` means `/dev/tty2`. Naming a VT other than the active one starts a detached bunterm there, switches the display to it, and immediately returns control to the calling shell. Without this argument, bunterm uses the active VT in the foreground. |
41
+ | `N`, `/dev/ttyN` | The virtual console to use for graphics and the keyboard; for example, `2` means `/dev/tty2`. Naming a VT other than the active one starts a detached bunterm there, switches the display to it, and immediately returns control to the calling shell. Without this argument, bunterm selects the next VT after the last known session (tty2 initially). |
37
42
  | `-e command [argument...]` | The program to run; everything after `-e` belongs to it. Default `/bin/sh`. |
38
- | `-s N`, `--font-size N` | Font size in pixels (default 16). The cell is 0.6 × N wide and 1.16 × N tall with DejaVu Sans Mono, so 1024×768 at 16 px gives 106 × 41 cells. |
43
+ | `-s N`, `--font-size N` | Font size in pixels (default 13). The cell is 0.6 × N wide and 1.16 × N tall with DejaVu Sans Mono, so 1024×768 at 16 px gives 106 × 41 cells. |
39
44
  | `--line-height F` | Multiplies the cell height (default 1). |
40
45
  | `--fb /dev/fbN` | The framebuffer device (default `/dev/fb0`). |
41
46
  | `--no-blink` | A steady cursor. |
42
47
  | `--no-mouse` | Do not attach a pointing device; nothing then reads `/dev/input`. |
43
- | `--no-clipboard` | Ignore OSC 52: programs can neither copy to nor read from the clipboard, and `xclip` is never run. |
48
+ | `--no-clipboard` | Disable both OSC 52 and menu copy/paste; `xclip` is never run. |
44
49
 
45
50
  ## What is drawn
46
51
 
@@ -66,7 +71,7 @@ identified from the process task name and its open console descriptor under
66
71
 
67
72
  ## Keyboard
68
73
 
69
- The console stays in the kernel's translated keyboard mode, so
74
+ Without Kitty keyboard negotiation, the console stays in the kernel's translated keyboard mode, so
70
75
  `Ctrl-Alt-F2` and friends still switch consoles; coming back repaints the
71
76
  screen. While its VT is inactive, bunterm continues consuming PTY output and
72
77
  updating its scrollback and kitty images, but neither writes the framebuffer
@@ -76,6 +81,28 @@ forth through the normal Linux VT switch. A few console-specific
76
81
  sequences are rewritten to xterm's (`F1`–`F5`, `Home`, `End`), and arrow keys
77
82
  follow the program's application cursor mode.
78
83
 
84
+ ### Kitty keyboard
85
+
86
+ The Kitty keyboard protocol uses the same encoder as jsgotty 1.2.0:
87
+ flags **1** (disambiguation), **2** (press/repeat/release), and **8** (all keys).
88
+ Applications enable it with `CSI > flags u`, query with `CSI ? u`, and restore
89
+ with `CSI < u`; normal and alternate buffers have separate stacks. Flags 4
90
+ (alternate keys) and 16 (associated text) are not advertised.
91
+
92
+ Only while an application enables Kitty, the active console uses Linux
93
+ `K_MEDIUMRAW` to distinguish Ctrl, Alt, Shift, Super, keypad and key releases.
94
+ Bunterm restores the original mode on pop/reset or exit. Ctrl+Alt+F1–F12 and
95
+ Alt+Left/Right remain reserved for VT switching. The kernel keymap supplies
96
+ printable characters, including Shift/Caps Lock/AltGr. Kernel dead-key/Compose
97
+ sequences are not implemented in this Kitty path; the ordinary translated
98
+ console path retains its existing behavior. No global evdev keyboard grab is
99
+ needed. A mode transition discards pending console typeahead so raw keycodes
100
+ cannot leak into the child as text.
101
+
102
+ 中文:Kitty 模式與 jsgotty 支援相同的 flags 1、2、8,可區分 Super、
103
+ Ctrl/Alt/Shift 組合及按下/重複/放開。程式退出模式後恢復原有 console
104
+ 輸入;Ctrl+Alt+Fn、Alt+左右保留為切換 VT。Kitty 模式尚不處理 dead key/Compose。
105
+
79
106
  ## Mouse
80
107
 
81
108
  Every pointing device under `/dev/input/event*` is opened and an arrow is
@@ -94,6 +121,13 @@ arrow keys on the alternate screen, which has no scrollback and is what a
94
121
  pager expects. Typing returns to the live screen, and the text cursor is
95
122
  hidden while it is scrolled out of view.
96
123
 
124
+ When mouse reporting is off, left-drag selects terminal text. Wide characters
125
+ and graphemes are selected whole; wrapped lines copy without extra newlines.
126
+ Use **Copy** in the top-left menu to send the selection to xclip. Selection is
127
+ cleared when new PTY text arrives or the font size changes, so it cannot refer
128
+ to replaced cells. Applications requesting mouse reporting receive the drag
129
+ instead; selection never overrides their mouse mode.
130
+
97
131
  `--no-mouse` turns all of this off: the terminal then never looks at
98
132
  `/dev/input` and never loads the mouse module.
99
133
 
@@ -114,7 +148,12 @@ bunterm keeps no clipboard of its own: `ESC ] 52 ; c ; <base64>` is passed to
114
148
  with the output of `xclip -selection clipboard -o`, so every bunterm session
115
149
  shares the same clipboard as `xclip`. A query xclip cannot answer is replied
116
150
  to with empty contents. `--no-clipboard` turns this off, so a program can
117
- neither set nor read the clipboard through the terminal.
151
+ neither set nor read the clipboard through the terminal; menu copy/paste is
152
+ also disabled. The menu's **Paste** reads xclip and sends one paste to the PTY,
153
+ wrapped in `CSI 200~` / `CSI 201~` when the application enabled bracketed paste
154
+ (`DECSET 2004`). Programs that have not requested it receive plain text.
155
+ Newlines are normalized to CR; embedded ESC bytes are stripped in bracketed
156
+ mode so clipboard text cannot close the paste early.
118
157
 
119
158
  ## Limits
120
159
 
@@ -123,10 +162,8 @@ neither set nor read the clipboard through the terminal.
123
162
  `--linux-lts` or `--real` (efifb/simpledrm from UEFI).
124
163
  - The aarch64 image has no framebuffer yet: `run-qemu.sh` gives QEMU's
125
164
  `virt` machine no display device, so there is no `/dev/fb0` to draw on.
126
- - No selection, and no keyboard way to scroll back: the wheel is it. The
127
- buffer keeps 1000 lines. A program that does not enable mouse reporting
128
- sees no clicks — the arrow still moves, so the pointer is visibly alive.
129
- `--no-mouse` removes the pointer entirely.
165
+ - Scrollback uses the wheel; the buffer keeps 1000 lines.
166
+ `--no-mouse` removes the pointer and local selection.
130
167
  - A program that prints a terminal reply while the tty echoes (that is, one
131
168
  not in raw mode) will see the reply echoed, as on any terminal.
132
169
  - Kitty images are drawn above text; `z` ordering below text and animation
@@ -143,3 +180,40 @@ neither set nor read the clipboard through the terminal.
143
180
  - `/lib/fbdev.js` — the framebuffer itself (`fbdev.md`)
144
181
  - `/buninu/apps/jsgotty/gotty.js` — the PTY backend and kitty packet parser
145
182
  that are reused
183
+
184
+ ## Local menu and commands
185
+
186
+ Left-click the top-left **2×2 physical pixels** to open a text menu of live
187
+ bunterm VTs and the initial tty (normally tty1). Click an entry to switch, or use
188
+ Up/Down and Enter. The active VT is marked `(current)`.
189
+ The wheel scrolls the selection; Escape, right-click, or a click
190
+ outside the entries closes the menu. Menu input is consumed locally, including
191
+ when a terminal application has enabled mouse reporting. Requires mouse support.
192
+ The menu switches existing sessions; it does not create a new bunterm.
193
+
194
+ - **Font − / +** changes the current session's font size and resizes the PTY.
195
+ - **Copy / Paste** uses the same xclip clipboard as OSC 52.
196
+ - Click the light **command input field**, or press Tab, to type a local command.
197
+ Enter executes it, Tab returns to menu navigation, Esc closes the menu.
198
+ Backspace/Delete, Left/Right, Home/End and Ctrl+U edit the field.
199
+
200
+ Commands: `font 16`, `font +`, `font -`, `copy`, `paste`, `vt 2`, `help`.
201
+ Font commands accept integer sizes 6–96; changes last for this session.
202
+ The command registry is `/lib/bunterm/commands.js`; new commands can be added
203
+ there without changing the input widget. These are bunterm commands, not shell
204
+ commands. Clipboard failures and command errors appear in the menu footer.
205
+
206
+ 中文:左鍵點擊螢幕最左上角 2×2 像素,會列出正在運行的 bunterm 和初始 tty。
207
+ 目前顯示的 VT 會標示 `(current)`。
208
+ 可以點選或用上下鍵、Enter 切換;Esc、右鍵或點擊選項外關閉。不會把選單操作
209
+ 送進底下的 shell/應用程式,也不會關閉原本的 bunterm。
210
+ 選單還有字體大小減/加、複製/貼上,以及自由輸入的命令框(點選或按 Tab)。
211
+ 可輸入 `font 16`、`copy`、`paste`、`vt 2`、`help`;Enter 執行。
212
+ 複製前用左鍵拖曳選字,僅在程式未開啟滑鼠回報時生效。貼上沿用 xclip,
213
+ 程式啟用 bracketed paste 時會加上貼上邊界。
214
+
215
+ On GPU-provided fbdev devices, a shared framebuffer mapping may not support
216
+ `msync`. bunterm probes it once: `EINVAL`/`EOPNOTSUPP` disables further msync
217
+ calls for that mapping while pixel writes continue normally. Drivers that
218
+ support msync retain it; other errors still propagate. This is not a vsync or
219
+ GPU-acceleration mechanism.
@@ -0,0 +1,34 @@
1
+ # chvt — switch Linux virtual terminals
2
+
3
+ ```sh
4
+ chvt 1 # switch to /dev/tty1 (normally the init REPL)
5
+ chvt 2 # switch to /dev/tty2
6
+ chvt -h # also --help
7
+ ```
8
+
9
+ Accepts one VT number, 1–63. Requires access to a real Linux virtual console
10
+ and permission to switch it (normally root). A PTY alone, including a remote
11
+ terminal or Android terminal, is not a Linux VT.
12
+
13
+ With bunterm, for example:
14
+
15
+ ```sh
16
+ bunterm 2 # start bunterm on tty2
17
+ chvt 1 # from its shell, return to tty1 without stopping bunterm
18
+ ```
19
+
20
+ Run `chvt 2` from a shell to return, or use Alt+F2 / Ctrl+Alt+F2 as appropriate.
21
+ At the init JavaScript REPL, run a command with
22
+ `Bun.spawnSync(["/bin/chvt", "2"], {stdio: ["inherit", "inherit", "inherit"]})`.
23
+ The command switches the existing VT; it does not start a shell or bunterm on an
24
+ empty VT. bunterm retains ownership of its VT, pauses drawing when switched away,
25
+ and redraws when switched back. chvt does not change keyboard or graphics modes.
26
+
27
+ Like the traditional command, chvt waits for the target VT to become active,
28
+ then exits. If its current owner refuses to release the VT, the wait can persist. No daemon is created.
29
+
30
+ 中文:`chvt 1` 切至 tty1,`chvt 2` 切回 tty2 的 bunterm;不會結束 bunterm,
31
+ 也不會替空白 VT 啟動 shell。切出/切回使用 bunterm 原有的釋放與重繪機制。
32
+
33
+ Uses Linux VT_ACTIVATE and VT_WAITACTIVE:
34
+ https://man7.org/linux/man-pages/man2/ioctl_vt.2.html
@@ -0,0 +1,82 @@
1
+ # dhclient — DHCPv4 client
2
+
3
+ Use `ip link` to list available network interfaces, then choose the interface
4
+ name for the command, for example `dhclient usb0`.
5
+
6
+ Acquire an IPv4 lease on an Ethernet-compatible interface. DHCP packets are
7
+ implemented in JavaScript; Bun FFI calls the runtime libc for packet/UDP
8
+ sockets and interface identification. Address and route changes invoke the
9
+ existing Buninu `ip` command, without an external DHCP binary or dependencies.
10
+
11
+ ```sh
12
+ dhclient eth0 # acquire, configure, then exit
13
+ dhclient -v -timeout 20 eth0 # show progress, fail after 20 seconds
14
+ dhclient -r eth0 # release a saved lease after the client stops
15
+ dhclient --no-dns eth0 # leave the resolver unchanged
16
+ ```
17
+
18
+ | Option | Meaning |
19
+ | --- | --- |
20
+ | `-4` | DHCPv4 (default) |
21
+ | `-d` | Accepted for compatibility; all invocations exit after configuration |
22
+ | `-1` | Acquire once (already the default) |
23
+ | `-r` | Send DHCPRELEASE and remove the saved lease's configuration |
24
+ | `-timeout SECONDS` | Initial acquisition deadline; default 60 seconds |
25
+ | `-v`, `-q` | Verbose protocol progress, or quiet output |
26
+ | `-H HOSTNAME` | Send DHCP hostname option |
27
+ | `-lf PATH` | JSON lease file; default `/var/lib/dhclient/INTERFACE.json` |
28
+ | `--metric NUMBER` | Default route metric, 0–32766 |
29
+ | `--no-dns` | Do not write DNS configuration |
30
+ | `--resolv-conf PATH` | Resolver file; default `/etc/resolv.conf` |
31
+ | `-h`, `--help` | This manual |
32
+
33
+ Specify one interface per process. The interface is brought up first. This
34
+ client replaces its primary IPv4 address and installs the first offered
35
+ router as its default gateway. DNS server addresses replace the resolver
36
+ file; its previous content is saved and restored on explicit release only if
37
+ another writer has not modified it. `--no-dns` is useful for secondary links.
38
+ Avoid simultaneous resolver management by multiple clients.
39
+
40
+ Each invocation acquires and configures one lease, then exits. No background
41
+ renewal process is started. `-1` is an optional alias for this default behavior.
42
+ A DHCP lease is still time-limited unless the server grants an infinite lease:
43
+ run the command again before expiry, or use an appropriate static address.
44
+ After exit this command cannot renew or remove an expired address. The reported
45
+ lease duration and JSON timestamps show the server's validity period.
46
+ Ctrl-C/SIGTERM during acquisition stops the attempt; successful configuration
47
+ remains after normal exit. Use `-r` to release it explicitly. Saved JSON leases
48
+ support release and resolver restoration; their addresses are never assumed
49
+ valid on a later acquisition.
50
+
51
+ The per-interface `/run/dhclient-INTERFACE.lock` prevents duplicate Buninu
52
+ clients, including callers using different lease files. Stop the running
53
+ client before `-r`. After an unclean kill, verify it is gone before removing
54
+ the stale lock. UDP port 68 is reserved exclusively to detect other clients.
55
+
56
+ Linux/Android on x86-64 or aarch64 is supported, subject to privileges:
57
+ CAP_NET_RAW for packet sockets, CAP_NET_ADMIN for interface/route changes,
58
+ and permission to bind UDP 68 and write lease/resolver files. Ordinary
59
+ unprivileged Termux cannot configure Android networking. Root in Buninu's
60
+ VM can. Library selection follows the shared `dlopen.js` runtime ABI rules.
61
+
62
+ This is a focused client, not an ISC dhclient CLI clone. DHCPv6, ISC config/
63
+ script hooks, address-conflict ARP probing/DECLINE, classless static routes,
64
+ and automatic renewal/daemonization are not implemented. Wi-Fi must already be
65
+ associated. A failed acquisition exits nonzero; successful one-shot/release
66
+ or clean signal termination returns zero.
67
+
68
+ Protocol: [RFC 2131](https://www.rfc-editor.org/rfc/rfc2131) and
69
+ [DHCP options, RFC 2132](https://www.rfc-editor.org/rfc/rfc2132).
70
+ Run `bun test test/dhcp.test.js test/libc.test.js` for codec, state-machine,
71
+ configuration and libc regression tests; tests do not reconfigure host links.
72
+
73
+ `cfg.net` launches foreground clients as background child processes. Each has
74
+ a 20-second acquisition deadline and an independent 25-second startup watchdog
75
+ (SIGTERM, then SIGKILL after 2 seconds if necessary). Successful clients exit after configuration; none remain to renew. All child and output failures are caught and logged. Metrics start
76
+ at 100 per interface; only the first interface may write DNS. Repeated calls
77
+ reuse active clients; a later call can retry clients which have exited.
78
+
79
+ Automatic calls report one final result per interface, prefixed with
80
+ `[dhcp INTERFACE]`. A failed interface does not change another interface's
81
+ success result or configuration; output is collected before reporting exit
82
+ status so a delayed stderr message cannot appear after its final result.
@@ -0,0 +1,91 @@
1
+ # ping — send ICMP echo requests
2
+
3
+ `ping` sends real IPv4 ICMP or IPv6 ICMPv6 echo requests through Bun FFI.
4
+ It does not execute a system ping, open a TCP connection, or use an HTTP probe.
5
+
6
+ ```sh
7
+ ping [-4|-6] [-nqD] [-c COUNT] [-i SECONDS] [-W SECONDS]
8
+ [-w SECONDS] [-s BYTES] [-t TTL] [-I ADDRESS|INTERFACE] DESTINATION
9
+ ping --help
10
+ ```
11
+
12
+ | Option | Meaning |
13
+ |---|---|
14
+ | `-c COUNT` | Stop after COUNT requests and their replies/timeouts. Default: 4 requests, then exit. |
15
+ | `-i SECONDS` | Send interval, default 1 second; fractional values supported, minimum 0.002 seconds. |
16
+ | `-W SECONDS` | Per-request reply timeout, default 2 seconds; fractional values supported. |
17
+ | `-w SECONDS` | Overall probing deadline, including outstanding requests. DNS resolution happens first. |
18
+ | `-s BYTES` | Payload size, default 56; 0–65507 bytes. The ICMP header adds 8 bytes. |
19
+ | `-t TTL` | IPv4 TTL or IPv6 hop limit, 1–255; default 64. |
20
+ | `-I ADDRESS` | Bind a source IPv4/IPv6 address. |
21
+ | `-I INTERFACE` | Bind an interface such as `eth0` or `wlan0`; OS permissions may be required. |
22
+ | `-4`, `-6` | Select IPv4 or IPv6. Numeric destinations infer their family; hostnames default to IPv4. |
23
+ | `-n` | Numeric reply addresses (currently always used; no reverse DNS). |
24
+ | `-q` | Print only the initial line and final statistics. |
25
+ | `-D` | Add Unix timestamps to per-packet output. |
26
+ | `-h`, `--help` | Show this document. |
27
+
28
+ Short options can be combined (`-nq`) and values attached (`-c3`). Use `--`
29
+ to end option parsing. Unknown options are rejected rather than ignored.
30
+
31
+ ```sh
32
+ ping -c 4 1.1.1.1
33
+ ping -c 3 localhost
34
+ ping -6 -c 3 ::1
35
+ ping -n -c 10 -i 0.2 -W 1 -s 1200 192.168.1.1
36
+ ping -q -w 5 192.168.1.1
37
+ ping -I eth0 -c 3 192.168.1.1
38
+ ```
39
+
40
+ Statistics include transmitted/received counts, loss and RTT min/average/max/
41
+ standard deviation. Ctrl-C prints statistics and closes the socket. Exit status
42
+ is 0 if any reply arrived, 1 if none arrived (or a combined `-c`/`-w` deadline
43
+ prevented receiving the requested count), and 2 for argument/setup/system errors.
44
+ RTT is measured by the Bun process, so event-loop scheduling affects it.
45
+
46
+ The preferred socket is an unprivileged ICMP datagram (ping) socket. If the OS
47
+ refuses that socket, a raw ICMP socket is attempted; this normally requires root
48
+ or `CAP_NET_RAW`. Linux controls datagram access with `ping_group_range`, and
49
+ Android may impose additional restrictions. The command does not change system
50
+ permissions. Replies are matched by identifier, sequence and payload; IPv4
51
+ checksums are checked. Concurrent outstanding probes are supported. Datagram
52
+ replies do not expose their received TTL through this implementation, so it is
53
+ not printed; raw IPv4 replies do include TTL.
54
+
55
+ Supported runtimes: 64-bit Linux (glibc or musl) and native Android/Termux
56
+ (bionic), on x86_64 or aarch64. `/lib/dlopen.js` chooses libc automatically:
57
+
58
+ - Android: `libc.so`, then the APEX and `/system/lib64` bionic paths; `__errno`.
59
+ - Linux glibc runtime: `libc.so.6`, then architecture-specific `/lib` and
60
+ `/usr/lib` glibc paths; `__errno_location`.
61
+ - Linux musl runtime: the adjacent `libc.musl-<arch>.so.1`, its soname,
62
+ `/lib/libc.musl-<arch>.so.1`, `/lib/ld-musl-<arch>.so.1`, then `libc.so`;
63
+ `__errno_location`.
64
+ - Search stays within the runtime ABI: loading musl into glibc can crash on
65
+ errno/TLS access.
66
+ - `BUNINU_LIBC=/absolute/path` overrides the search. A bad override fails
67
+ explicitly rather than silently selecting a different library. Symbols resolve
68
+ on first use: an unavailable mount symbol does not prevent ping from using
69
+ the socket symbols. An explicit override is not rejected based on its filename;
70
+ matching the runtime ABI remains the caller's responsibility.
71
+
72
+ Windows requires a separate `iphlpapi.dll` ICMP backend and is not implemented.
73
+ Flood/adaptive modes, IPv4 record-route/timestamps, reverse DNS, broadcast ping,
74
+ and IPv6 scoped address notation (`fe80::1%eth0`) are not implemented.
75
+
76
+ ## Tests
77
+
78
+ ```sh
79
+ bun test test/ping.test.js test/libc.test.js
80
+ ```
81
+
82
+ These compare local IPv4/IPv6 echo replies, payload sizes, counts, quiet output,
83
+ source selection, deadlines and exit codes against the installed system ping.
84
+ RTT values are not expected to match. A missing system ping or unavailable
85
+ loopback ICMP support skips the corresponding network comparisons. Older
86
+ Android systems have a separate `ping6` and a 200 ms interval restriction; the
87
+ reference tests accommodate those without limiting this command's options.
88
+ Packet validation, argument errors, fast intervals and Ctrl-C also have tests.
89
+
90
+ References: [Linux ICMP sockets](https://man7.org/linux/man-pages/man7/icmp.7.html),
91
+ [Android errno](https://android.googlesource.com/platform/bionic/+/master/libc/include/errno.h).
@@ -0,0 +1,43 @@
1
+ # xdg-open — open in a new browser terminal / 開啟瀏覽器
2
+
3
+ ```sh
4
+ xdg-open https://buninu.org
5
+ xdg-open about:audio
6
+ xdg-open ./page.html
7
+ xdg-open "./file with spaces.md"
8
+ xdg-open file:///buninu/page.html
9
+ ```
10
+
11
+ Runs `bunterm -e buninu-browser URL` on a new virtual console. HTTP, HTTPS,
12
+ and `about:` URLs go to the browser. Local files must exist: symbolic links
13
+ are resolved and the real path is encoded as a `file://` URL, including spaces,
14
+ Chinese characters, `#`, and `%`. Markdown also opens in the browser.
15
+
16
+ 透過 bunterm 在新 tty 啟動瀏覽器。本地檔案先確認存在、解析實際路徑,再轉成
17
+ `file://` 網址;Markdown 同樣使用瀏覽器。檔名若以 `-` 開頭,請加上 `./`。
18
+
19
+ Directories and other schemes (including `data:`, `mailto:` and `ftp:`) are
20
+ not supported. This is Buninu's lightweight implementation, not xdg-utils;
21
+ it does not consult MIME associations or desktop application registrations.
22
+ 目前不支援目錄與其他協定,也不查詢 MIME 預設程式關聯。
23
+
24
+ ## Options / 選項
25
+
26
+ | Option | Meaning |
27
+ | --- | --- |
28
+ | `-h`, `--help`, `--manual` | Show this Markdown manual / 顯示本手冊 |
29
+ | `--version` | Show the Buninu Linux version from the image's os-release / 顯示映像檔的發行版版本 |
30
+
31
+ ## Exit codes / 退出碼
32
+
33
+ | Code | Meaning |
34
+ | --- | --- |
35
+ | 0 | New terminal launch succeeded / 新終端啟動成功 |
36
+ | 1 | Invalid arguments or URL / 參數或網址格式錯誤 |
37
+ | 2 | Local file does not exist / 本地檔案不存在 |
38
+ | 3 | Required tool not found / 缺少必要工具 |
39
+ | 4 | Opening failed or target unsupported / 開啟失敗或目標不支援 |
40
+
41
+ bunterm detaches when opening a new VT. Exit code 0 confirms the launcher
42
+ succeeded, not that the browser subsequently loaded the page.
43
+ 新 tty 以背景工作階段啟動,因此成功退出不代表後續網頁一定載入成功。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "buninu-linux",
3
- "version": "0.13.56",
3
+ "version": "0.15.58",
4
4
  "description": "A Linux distribution running Bun as PID 1 with the Buninu userspace.",
5
5
  "type": "module",
6
6
  "main": "./index.js",
@@ -37,6 +37,6 @@
37
37
  "fetch": "./index.js -f",
38
38
  "pack": "./index.js -b",
39
39
  "start": "./index.js -r",
40
- "check": "for f in ./index.js ./initramfs/init.js ./initramfs/lib/document.js ./initramfs/lib/dlopen.js ./initramfs/lib/fbdev.js ./initramfs/lib/canvas.js ./initramfs/lib/bunterm/glyphs.js ./initramfs/lib/bunterm/renderer.js ./initramfs/lib/bunterm/images.js ./initramfs/lib/bunterm/input.js ./initramfs/lib/bunterm/mouse.js ./initramfs/lib/bunterm/terminal.js ./initramfs/lib/modprobe.js ./initramfs/lib/power.js ./initramfs/bin/bunterm ./initramfs/bin/chroot ./initramfs/bin/mount ./initramfs/bin/umount ./initramfs/bin/ip ./initramfs/bin/ps ./initramfs/bin/top ./initramfs/bin/poweroff ./initramfs/bin/reboot ./initramfs/bin/tar ./initramfs/bin/stripansi; do node --check \"$f\" || exit 1; done"
40
+ "check": "for f in ./index.js ./initramfs/init.js ./initramfs/lib/document.js ./initramfs/lib/dlopen.js ./initramfs/lib/ping.js ./initramfs/lib/dhcp.js ./initramfs/lib/dhcp-transport.js ./initramfs/lib/dhclient.js ./initramfs/lib/dhcp-start.js ./initramfs/lib/fbdev.js ./initramfs/lib/canvas.js ./initramfs/lib/bunterm/glyphs.js ./initramfs/lib/bunterm/renderer.js ./initramfs/lib/bunterm/images.js ./initramfs/lib/bunterm/input.js ./initramfs/lib/bunterm/mouse.js ./initramfs/lib/bunterm/terminal.js ./initramfs/lib/modprobe.js ./initramfs/lib/power.js ./initramfs/bin/bunterm ./initramfs/bin/chroot ./initramfs/bin/mount ./initramfs/bin/umount ./initramfs/bin/ip ./initramfs/bin/ping ./initramfs/bin/dhclient ./initramfs/bin/ps ./initramfs/bin/top ./initramfs/bin/poweroff ./initramfs/bin/reboot ./initramfs/bin/tar ./initramfs/bin/stripansi; do node --check \"$f\" || exit 1; done"
41
41
  }
42
42
  }
package/scripts/arch.js CHANGED
@@ -16,8 +16,8 @@ export const rootDir = resolve(dirname(fileURLToPath(import.meta.url)), "..");
16
16
 
17
17
  const pins = {
18
18
  x86_64: {
19
- linuxVirtSha256: "755deb045cfeb8c2bcaa2b2febe01ab2101d747921e64d4cd54d0312321e8d5d",
20
- linuxLtsSha256: "b0d8cc4d7e031b5619221e7978920d051bf1dd1e335f6d05d03964b2285fc3b4",
19
+ linuxVirtSha256: "1eec55004cf7167c914c8839f46691d2bc82767e20466bff51eb45d06f8e90cc",
20
+ linuxLtsSha256: "af399fba75cafb2940fc2853eb73ba2289aa463228f33541cd3010334a30992b",
21
21
  muslSha256: "573712e2f49c15bfc20a2699f204acdfc74c772722b15e7353d768057fae0e71",
22
22
  stubSha256: "8e64a5a3afee5f930e6e6716be726dc6d405530ac7f8fa5be6251dae68671ec9",
23
23
  libstdcppSha256: "14c987b556f5385a5db18376e788c75f37d85321b8dc1920d926ea7daac1d6f6",
@@ -32,8 +32,8 @@ const pins = {
32
32
  serialMajor: 4,
33
33
  },
34
34
  aarch64: {
35
- linuxVirtSha256: "e3839bfd751ff0a4421484f712b9b29efb514024523736a0ef62521521571b12",
36
- linuxLtsSha256: "795bcd49840be7f4ff9566f5f669201bd41202376a455b720a98eb814f0e72f8",
35
+ linuxVirtSha256: "b46c51ddf572d85b2ba7b9adfaa64f4c38fc490c93d97a20ffd2418d51284085",
36
+ linuxLtsSha256: "65ab581dd6773e2b1b6831dac50142518b2f2083668f164f68ebfcd00d1763c4",
37
37
  muslSha256: "5e9674b7f41152fe2119093b5cb4c13eaaadb19c2d5422b2d7267913e663ee6e",
38
38
  stubSha256: "a1823d2d7082db555d528f82c1809f276c818aeb5b40f198f4565f104e055c38",
39
39
  libstdcppSha256: "2302e766d4e4926038ec166ecb85837ee884576115236ddb565e3a5fca4a11d7",
@@ -58,6 +58,7 @@ export const config = ({
58
58
  arch = process.env.BUNINU_ARCH || "x86_64",
59
59
  flavor = process.env.LINUX_FLAVOR || "virt",
60
60
  real = process.env.REAL_MACHINE === "1",
61
+ noGpu = process.env.BUNINU_NO_GPU === "1",
61
62
  mirror = process.env.ALPINE_MIRROR || "https://dl-cdn.alpinelinux.org/alpine",
62
63
  } = {}) => {
63
64
  arch = normalizeArch(arch);
@@ -67,7 +68,7 @@ export const config = ({
67
68
  // The Alpine repository keeps only the newest build of a package, so a pin
68
69
  // stops downloading when Alpine bumps it; the hashes then fail loudly.
69
70
  const alpineBase = `${mirror}/v3.24/main/${arch}`;
70
- const kernelVersion = "6.18.56";
71
+ const kernelVersion = "6.18.58";
71
72
  const kernelRelease = `${kernelVersion}-0-${flavor}`;
72
73
  const bunVersion = "1.4.2";
73
74
  const downloadsDir = join(rootDir, "downloads", arch);
@@ -77,6 +78,7 @@ export const config = ({
77
78
  arch,
78
79
  flavor,
79
80
  real,
81
+ noGpu,
80
82
  rootDir,
81
83
  alpineBase,
82
84
  kernelVersion,
package/scripts/arch.sh CHANGED
@@ -44,7 +44,7 @@ fi
44
44
  alpine_mirror=${ALPINE_MIRROR:-https://dl-cdn.alpinelinux.org/alpine}
45
45
  alpine_base="$alpine_mirror/v3.24/main/$arch"
46
46
 
47
- kernel_version=6.18.56
47
+ kernel_version=6.18.58
48
48
  kernel_release="$kernel_version-0-$linux_flavor"
49
49
  linux_package="linux-$linux_flavor-$kernel_version-r0.apk"
50
50
  musl_package=musl-1.2.6-r2.apk
@@ -63,8 +63,8 @@ musl_libc="libc.musl-$arch.so.1"
63
63
 
64
64
  case $arch in
65
65
  x86_64)
66
- linux_virt_sha256=755deb045cfeb8c2bcaa2b2febe01ab2101d747921e64d4cd54d0312321e8d5d
67
- linux_lts_sha256=b0d8cc4d7e031b5619221e7978920d051bf1dd1e335f6d05d03964b2285fc3b4
66
+ linux_virt_sha256=1eec55004cf7167c914c8839f46691d2bc82767e20466bff51eb45d06f8e90cc
67
+ linux_lts_sha256=af399fba75cafb2940fc2853eb73ba2289aa463228f33541cd3010334a30992b
68
68
  musl_sha256=573712e2f49c15bfc20a2699f204acdfc74c772722b15e7353d768057fae0e71
69
69
  stub_sha256=8e64a5a3afee5f930e6e6716be726dc6d405530ac7f8fa5be6251dae68671ec9
70
70
  libstdcpp_sha256=14c987b556f5385a5db18376e788c75f37d85321b8dc1920d926ea7daac1d6f6
@@ -82,8 +82,8 @@ case $arch in
82
82
  serial_major=4
83
83
  ;;
84
84
  aarch64)
85
- linux_virt_sha256=e3839bfd751ff0a4421484f712b9b29efb514024523736a0ef62521521571b12
86
- linux_lts_sha256=795bcd49840be7f4ff9566f5f669201bd41202376a455b720a98eb814f0e72f8
85
+ linux_virt_sha256=b46c51ddf572d85b2ba7b9adfaa64f4c38fc490c93d97a20ffd2418d51284085
86
+ linux_lts_sha256=65ab581dd6773e2b1b6831dac50142518b2f2083668f164f68ebfcd00d1763c4
87
87
  musl_sha256=5e9674b7f41152fe2119093b5cb4c13eaaadb19c2d5422b2d7267913e663ee6e
88
88
  stub_sha256=a1823d2d7082db555d528f82c1809f276c818aeb5b40f198f4565f104e055c38
89
89
  libstdcpp_sha256=2302e766d4e4926038ec166ecb85837ee884576115236ddb565e3a5fca4a11d7
package/scripts/build.js CHANGED
@@ -28,6 +28,7 @@ import { format, openVolume } from "../initramfs/lib/fat.js";
28
28
  import { TYPES, randomGuid, writeGpt } from "../initramfs/lib/gpt.js";
29
29
  import { config, jsRuntime, rootDir, runIfMain } from "./arch.js";
30
30
  import { fetchAlpine } from "./fetch.js";
31
+ import { gpuReady } from "./fetch-gpu.js";
31
32
  import { pack } from "./pack.js";
32
33
 
33
34
  const nonEmpty = (path) => existsSync(path) && statSync(path).size > 0;
@@ -64,6 +65,7 @@ export const uki = async (cfg = config()) => {
64
65
  const missing = !nonEmpty(cfg.kernelImage)
65
66
  || !nonEmpty(join(cfg.kernelDir, cfg.efiStub))
66
67
  || !nonEmpty(join(cfg.modulesRoot, "modules.dep"))
68
+ || !gpuReady(cfg)
67
69
  || (cfg.real && (
68
70
  !nonEmpty(join(cfg.modulesRoot, "kernel/drivers/hid/usbhid/usbhid.ko"))
69
71
  || !nonEmpty(join(cfg.modulesRoot, "kernel/drivers/acpi/battery.ko"))
@@ -94,11 +96,22 @@ export const uki = async (cfg = config()) => {
94
96
  console.log(`Built ${cfg.arch} UKI with Alpine linux-${cfg.flavor} at vda/EFI/BOOT/${cfg.efiBootName}`);
95
97
  };
96
98
 
97
- /** build-image.sh: vda.img, 128 MiB, GPT with the ESP from sector 2048 to the last usable one. */
99
+ // Keep small images at 128 MiB. Reserve 1/16 payload size plus 4 MiB for
100
+ // FAT metadata, directories, GPT/alignment and free space, rounded to 64 MiB.
101
+ // Keep this calculation aligned with build-image.sh.
102
+ export const imageBytes = (payloadBytes) => {
103
+ if (!Number.isSafeInteger(payloadBytes) || payloadBytes < 0 || payloadBytes > 0xffffffff)
104
+ throw new Error("EFI payload exceeds the FAT32 single-file limit or has an invalid size");
105
+ const unit = 64 * 1024 * 1024;
106
+ return Math.max(128 * 1024 * 1024,
107
+ Math.ceil((payloadBytes + Math.ceil(payloadBytes / 16) + 4 * 1024 * 1024) / unit) * unit);
108
+ };
109
+
110
+ /** build-image.sh: dynamically sized GPT disk with one FAT32 ESP. */
98
111
  export const image = (cfg = config()) => {
99
112
  const efi = join(rootDir, "vda/EFI/BOOT", cfg.efiBootName);
100
113
  if (!nonEmpty(efi)) throw new Error(`no ${cfg.arch} EFI payload ${efi} yet; build the UKI first`);
101
- const diskSectors = (128 * 1024 * 1024) / 512;
114
+ const diskSectors = imageBytes(statSync(efi).size) / 512;
102
115
  const espStart = 2048;
103
116
  const espEnd = diskSectors - 34;
104
117
  const path = join(rootDir, "vda.img");
@@ -134,7 +147,7 @@ export const image = (cfg = config()) => {
134
147
  } finally {
135
148
  volume.close();
136
149
  }
137
- console.log(`Packed vda/EFI/BOOT/${cfg.efiBootName} into vda.img`);
150
+ console.log(`Packed vda/EFI/BOOT/${cfg.efiBootName} into vda.img (${diskSectors * 512 / 1024 / 1024} MiB)`);
138
151
  };
139
152
 
140
153
  export const buildAll = async (cfg = config()) => {