1024手写Shell:拼写建议、信号处理与执行边界

发布时间:2026/10/25 2:37:58

1024手写Shell:拼写建议、信号处理与执行边界 终端里把grep敲成gerp程序可以猜一个相似单词却不能据此断定用户想做什么。这个差别很小也很容易被“智能Shell”四个字盖过去。这次只做一个窄原型按空白拆参数启动一个前台子进程等待它退出找不到程序时给出静态词典中的拼写建议。它不支持管道、引号、变量展开、重定向和后台作业。遇到这些语法直接拒绝避免把半套解析器交给用户误用。先把CtrlC的归属讲清楚在交互终端中CtrlC通常向前台进程组发送SIGINT。本原型不实现完整作业控制父Shell与命令仍在同一前台组父进程忽略SIGINT子进程在execvp前恢复默认处置。子进程还显式清空信号屏蔽字。这里有两个不同动作sigaction设置处置方式sigprocmask设置哪些信号暂时不递送。SIG_DFL是默认处置不是“默认屏蔽字”。忽略信号的处置可能跨exec保留因此不能指望启动新程序后自动恢复。Linux signal(7)图中waitpid对EINTR重试是一般防御如果某个信号被忽略它本身并不必然造成EINTR。完整Shell还需要处理进程组、终端控制权、停止与继续这里没有实现。一个可以编译的原型保存成minish.c#define _POSIX_C_SOURCE 200809L #include errno.h #include signal.h #include stdio.h #include stdlib.h #include string.h #include sys/types.h #include sys/wait.h #include unistd.h static int min3(int a, int b, int c) { int m a b ? a : b; return m c ? m : c; } /* Optimal string alignment distance: not unrestricted Damerau-Levenshtein. */ static int osa(const char *a, const char *b) { size_t n strlen(a), m strlen(b); if (n 63 || m 63) return 64; int d[64][64]; for (size_t i 0; i n; i) d[i][0] (int)i; for (size_t j 0; j m; j) d[0][j] (int)j; for (size_t i 1; i n; i) { for (size_t j 1; j m; j) { d[i][j] min3(d[i-1][j] 1, d[i][j-1] 1, d[i-1][j-1] (a[i-1] ! b[j-1])); if (i 1 j 1 a[i-1] b[j-2] a[i-2] b[j-1] d[i-2][j-2] 1 d[i][j]) d[i][j] d[i-2][j-2] 1; } } return d[n][m]; } static void suggest(const char *cmd) { const char *dict[] {grep, cat, ls, pwd, NULL}; for (size_t i 0; dict[i]; i) if (osa(cmd, dict[i]) 1) fprintf(stderr, suggest only: %s\n, dict[i]); } static int disposition(int sig, void (*handler)(int)) { struct sigaction sa; memset(sa, 0, sizeof sa); sa.sa_handler handler; sigemptyset(sa.sa_mask); return sigaction(sig, sa, NULL); } int main(void) { if (disposition(SIGINT, SIG_IGN) || disposition(SIGQUIT, SIG_IGN)) return 1; char line[4096]; int last 0; for (;;) { if (isatty(STDIN_FILENO)) { fputs(mini , stdout); fflush(stdout); } if (!fgets(line, sizeof line, stdin)) break; if (!strchr(line, \n) !feof(stdin)) { int ch; while ((ch getchar()) ! \n ch ! EOF) {} fputs(line too long\n, stderr); last 2; continue; } if (strpbrk(line, |;$\\\())) { fputs(unsupported syntax\n, stderr); last 2; continue; } char *argv[64], *save NULL; size_t n 0; int overflow 0; for (char *t strtok_r(line, \t\r\n, save); t; t strtok_r(NULL, \t\r\n, save)) { if (n 63) { overflow 1; break; } argv[n] t; } if (overflow) { fputs(too many arguments\n, stderr); last 2; continue; } if (!n) continue; argv[n] NULL; if (!strcmp(argv[0], exit)) { if (n ! 1) { fputs(exit takes no arguments\n, stderr); last 2; continue; } return last; } pid_t pid fork(); if (pid 0) { perror(fork); last 1; continue; } if (!pid) { sigset_t empty; sigemptyset(empty); if (disposition(SIGINT, SIG_DFL) || disposition(SIGQUIT, SIG_DFL) || sigprocmask(SIG_SETMASK, empty, NULL)) _exit(126); execvp(argv[0], argv); int e errno; if (e ENOENT) suggest(argv[0]); fprintf(stderr, %s: %s\n, argv[0], strerror(e)); _exit(e ENOENT ? 127 : 126); } int st; pid_t w; do { w waitpid(pid, st, 0); } while (w 0 errno EINTR); if (w 0) { perror(waitpid); last 1; } else if (WIFEXITED(st)) last WEXITSTATUS(st); else if (WIFSIGNALED(st)) last 128 WTERMSIG(st); else last 1; } return last; }编译命令cc -stdc11 -Wall -Wextra -Werror -O2 minish.c -o minish ./minish纠错函数使用的是optimal string alignment distanceOSA支持受限的相邻换位。它不是完整的Damerau–Levenshtein算法更不是语义理解。距离近的命令可能完全不同所以程序只向stderr输出候选不会执行候选。fork后的地址空间、文件描述符和信号存在明确继承规则多线程程序在子进程执行exec前能安全做的操作更受限制。此例是单线程教学程序不能直接塞入已有多线程终端宿主。fork(2)用失败输入检查边界示例在macOS arm64、Apple Clang 21.0.0上以以上严格编译选项通过。运行记录包括输入或动作观察到的结果true、false、exit最后返回1gerp、exitstderr给出grep建议返回127echo a|cat拒绝未支持语法返回2超长行、过多参数明确拒绝返回2PATH中不可执行的测试文件返回126没有拼写建议子进程执行sleep时向测试进程组发SIGINT子进程终止父进程继续读exit最终返回130这些是本机用户态结果不是Linux发行版兼容性证明。SIGINT测试使用独立测试进程组没有给日常终端或其他进程发信号。还要小心ENOENT它也可能来自可执行文件依赖的解释器或加载器缺失不总意味着命令名字拼错。建议前缀因此写成suggest only。静态词典也可能建议一个本机没有安装的程序若未来扫描PATH缓存更新、权限与同名程序选择都得重新设计。这个原型的价值在于能说清自己做了什么启动命令、等待退出、展示候选。它没有“自愈成功”的承诺也不应该获得替用户执行修正命令的默认权力。2026年10月9日Anthropic披露的内部评测越界案例可以作为授权边界的背景不能拿来证明本程序已经安全。原始报告资料于2026年10月23日核对。封面和流程图为教学示意图中的终端不是实测截图。
延伸阅读

更多相关文章

2026/10/25 2:32:58

Hadoop核心架构解析:HDFS、YARN与MapReduce协同原理

1. Hadoop核心架构解析:三驾马车如何协同工作?在大数据领域摸爬滚打多年,我见过太多初学者面对Hadoop时一脸茫然的样子。这个2006年诞生的分布式系统框架,如今已成为企业级数据处理的标配工具。但很多人对它的理解停留在"Had…

2026/10/25 3:38:04

impeccable质量标准:从主观感知到可测可验的工程实践

1. 项目概述:当“impeccable”不再只是词典里的形容词最近在多个技术社区、设计论坛和内容创作小组里,频繁看到一个词被反复拎出来讨论——impeccable。它不是新发布的工具名,不是某个开源项目的代号,甚至不是缩写或黑话。它就静静…

2026/10/25 3:38:04

警惕AI领域虚假模型信息:如何识别与验证技术新闻

我注意到输入内容中存在严重信息缺失:项目标题提及“Google 发布图像模型 Nano Banana 2.1”,但经核实,Google 官方从未发布、命名或开源任何名为 “Nano Banana” 或 “Nano Banana 2.1” 的图像生成模型;该名称在 Google Resear…

2026/10/25 3:38:04

5个音色资源站整理与选型指南:方言、中英文、多风格全覆盖

1. 音色资源站的整理逻辑与选型思路做音频内容这行十来年,我电脑里存过的音色包少说也有几百个G。早期做播客剪辑、后来接商业配音、再到现在帮一些团队做短视频口播,绕不开的一个环节就是找音色。很多人第一反应是去搜“音色包下载”,结果要…

2026/10/25 3:38:04

GPU加速超大规模物流优化:亿级变量决策求解实战

1. 项目概述:当物流调度问题突破“百万变量”天花板你有没有算过,一个中等规模的城市配送网络,每天要处理多少个决策点?不是订单数,而是背后真正需要求解的变量总数——比如某辆车在某个时间点是否经过某条路、是否服务…

2026/10/25 3:38:04

路径与流量协同演化:交通建模的神经反射弧重构

1. 项目概述:这不是在拟合路径,而是在重建交通系统的“神经反射弧”“Co-Evolving Paths and Flows via Path-Flow Alignment”——这个标题乍看像一篇纯理论论文,但如果你在城市交通建模、物流网络优化或智能导航系统开发一线干过三年以上&a…

2026/10/25 3:33:04

Claude对话功能的本质是状态化会话工程

1. 这不是“调用API”那么简单:Claude对话功能的本质是状态化会话工程很多人看到“Claude对话功能”第一反应是:“不就是发个HTTP请求,把用户输入塞进messages数组,再把response.text取出来显示吗?”——我去年在某跨平…

2026/10/25 0:02:22

全国计算机二级C语言真题PDF高效刷题指南

简介:这份PDF是全国计算机二级C语言考试的试题与答案解析,专为备考二级C语言的考生准备。内容涵盖C语言特点与设计理念、程序基本组成单位、main函数执行流程、函数嵌套调用规则、标识符命名规范、整型实型字符型数据类型、八进制十六进制数合法形式、运…

2026/10/25 0:02:23

requests+BeautifulSoup:爬虫抓取h1标题的入门实战指南

简介:一份以实战为导向的Python爬虫入门资源,面向具备基本编程基础、希望快速掌握网络数据抓取的初学者,可解决从零编写简单爬虫的常见困惑。实例以requests库发送HTTP请求、BeautifulSoup解析HTML文档,完整演示从网页中提取 标题…

2026/10/25 0:02:23

递推最小二乘参数辨识MATLAB编程:二阶系统与渐消记忆实现

简介:这是一篇面向控制系统、信号处理与机器学习等领域学习者的最小二乘参数辨识程序说明文档。资源共包含一个docx格式文档,压缩包大小七十八KB,内容围绕递推最小二乘算法和渐消记忆最小二乘算法展开:先构造一个极点位于单位圆内…

2026/10/25 0:02:22

全国计算机二级C语言真题PDF高效刷题指南

简介:这份PDF是全国计算机二级C语言考试的试题与答案解析,专为备考二级C语言的考生准备。内容涵盖C语言特点与设计理念、程序基本组成单位、main函数执行流程、函数嵌套调用规则、标识符命名规范、整型实型字符型数据类型、八进制十六进制数合法形式、运…

2026/10/25 0:02:23

requests+BeautifulSoup:爬虫抓取h1标题的入门实战指南

简介:一份以实战为导向的Python爬虫入门资源,面向具备基本编程基础、希望快速掌握网络数据抓取的初学者,可解决从零编写简单爬虫的常见困惑。实例以requests库发送HTTP请求、BeautifulSoup解析HTML文档,完整演示从网页中提取 标题…

2026/10/25 0:02:23

递推最小二乘参数辨识MATLAB编程:二阶系统与渐消记忆实现

简介:这是一篇面向控制系统、信号处理与机器学习等领域学习者的最小二乘参数辨识程序说明文档。资源共包含一个docx格式文档,压缩包大小七十八KB,内容围绕递推最小二乘算法和渐消记忆最小二乘算法展开:先构造一个极点位于单位圆内…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑