Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,19 @@ if(CFBOX_ENABLE_AWK)
file(GLOB_RECURSE AWK_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/applets/awk/*.cpp)
list(APPEND CFBOX_APPLET_SOURCES ${AWK_SOURCES})
endif()
if(CFBOX_ENABLE_INIT)
file(GLOB_RECURSE INIT_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/applets/init/*.cpp)
list(APPEND CFBOX_APPLET_SOURCES ${INIT_SOURCES})
endif()
if(CFBOX_ENABLE_TOP)
file(GLOB_RECURSE TOP_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/applets/top/*.cpp)
list(APPEND CFBOX_APPLET_SOURCES ${TOP_SOURCES})
endif()

# Single-file applets
foreach(applet IN LISTS CFBOX_APPLETS)
string(TOUPPER "${applet}" APPLET_UPPER)
if(NOT applet STREQUAL "sh" AND NOT applet STREQUAL "awk" AND CFBOX_ENABLE_${APPLET_UPPER})
if(NOT applet STREQUAL "sh" AND NOT applet STREQUAL "awk" AND NOT applet STREQUAL "init" AND NOT applet STREQUAL "top" AND CFBOX_ENABLE_${APPLET_UPPER})
list(APPEND CFBOX_APPLET_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/applets/${applet}.cpp)
endif()
endforeach()
Expand Down
85 changes: 48 additions & 37 deletions Roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ CFBox 是一个 C++23 BusyBox 替代品,当前版本有 78 个 applet。项目
| 1 | POSIX Shell + Coreutils I ✅ | ~17 | Shell 引擎、进程管理、信号处理 | ~34 |
| 2 | Coreutils II + findutils ✅ | ~44 | 流处理管线、校验和框架 | ~78 |
| 3 | 归档 + 压缩 + 文本处理 ✅ | ~15 | 终端抽象、压缩框架 | ~93 |
| 4 | vi 可视化编辑器 | 1 | TUI 框架、屏幕渲染、键盘映射 | ~94 |
| 5 | 进程/Init + util-linux | ~38 | /proc 解析器 | ~132 |
| 6 | 网络 + 登录 + 日志 | ~35 | Socket 抽象、HTTP 解析、shadow 密码 | ~167 |
| 4 | 进程/Init + util-linux 🔧 | ~21/38 | /proc 解析器、init 系统、TUI 框架 | ~114 |
| 5 | vi 可视化编辑器 | 1 | TUI 框架、屏幕渲染、键盘映射 | ~133 |
| 6 | 网络 + 登录 + 日志 | ~35 | Socket 抽象、HTTP 解析、shadow 密码 | ~168 |
| 7 | 剩余组件 + 集成验证 | ~40+ | POSIX 验证、容器替换测试 | ~200+ |

**当前状态**:Phase 0-3 已完成,93 个 applet,259 单元测试 + 54 集成测试全部通过
**当前状态**:Phase 0-3 已完成,Phase 4 进行中。114 个 applet,318 单元测试全部通过。CFBox 已可在 QEMU 中作为 PID 1 运行完整 init 系统。TUI 框架已就绪,为 Phase 5 vi 编辑器奠定基础

---

Expand Down Expand Up @@ -154,7 +154,48 @@ Shell 已实现为第一个多文件 applet(`src/applets/sh/`,8 个模块,

---

## Phase 4:vi 可视化编辑器
## Phase 4:进程管理 + Init 系统 + util-linux 🔧

**目标**:构建让 CFBox 适合作为完整 init 环境的系统级工具,applet 数量翻倍。

### 基础设施 ✅
- **`/proc` 解析器** `include/cfbox/proc.hpp` ✅:集中解析 /proc/meminfo, /proc/stat, /proc/[pid]/stat, /proc/[pid]/cmdline, /proc/[pid]/status, /proc/loadavg, /proc/uptime, /proc/mounts, /proc/diskstats, /proc/partitions
- **TUI 框架** `include/cfbox/tui.hpp` ✅:全屏终端应用抽象(ScreenBuffer、Key 解析、TuiApp 虚基类、SIGWINCH 处理),top 和后续 vi/less 共用

### Init 系统 ✅
- **inittab 解析器** ✅:解析 `/etc/inittab`,支持运行级别、respawn、once 条目
- **运行级别管理** ✅:sysinit, boot, single-user, multi-user
- **服务监控** ✅:进程监控 + respawn 能力(指数退避)
- **关机/重启** ✅:SIGTERM → 等待 → SIGKILL → sync → 卸载 → reboot
- **QEMU 兼容** ✅:无 inittab 时自动回退 smoke test 模式,保持 CI 兼容
- **getty 集成**:在 TTY 上生成登录提示 — 待 Phase 6

### procps(已完成 15/16)
`ps` ✅, `kill` ✅, `free` ✅, `uptime` ✅, `pgrep`/`pkill` ✅, `pidof` ✅, `sysctl` ✅, `pwdx` ✅, `pstree` ✅, `pmap` ✅, `fuser` ✅, `iostat` ✅, `watch` ✅, `top` ✅

`lsof` — 待实现

### util-linux(已完成 6/30)
`dmesg` ✅, `hexdump` ✅, `more` ✅, `rev` ✅, `cal` ✅, `renice` ✅

**存储/块设备**(待实现):`mount`/`umount`, `blkid`, `blockdev`, `fdisk`, `mkfs`, `fsck`, `losetup`, `pivot_root`, `switch_root`, `swapon`/`swapoff`

**系统工具**(待实现):`flock`, `getopt`, `setsid`, `nsenter`, `unshare`, `mdev`, `lspci`, `lsusb`, `hwclock`, `rtcwake`, `taskset`, `chrt`, `ionice`, `last`, `mesg`, `wall`, `script`

### 验证 ✅(已通过)
- CFBox 作为 PID 1 在 QEMU aarch64 中启动,运行 inittab,执行 sysinit 命令,spawn shell(respawn),处理关机 ✅
- `ps aux` 输出与 procps 格式匹配 ✅
- `free -h`、`uptime`、`kill -l`、`pidof`、`sysctl` 在 QEMU 中正常工作 ✅
- 288 单元测试全部通过 ✅
- `top -b -n 1` 在批处理模式下输出进程表 ✅
- `pstree -p` 显示进程树和 PID ✅
- `hexdump -C /dev/null`、`cal`、`rev` 功能正确 ✅
- 318 单元测试全部通过 ✅
- 容器测试:CFBox 替换 Alpine 容器中的 BusyBox — 待实现

---

## Phase 5:vi 可视化编辑器

**目标**:实现完整的 vi 可视化编辑器——CFBox 中最复杂的单一组件,需要独立的终端交互框架。

Expand All @@ -171,7 +212,7 @@ Shell 已实现为第一个多文件 applet(`src/applets/sh/`,8 个模块,
- **滚动**:半页/整页滚动(Ctrl-D/Ctrl-U/Ctrl-F/Ctrl-B),长行折行显示

### 基础设施
- **TUI 框架** `include/cfbox/tui.hpp`:全屏终端应用抽象,vi/top/less 共用
- TUI 框架已在 Phase 4 实现 ✅,vi 直接复用
- 屏幕缓冲区管理、增量渲染
- 键盘事件映射(普通键 + 转义序列解析)
- 信号处理(SIGWINCH 终端大小变化)
Expand All @@ -197,36 +238,6 @@ src/applets/vi/

---

## Phase 5:进程管理 + Init 系统 + util-linux

**目标**:构建让 CFBox 适合作为完整 init 环境的系统级工具。

### Init 系统(完整)
- **inittab 解析器**:解析 `/etc/inittab`,支持运行级别、respawn、once 条目
- **运行级别管理**:sysinit, boot, single-user, multi-user
- **服务监控**:进程监控 + respawn 能力
- **关机/重启**:SIGTERM → 等待 → SIGKILL → sync → 卸载 → 重启
- **getty 集成**:在 TTY 上生成登录提示

### procps(解析 `/proc` 文件系统)
`ps`, `top`, `kill`, `free`, `uptime`, `pgrep`/`pkill`, `pidof`, `pmap`, `iostat`, `lsof`, `watch`, `sysctl`, `pstree`, `fuser`, `pwdx`

### util-linux
**存储/块设备**:`mount`/`umount`, `blkid`, `blockdev`, `dmesg`, `fdisk`, `mkfs`, `fsck`, `losetup`, `pivot_root`, `switch_root`, `swapon`/`swapoff`

**系统工具**:`hexdump`, `more`, `flock`, `getopt`, `cal`, `rev`, `setsid`, `nsenter`, `unshare`, `mdev`, `lspci`, `lsusb`, `hwclock`, `rtcwake`, `taskset`, `chrt`, `ionice`, `renice`, `last`, `mesg`, `wall`, `script`

### 基础设施
- **`/proc` 解析器** `include/cfbox/proc.hpp`:集中解析 /proc/meminfo, /proc/stat, /proc/[pid]/stat 等
- TUI 框架已在 Phase 4 实现,top/less 可直接复用

### 验证
- CFBox 作为 PID 1 在 QEMU 中启动,运行 inittab,生成 getty,处理关机
- `ps aux` 输出与 procps 格式匹配
- 容器测试:CFBox 替换 Alpine 容器中的 BusyBox,`docker run` 成功

---

## Phase 6:网络 + 登录管理 + 系统日志

**目标**:添加网络工具和用户/会话管理,使 CFBox 适用于网络启动系统和多用户环境。
Expand Down Expand Up @@ -297,7 +308,7 @@ src/applets/vi/
|------|------|---------|
| **Shell 复杂度** | 最高——5000+ 行代码 | 增量构建:先非交互 → 行编辑 → 作业控制,从第一天开始测试 POSIX shell 测试套件 |
| **AWK 复杂度** | 高——第二复杂组件 | 从 POSIX awk 子集开始,实现解释器而非编译器 |
| **vi 复杂度** | 高——终端处理微妙、独立 Phase 4 | 使用 Phase 3 的终端抽象 + 自建 TUI 框架,自动化按键注入测试,双缓冲 diff 驱动渲染 |
| **vi 复杂度** | 高——终端处理微妙、独立 Phase 5 | 使用 Phase 3 的终端抽象 + Phase 4 的 TUI 框架,自动化按键注入测试,双缓冲 diff 驱动渲染 |
| **二进制体积膨胀** | 中——200+ applet | Phase 0 的 CMake 配置允许裁剪,LTO 和死代码消除,每阶段监控体积 |
| **跨平台边界情况** | 中——ioctl、/proc 格式差异 | 平台特性抽象到 `include/cfbox/` 头文件,每阶段三平台测试 |
| **网络安全** | 中——wget/httpd 需要 TLS | 先做 HTTP-only,HTTPS 通过可选 mbedTLS 依赖,作为 CMake 选项 |
Expand Down
4 changes: 4 additions & 0 deletions cmake/Config.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ set(CFBOX_APPLETS
xargs
gzip gunzip diff cmp patch ed tar cpio ar unzip
awk
free uptime kill pidof ps pgrep sysctl
pwdx pstree pmap fuser iostat
watch top
dmesg hexdump more rev cal renice
)

foreach(applet IN LISTS CFBOX_APPLETS)
Expand Down
4 changes: 4 additions & 0 deletions cmake/compile/CompilerFlag.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ target_compile_options(cfbox_compiler_flags INTERFACE
$<$<CONFIG:Debug>:-fno-sanitize-recover=all>
)

target_link_options(cfbox_compiler_flags INTERFACE
$<$<CONFIG:Debug>:-fsanitize=address,undefined>
)

# ── Release-specific flags ────────────────────────────────────
if(CFBOX_OPTIMIZE_FOR_SIZE)
target_compile_options(cfbox_compiler_flags INTERFACE
Expand Down
21 changes: 21 additions & 0 deletions configs/qemu-inittab
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# CFBox /etc/inittab — QEMU aarch64 virt machine test
# Format: id:runlevels:action:process

# Note: /proc, /sys, /dev are mounted automatically by init's sysinit phase.
# (mount applet is not yet available, init does it internally)

# Boot test — verify applets work under init
::sysinit:/bin/echo "=== CFBox Init (inittab mode) ==="
::sysinit:/bin/uname -a
::sysinit:/bin/free -h
::sysinit:/bin/uptime
::sysinit:/bin/ps
::sysinit:/bin/echo "=== Inittab tests PASSED ==="

# Phase 3: Spawn shell on serial console (respawn if killed)
ttyAMA0::respawn:/bin/sh

# Signals
::ctrlaltdel:/bin/echo "Ctrl-Alt-Del pressed, rebooting..."
::shutdown:/bin/echo "Shutting down..."
::shutdown:/bin/sync
20 changes: 20 additions & 0 deletions include/cfbox/applet_config.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,23 @@
#cmakedefine01 CFBOX_ENABLE_AR
#cmakedefine01 CFBOX_ENABLE_UNZIP
#cmakedefine01 CFBOX_ENABLE_AWK
#cmakedefine01 CFBOX_ENABLE_FREE
#cmakedefine01 CFBOX_ENABLE_UPTIME
#cmakedefine01 CFBOX_ENABLE_KILL
#cmakedefine01 CFBOX_ENABLE_PIDOF
#cmakedefine01 CFBOX_ENABLE_PS
#cmakedefine01 CFBOX_ENABLE_PGREP
#cmakedefine01 CFBOX_ENABLE_SYSCTL
#cmakedefine01 CFBOX_ENABLE_PWDX
#cmakedefine01 CFBOX_ENABLE_PSTREE
#cmakedefine01 CFBOX_ENABLE_PMAP
#cmakedefine01 CFBOX_ENABLE_FUSER
#cmakedefine01 CFBOX_ENABLE_IOSTAT
#cmakedefine01 CFBOX_ENABLE_WATCH
#cmakedefine01 CFBOX_ENABLE_TOP
#cmakedefine01 CFBOX_ENABLE_DMESG
#cmakedefine01 CFBOX_ENABLE_HEXDUMP
#cmakedefine01 CFBOX_ENABLE_MORE
#cmakedefine01 CFBOX_ENABLE_REV
#cmakedefine01 CFBOX_ENABLE_CAL
#cmakedefine01 CFBOX_ENABLE_RENICE
121 changes: 121 additions & 0 deletions include/cfbox/applets.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,66 @@ extern auto unzip_main(int argc, char* argv[]) -> int;
#if CFBOX_ENABLE_AWK
extern auto awk_main(int argc, char* argv[]) -> int;
#endif
#if CFBOX_ENABLE_FREE
extern auto free_main(int argc, char* argv[]) -> int;
#endif
#if CFBOX_ENABLE_UPTIME
extern auto uptime_main(int argc, char* argv[]) -> int;
#endif
#if CFBOX_ENABLE_KILL
extern auto kill_main(int argc, char* argv[]) -> int;
#endif
#if CFBOX_ENABLE_PIDOF
extern auto pidof_main(int argc, char* argv[]) -> int;
#endif
#if CFBOX_ENABLE_PS
extern auto ps_main(int argc, char* argv[]) -> int;
#endif
#if CFBOX_ENABLE_PGREP
extern auto pgrep_main(int argc, char* argv[]) -> int;
#endif
#if CFBOX_ENABLE_SYSCTL
extern auto sysctl_main(int argc, char* argv[]) -> int;
#endif
#if CFBOX_ENABLE_PWDX
extern auto pwdx_main(int argc, char* argv[]) -> int;
#endif
#if CFBOX_ENABLE_PSTREE
extern auto pstree_main(int argc, char* argv[]) -> int;
#endif
#if CFBOX_ENABLE_PMAP
extern auto pmap_main(int argc, char* argv[]) -> int;
#endif
#if CFBOX_ENABLE_FUSER
extern auto fuser_main(int argc, char* argv[]) -> int;
#endif
#if CFBOX_ENABLE_IOSTAT
extern auto iostat_main(int argc, char* argv[]) -> int;
#endif
#if CFBOX_ENABLE_WATCH
extern auto watch_main(int argc, char* argv[]) -> int;
#endif
#if CFBOX_ENABLE_TOP
extern auto top_main(int argc, char* argv[]) -> int;
#endif
#if CFBOX_ENABLE_DMESG
extern auto dmesg_main(int argc, char* argv[]) -> int;
#endif
#if CFBOX_ENABLE_HEXDUMP
extern auto hexdump_main(int argc, char* argv[]) -> int;
#endif
#if CFBOX_ENABLE_MORE
extern auto more_main(int argc, char* argv[]) -> int;
#endif
#if CFBOX_ENABLE_REV
extern auto rev_main(int argc, char* argv[]) -> int;
#endif
#if CFBOX_ENABLE_CAL
extern auto cal_main(int argc, char* argv[]) -> int;
#endif
#if CFBOX_ENABLE_RENICE
extern auto renice_main(int argc, char* argv[]) -> int;
#endif

// registry — one line per applet, conditionally compiled
constexpr auto APPLET_REGISTRY = std::to_array<cfbox::applet::AppEntry>({
Expand Down Expand Up @@ -542,4 +602,65 @@ constexpr auto APPLET_REGISTRY = std::to_array<cfbox::applet::AppEntry>({
#if CFBOX_ENABLE_AWK
{"awk", awk_main, "pattern-directed scanning and processing language"},
#endif
#if CFBOX_ENABLE_FREE
{"free", free_main, "display amount of free and used memory"},
#endif
#if CFBOX_ENABLE_UPTIME
{"uptime", uptime_main, "tell how long the system has been running"},
#endif
#if CFBOX_ENABLE_KILL
{"kill", kill_main, "send a signal to a process"},
#endif
#if CFBOX_ENABLE_PIDOF
{"pidof", pidof_main, "find the process ID of a running program"},
#endif
#if CFBOX_ENABLE_PS
{"ps", ps_main, "report a snapshot of current processes"},
#endif
#if CFBOX_ENABLE_PGREP
{"pgrep", pgrep_main, "look up processes based on name"},
{"pkill", pgrep_main, "signal processes based on name"},
#endif
#if CFBOX_ENABLE_SYSCTL
{"sysctl", sysctl_main, "configure kernel parameters at runtime"},
#endif
#if CFBOX_ENABLE_PWDX
{"pwdx", pwdx_main, "print working directory of a process"},
#endif
#if CFBOX_ENABLE_PSTREE
{"pstree", pstree_main, "display a tree of processes"},
#endif
#if CFBOX_ENABLE_PMAP
{"pmap", pmap_main, "display memory map of a process"},
#endif
#if CFBOX_ENABLE_FUSER
{"fuser", fuser_main, "identify processes using files or sockets"},
#endif
#if CFBOX_ENABLE_IOSTAT
{"iostat", iostat_main, "report CPU and I/O statistics"},
#endif
#if CFBOX_ENABLE_WATCH
{"watch", watch_main, "execute a program periodically"},
#endif
#if CFBOX_ENABLE_TOP
{"top", top_main, "display Linux processes"},
#endif
#if CFBOX_ENABLE_DMESG
{"dmesg", dmesg_main, "print kernel ring buffer"},
#endif
#if CFBOX_ENABLE_HEXDUMP
{"hexdump", hexdump_main, "display file contents in hexadecimal"},
#endif
#if CFBOX_ENABLE_MORE
{"more", more_main, "file perusal filter for crt viewing"},
#endif
#if CFBOX_ENABLE_REV
{"rev", rev_main, "reverse lines characterwise"},
#endif
#if CFBOX_ENABLE_CAL
{"cal", cal_main, "display a calendar"},
#endif
#if CFBOX_ENABLE_RENICE
{"renice", renice_main, "alter priority of running processes"},
#endif
});
Loading
Loading