Repository navigation
系统地支持环境变量(环境配置文件)的读、写、删 - #402
Open
Mikachu2333 wants to merge 19 commits into
Open
Mikachu2333 wants to merge 19 commits into
Mikachu2333 wants to merge 19 commits into
Conversation
|
Hi @Mikachu2333, ❤️ 感谢你的贡献!你的 PR 当前基于 |
Collaborator
Author
|
等标记成ready for review再来看就行,当前还有一堆小问题没调好 |
Mikachu2333
marked this pull request as ready for review
October 28, 2026 14:57
Collaborator
Author
|
READY |
Collaborator
Author
|
发现本branch还没有办法把 #393 这种问题也提供一个通用的工具,感觉还得再开个branch把那边一类按此思路处理,给出一个通用的替换追加删除的类 |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
问题描述
方案与实现
实在太多太多了,参见下文详情,经个人核实,暂未发现模型发现的漏洞有误
Plan.md
# 环境变量管理模块化 — 实施计划(定稿)0. 目标 / 非目标
目标
src/framework/env.c一处可复用实现,recipe 贡献者不再手写平台与 shell 方言分支。rustup、Pub、Flutter、nvm、Homebrew)全部只chsrc_append_to_file,重复chsrc set无限堆积脏行。setx NAME "<url>"字符串拼接,改用 Win32 注册表宽字符 API,引号注入面归零;$、`、引号、反斜杠与换行符。chsrc get(chsrc_get_env)优先报出持久化值;持久化配置中没有该项时回退为当前终端继承的值(不额外提示),仅当两者同时存在且不一致时才提示临时值差异;多文件冲突或复杂动态语法无法唯一定位时拒绝盲猜并告知原因。lib/xy.h中已识别的底层函数缺陷与平台宏混用问题(见第 1 节)。非目标
PATH式"列表追加"语义(当前 0 个 recipe 需要)。ProjectScope)环境变量的实际落地。block.c、ProgStatus.CurrentDish/CurrentSource,不在 POSIX 配置文件中写入# Ver2 CHSRC BLOCK ...注释包裹头尾,也不主动清扫历史遗留的# ------ chsrc BLOCK BEGIN/ENDIN ------等注释痕迹(仅折叠同文件内重复的同名变量赋值行,并对config.fish中阻塞生效的 5 个迁移 dish 旧变量赋值行做一次性精确清理)。Arch-Linux.c那类非环境变量的"配置文件换源"。1. 需提前修复的既有错误 / 不完善函数清单(Phase P0)
以下既有问题直接影响本模块的正确性、安全性或跨平台一致性,按职责拆分为独立前置 commit 先行修复:
src/framework/OS.c:280-299chsrc_ensure_root ()getenv ("$EUID")多写了$,恒为NULL,导致每次必 forkid -u。2. 严重提权误判漏洞:
xy_str2int (buf)在buf == NULL或非数字时返回0(见lib/xy.h:505),一旦id -u执行失败(如 Windows 或精简容器环境),0 != xy_str2int(buf)为假,直接误判当前用户是 root!3. 缺少非中止的权限探测函数,且 Windows 无管理员组判定与对应提权文案。
bool chsrc_is_root (void):POSIX 下直接调<unistd.h>的geteuid () == 0(零 fork、无字符串解析歧义);#ifdef XY_Build_On_Windows下用AllocateAndInitializeSid+CheckTokenMembership检测DOMAIN_ALIAS_RID_ADMINS。2.
chsrc_ensure_root ()改为调用chsrc_is_root (),失败时按平台输出双语指引(Windows 提示以管理员身份运行终端,POSIX 提示sudo/切换root)并exit (Exit_UserCause)。src/framework/OS.c:748-868chsrc_overwrite_file ()chsrc_append_to_file ()chsrc_prepend_to_file ()chsrc_overwrite_file与chsrc_append_to_file执行fwrite (str, len, 1, f)后断言ret == 1;按 C11 标准,当len == 0(如删掉文件中唯一一条环境变量后覆写空串)时fwrite返回0,误触发"写入文件失败"并exit (Exit_UserCause)。2.
chsrc_append_to_file在fwrite失败分支漏掉了fclose (f)。3.
chsrc_prepend_to_file未调用chsrc_ensure_dir、未校验fwrite返回值、报错硬编码中文"文件打开失败"。len > 0时才执行fwrite与ret != 1校验(len == 0时打开"w"已完成截断清空);补齐fclose (f)、chsrc_ensure_dir及中英双语错误信息。src/framework/OS.c:873-948chsrc_backup ()path先做xy_normalize_path:ComboBackedUpPaths去重栈直接比较原始字符串("~/.bashrc"与展开后绝对路径可能不一致);Windows 分支copy /Y <path> <path>.bak遇到~或正斜杠/会直接失败;路径含空格时 shell 命令未加引号保护。path先通过xy_normalize_path规范化用于去重与实际文件拷贝(日志仍展示直观路径),并在 shell 拷贝命令中对路径加引号保护。lib/xy.h:111,1405,1553src/framework/OS.c:407,495,957,1012XY_Build_On_Windows与xy.on_windows用法混乱且存在逻辑断层:1.
lib/xy.h:1553_xy_detect_os()通过探测%SystemDrive%\Windows在运行期置xy.on_windows = true;f,进而使lib/xy.h:1405xy_dir_exist()落入空#ifdef分支恒返回false。2.
OS.c:957,1012写了#if XY_Build_On_Windows(非 Windows 下宏未定义),而OS.c:407写#ifdef XY_Build_On_Windows。3.
OS.c:495在#ifdef XY_Build_On_Windows块外用运行期if (xy.on_windows && !tmpfilepath)触发xy_unreached()。lib/xy.h与src/framework/OS.c:- 在
lib/xy.h中使_xy_detect_os()的 Windows 判定严格受#ifdef XY_Build_On_Windows约束(Cygwin/MSYS POSIX 运行时归入 Unix 分支),消除xy.on_windows与XY_Build_On_Windows的分裂,修复xy_dir_exist()。- 编译期
#ifdef XY_Build_On_Windows:全仓统一用#ifdef(禁用#if),且仅用于包裹 Win32 SDK 专有类型与 API 调用。- 运行期
if (xy.on_windows):所有纯 C 跨平台分支逻辑一律用if (xy.on_windows)。src/framework/struct.h:140src/framework/chef.c:393src/framework/source.c:797src/framework/waiter.c:250,882waiter_handle_Reset_Source ()漏调chsrc_check_scope_capability (dish),导致chsrc reset -scope=project <dish>绕过框架拦截。2. 新增
ScopeCap_Able_But_Just_Docs需同步更新struct.h、chef_set_default_scope ()、chsrc_check_scope_capability ()、cli_print_dish_features ()。3. Scope 检查与
ls状态提示硬编码中文,不支持-en。waiter_handle_Reset_Source ()的 scope 校验;合入ScopeCap_Able_But_Just_Docs框架支持(校验与默认作用域均放行,ls显示黄色HalfYesMark,本分支暂不绑定具体 dish);补齐中英双语文案。Makefile:61-67,168-170,240,245justfile:59-88OS.c/xy.h已调用kernel32/shell32API,但构建脚本依赖编译器隐式链接。2.
Makefile在 Windows MSYS2 上交叉编译 Android(CROSS_BUILD_WINDOWS_FOR_ANDROID=1)时On-Windows仍为1,无条件加 Windows 库会打挂 Android Release CI。3. MinGW 单遍链接器要求
-l*位于源文件与-static之后。Makefile(加ifneq ($(CROSS_BUILD_WINDOWS_FOR_ANDROID), 1)守卫)与justfile中新增尾部链接库变量LDLIBS_win = -ladvapi32 -lkernel32 -luser32 -lshell32,统一置于编译命令行末端(.c文件之后)。src/chsrc-main.c:171,231chsrc set -scope末尾缺参时argv[i+1]为NULL,传入xy_strcat导致空指针解引用崩溃;且消费argv[i+1]后未执行i++。2. 第 231–232 行判断
-version/--version误写xy_streql (command, ...)而非argv[i],导致chsrc -en --version报未知选项。i + 1 <= argc边界检查、i++及argv[i]修正。2. 已锁定决策汇总
block.c与注释头;内聚行级精确键值编辑(C1)block.c、不加ProgStatus.CurrentDish/CurrentSource、不写# Ver2 CHSRC BLOCK ...注释头尾。env.c内部以static原语直接按目标方言精确匹配同名环境变量赋值行:已存在则原位改写第 1 条并剔除同文件内后续重复的同名赋值行;不存在则追加;值为NULL则删除全部匹配赋值行;若匹配行含动态展开/多变量同行等复杂语法则拒绝改写并报错告知文件与行号。用户原有注释及历史# ------ chsrc BLOCK BEGIN/ENDIN ------注释痕迹一律保留不碰。REG_SZRegOpenKeyExW/RegQueryValueExW/RegSetValueExW/RegDeleteValueW/RegCloseKey;写入类型固定为REG_SZ(读取时兼容既有REG_SZ与REG_EXPAND_SZ),在env.c内提供staticUTF-8 ↔ UTF-16LE 转换(MultiByteToWideChar/WideCharToMultiByte)。Makefile(排除CROSS_BUILD_WINDOWS_FOR_ANDROID=1)与justfile显式后置链接-ladvapi32 -lkernel32 -luser32 -lshell32。comm(Linux/Android 读/proc/<ppid>/comm,macOS/BSD 走ps -p <ppid> -o comm=)→$SHELL。- 无法识别当前 shell 时(C3=B):
set与get均拒绝盲目执行,报错说明无法确认当前 shell 并给出手工添加指引。- 写入规则:已知 rc 文件仅在已存在时写入;
~/.profile例外(bash/zsh 下不存在则创建兜底登录环境);当前 shell 为 fish 时目标为~/.config/fish/conf.d/chsrc.fish(不存在则创建)。- 检查集提醒:其余已知 shell 配置文件若检测到同名变量,用
chsrc_note2双语提示,不跨 shell 清理。config.fish加载顺序陷阱一次性清理conf.d/*.fish后加载config.fish。对迁移的 5 个 dish 涉及的已知变量名,写入conf.d/chsrc.fish时若检测到~/.config/fish/config.fish中存在非注释且语法可精确判定的set -x/set -gx同名行,先chsrc_backup再精确删除该行。SystemScope+ 前置权限自检/etc/environment,Windows 写HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment。执行前先调chsrc_is_root ()自检权限;不足则不做任何修改、不建备份,直接打印对应平台的提权/手工修改双语指引并exit (Exit_UserCause)。ImplementationDefinedScope→UserScopeUserScope。ScopeCap_Able_But_Just_Docs,本分支暂置空chef_set_default_scope放行、chsrc_check_scope_capability放行及ls黄色HalfYesMark双语展示;本分支不修改具体 dish 使用该枚举。waiter_handle_Reset_Source补齐 scope 校验,env.c内部保留ProjectScope防御性拦截。setenv/_putenv。当所有目标持久化值已等于新值时,不备份、不写盘、不广播、不打印重启提示,返回Env_Unchanged;仅当实际发生写入/删除(Env_OK)时,在单次 API 调用末尾自动输出 1 次中英双语"请重启终端使环境变量生效"提示。chsrc_get_env优先读持久化值、缺失回退getenv,不确定时拒绝执行void chsrc_get_env (const char *var1, ...)变参签名,不做批量gets。按精确匹配定位持久化来源:能唯一确认值时打印NAME=persisted_value;持久化配置中没有该项时以当前进程getenv(NAME)为准(会话中也没有则输出NAME=),且不做额外提示,以免在持久化配置尚未建立时产生噪音;仅当持久化值与会话值同时存在且不一致时,用chsrc_note2提示临时值差异。若无法确认当前 shell、相关配置文件间存在不同值冲突或行含复杂动态语法,放弃执行并报错告知具体原因与文件路径。value == NULL即删除;单变量与多变量增量一致unset函数,chsrc_set_env (name, NULL)(或chsrc_set_env_block中某项值为NULL)即删除该变量。POSIX 与 Windows 均按变量名独立增量合并/删除,同一 dish 内即使分多次调用chsrc_set_env也不会互相抹除其他变量。export NAME="value"(拒绝含"、\、$、`、\r、\n)- fish
conf.d/chsrc.fish:set -x NAME "value"(不用-Ux;拒绝字符同上)-
/etc/environment:NAME=value(无export、无引号;额外拒绝空白符、#、')- Windows 注册表:原值存入
REG_SZ(不加引号;拒绝\r、\n)%TEMP%\chsrc-<PID>\的.reg%TEMP%\chsrc-<PID>\,写/删注册表前将旧状态导出为标准 UTF-16LE + BOM 格式的.reg文件(覆盖 HKCU 与 HKLM);写入中途出错自动回滚并报错;.reg创建失败须明确告知磁盘/权限/路径原因并中止。Dry-run 模式下不写注册表也不生成.reg。reset模式env.c不读chsrc_in_reset_mode ();resetsrc设为上游源还是传NULL删除由各 recipe 自行决定。WM_SETTINGCHANGEEnv_OK)后调用SendMessageTimeoutW (HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 1500, NULL),超时或失败静默忽略。EnvOp_t可单测,公开 API 遇错即报错退出EnvOp_t全部状态供test/fw.c覆盖测试;公开的chsrc_set_env/chsrc_set_env_block在非Env_OK/Env_Unchanged时统一打印双语错误并exit,防止 recipe 漏检返回值导致打印假成功结论。rustup、Pub、Flutter、nvm、Homebrew:统一开放UserScope与SystemScope(ProjectScope为Unable);Homebrew的getsrc迁入chsrc_get_env,删除Homebrew/rawstr4c.{h,md},用hp_remove_trailing_slash消除 URL 双斜杠;Windows 下拦截不支持的Homebrew与nvm;更新nvm的 Fish 备注并开启rustup英文支持。3. 模块详细设计
3.1 API 设计(
src/framework/env.c)3.2 平台 × Scope × 目标映射
#ifdef XY_Build_On_Windows)UserScopeHKCU\EnvironmentSystemScopeHKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment/etc/environmentProjectScopeScopeCap_Unable)ScopeCap_Unable)ImplementationDefinedScopeUserScopeUserScopePOSIX
UserScope写入集与检查集:chsrc_note2提醒)bash~/.bashrc(存在才写)、~/.bash_profile(存在才写)、~/.profile(不存在则创建)~/.zshrc、~/.zprofile、~/.config/fish/conf.d/chsrc.fish、~/.config/fish/config.fishzsh~/.zshrc(存在才写)、~/.zprofile(存在才写)、~/.profile(不存在则创建)~/.bashrc、~/.bash_profile、~/.config/fish/conf.d/chsrc.fish、~/.config/fish/config.fishfish~/.config/fish/conf.d/chsrc.fish(不存在则创建)+ 一次性精确清理
~/.config/fish/config.fish中 5 个迁移 dish 的旧同名行~/.bashrc、~/.zshrc、~/.profile(及非 5 dish 变量在config.fish中的同名定义)dash/tcsh/nu等)Env_AmbiguousTarget),告知无法确认当前 shell 并给出手工添加指引3.3 POSIX 行级精确匹配、复杂行保护与改写规则
#开头的注释行;严格校验变量名边界,杜绝ABC误命中ABCD:^[ \t]*(export[ \t]+)?NAME=(.*)$(写出格式固定为export NAME="value"):export A=1 B=2)、未闭合引号、命令替换/变量展开(含$或`)或非注释尾部管道/分号链接命令,判定为复杂动态行(Env_AmbiguousTarget),拒绝自动覆写并报错指明文件与行号;"..."、单引号'...'或无空白无展开裸值(如历史nvm写出的export NVM_NODEJS_ORG_MIRROR=https://...),行尾允许紧跟# ...纯注释。^[ \t]*set([ \t]+-[A-Za-z]+)*[ \t]+NAME([ \t]+.*)?$(写出格式固定为set -x NAME "value"):-x/-gx/-xg/-g -x/-x -g,不含-Uuniversal 或-eerase 等冲突标志)且值部分为单个安全字面量("..."、'...'或无空白无$裸值)时视为安全可管行;否则判定为Env_AmbiguousTarget报错指明文件与行号。/etc/environment:识别^[ \t]*(export[ \t]+)?NAME=(.*)$(写出格式固定为无export、无引号的NAME=value);含$、`、未配对引号或同行多词时判定为Env_AmbiguousTarget。NAME安全可管行 → 第 1 处原位替换为标准新行,同文件后续重复的NAME赋值行直接剔除;NAME且value != NULL→ 若原非空文件不以\n结尾先补\n,再追加标准新行;value == NULL→ 删除该文件内所有匹配NAME的安全可管行。chsrc_backup ()与写入;所有目标文件均无变化时返回Env_Unchanged。3.4 Windows 注册表与
.reg备份回滚细则GetTempPathW下定位chsrc-<GetCurrentProcessId()>子目录(不存在则创建),按操作序号生成env-hkcu-<seq>.reg或env-hklm-<seq>.reg(combo dish 同一根键去重只备份一次原始状态)。.reg文件格式:写入 UTF-16LE BOM(0xFF 0xFE)及Windows Registry Editor Version 5.00\r\n\r\n[<KeyPath>]\r\n:REG_SZ)→ 按.reg转义规则(\→\\,"→\")写出"NAME"="old_value";REG_EXPAND_SZ等其他类型)→ 写出"NAME"=hex(2):...精确字节表示;"NAME"=-。RegSetValueExW/RegDeleteValueW过程中一旦某一步失败,立即将内存保存的各变量原状态写回注册表恢复现场,同时输出.reg备份路径供核查,再报错退出。4. 实施阶段与 Commit 切分(单 PR 线性提交)
Phase P0:前置基础设施修复(独立先行 commits)
修复 chsrc_ensure_root 的 $EUID 与误判 root 缺陷并新增 chsrc_is_root(F1)修复文件写入族函数空串写入失败、句柄泄漏与双语提示(F2)改进 chsrc_backup 路径规范化与空格引号保护(F3)统一 XY_Build_On_Windows 与 xy.on_windows 的平台判定与用法(F4,含lib/xy.h与OS.c)修复 CLI -scope 缺参崩溃与 --version 选项解析缺陷(F7)补齐 reset 作用域校验并引入 ScopeCap_Able_But_Just_Docs 枚举(F5 + D10/D28)显式后置链接 Windows 导入库并排除 Android 交叉编译(F6)Phase P1 & P2:环境变量核心模块(
src/framework/env.c)新增 framework/env.c 实现 POSIX 环境变量精确读写与持久化查看(P1)实现 env.c 的 Windows 注册表后端、.reg 备份回滚与设置变更广播(P2)Phase P3:统一迁移 5 个 Recipe(清除旧逻辑)
迁移 rustup、Pub、Flutter、nvm、Homebrew 至 env 模块并移除旧逻辑(P3)Phase P4:单元测试、CLI 回归测试与文档同步
补充 env 模块单元测试、CLI 幂等回归测试与开发文档(P4)