向busybox中添加自己的applet
关键词:buysbox、applet等。
busybox常用于嵌入式环境,集成中断Linux命令和工具。这些工具简单高效。
下面从如下方面了解:
- 这些命令是一个软链接到busybox,那么是如何从软连接到busybox再到执行相应的功能的?
- 如何添加自己的applet命令,进而扩展busybox?
- 以及一个applet是如何嵌入到busybox环境的。
1. 如何从软链接到busybox的applet调用?
在busybox环境中,调用命令比如ls,其实是指向/bin/ls -> busybox的。
那么buysbox又是如何将这个软链接对应的实际功能的呢?
int main(int argc UNUSED_PARAM, char **argv)
{
...
#if defined(SINGLE_APPLET_MAIN)
...
#else lbb_prepare("busybox" IF_FEATURE_INDIVIDUAL(, argv));
# if !ENABLE_BUSYBOX
if (argv[] && is_prefixed_with(bb_basename(argv[]), "busybox"))
argv++;
# endif
applet_name = argv[];
if (applet_name[] == '-')
applet_name++;
applet_name = bb_basename(applet_name);
parse_config_file(); /* ...maybe, if FEATURE_SUID_CONFIG */run_applet_and_exit(applet_name, argv);
#endif
} static NORETURN void run_applet_and_exit(const char *name, char **argv)
{
# if ENABLE_BUSYBOX
if (is_prefixed_with(name, "busybox"))
exit(busybox_main(argv));--------------------------------显示busybox帮助信息、applet列表等。
# endif
# if NUM_APPLETS >
/* find_applet_by_name() search is more expensive, so goes second */
{
int applet = find_applet_by_name(name);------------------根据applet的name找到其在applet_main[]中的序号。
if (applet >= )
run_applet_no_and_exit(applet, name, argv);
}
# endif
...
} static int busybox_main(char **argv)
{
if (!argv[]) {-----------------------------------------------只有busybox情况下,显示帮助信息。
/* Called without arguments */
...
} if (is_prefixed_with(argv[], "--list")) {---------------------busybox --list显示busybox所有applet。
...
}
...
if (strcmp(argv[], "--help") == ) {--------------------------busybox --help显示busybox帮助信息。
/* "busybox --help [<applet>]" */
if (!argv[])
goto help;
/* convert to "<applet> --help" */
argv[] = argv[];
argv[] = NULL;
} else {
/* "busybox <applet> arg1 arg2 ..." */
argv++;
}
/* We support "busybox /a/path/to/applet args..." too. Allows for
* "#!/bin/busybox"-style wrappers */
applet_name = bb_get_last_path_component_nostrip(argv[]);
run_applet_and_exit(applet_name, argv);-----------------------类似于执行busybox ls,然后调用ls applet。
} void FAST_FUNC run_applet_no_and_exit(int applet_no, const char *name, char **argv)
{
...
if (
# if defined APPLET_NO_test
&& applet_no != APPLET_NO_test
# endif
# if defined APPLET_NO_true
&& applet_no != APPLET_NO_true
# endif
# if defined APPLET_NO_false
&& applet_no != APPLET_NO_false
# endif
) {
if (argc == && strcmp(argv[], "--help") == ) {-------如果是applet对应的--help。
/* Make "foo --help" exit with 0: */
xfunc_error_retval = ;
bb_show_usage();
}
}
if (ENABLE_FEATURE_SUID)
check_suid(applet_no);
xfunc_error_retval =applet_main[applet_no](argc, argv);-----根据applet_no好找到对应的函数,比如ls对应ls_main()。
/* Note: applet_main() may also not return (die on a xfunc or such) */
xfunc_die();
} void FAST_FUNC bb_show_usage(void)
{
if (ENABLE_SHOW_USAGE) {
#ifdef SINGLE_APPLET_STR
...
#else
const char *p;
const char *usage_string = p = unpack_usage_messages();
int ap = find_applet_by_name(applet_name);---------------根据全局变量applet_name找到对应的序号,然后根据需要找到对应的usage字符串。 if (ap < ) /* never happens, paranoia */
xfunc_die();
while (ap) {
while (*p++) continue;
ap--;
}
...
}
xfunc_die();
}
2. 如何添加applet
若需要添加自己的applet,比如在miscutils下创建一个monitor.c文件,在include创建一个monitor.h文件。
//config:config MONITOR-----------------------------------------------------Config.src会读取下面内容写入到Config.in中,用于配置monitor功能。
//config: bool "monitor"
//config: default n
//config: select PLATFORM_LINUX
//config: help
//config: Monitor will collect system exception, daemon corruption, critical app exit. //applet:IF_MONITOR(APPLET(monitor, BB_DIR_SBIN, BB_SUID_DROP))--------------此句会写入include/applets.h中,等于是声明了monitor_main()函数。 //kbuild:lib-$(CONFIG_MONITOR) += monitor.o----------------------------------经由Kbuild.src生成写入到Kbuild中,是对是否编译monitor.c的控制。 //usage:#define monitor_trivial_usage----------------------------------------写入到include/usage.h中,是monitor的帮助信息。
//usage: "[-q] [-o OFF] [-f FREQ] [-p TCONST] [-t TICK]"
//usage:#define monitor_full_usage "\n\n"
//usage: "Monitor system or app exception.\n"
//usage: "\n -q Quiet" #include "libbb.h"
#include <syslog.h>
#include <sys/un.h>
上面的config/applet/kbuild/usage,分别生成到miscutils/Config.in、include/applets.h、miscutils/Kbuild、include/usage.h四个文件中。
所以在配置了CONFIG_MONITOR之后,根据miscutils/Kbuild会编译monitor.c,入口函数是monitor_main()。
3. applet是如何嵌入到busybox的?
通过applets/applet_tables.c生成可执行文件applet_tables。
applets/Kbuild中执行cmd_gen_applet_tables = applets/applet_tables include/applet_tables.h include/NUM_APPLETS.h,生成applet_tables.h文件,以及applet总数的NUM_APPLETS定义。
#define NUM_APPLETS 260
#define KNOWN_APPNAME_OFFSETS 8 const uint16_t applet_nameofs[] ALIGN2 = {
,
,
,
,
,
,
,
}; const char applet_names[] ALIGN1 = ""--------------------------------------在find_applet_by_name()等函数中根据applet名称找到applet对应序号。
"[" "\0"
"[[" "\0"
"addgroup" "\0"
"adduser" "\0"
...
"zcat" "\0"
; #define APPLET_NO_addgroup 2
#define APPLET_NO_adduser 3
...
#define APPLET_NO_zcat 259 #ifndef SKIP_applet_main
int (*const applet_main[])(int argc, char **argv) = {---------------------根据applet序号,找到对应的入口函数。
test_main,
test_main,
addgroup_main,
adduser_main,
...
gunzip_main,
};
#endif const uint8_t applet_suid[] ALIGN1 = {
0x00,
0x00,
...0x00,
}; const uint8_t applet_install_loc[] ALIGN1 = {
0x33,
0x44,
...0x13,
};
其他生成文件还包括:usage.h、applets.h等。
usage.h中包含了函数的帮助信息,是由usage.c编译的usage生成的。
#define monitor_trivial_usage \
"[-q] [-o OFF] [-f FREQ] [-p TCONST] [-t TICK]" \ #define monitor_full_usage "\n\n" \
"Monitor system or app exception.\n" \
"\n -q Quiet" \
4. 小结
一个是添加applet的路径,新增.c和.h文件,其中最重要的是.c文件中特殊注释:config:、applet:、kbuild:、usage:。
然后busybox编译系统,解析.c中的注释,并将其添加到include/applets.h、include/usage.h、include/applet_tables.h等文件中。
两一个是applet的执行路径,busybox的入口函数mian()根据传入的applet_name,然后通过find_applet_by_name()找到对应序号,然后执行applet_main[]函数。即完成对applet的调用。
参考文档:《扩充BusyBox,追加Applet的方法》、《如何向busybox添加自己的命令》。
向busybox中添加自己的applet的更多相关文章
- [转]busybox中telnet 功能添加
使用busybox制作的一个基本根文件系统如何添加telnetd服务呢? 下面把本人的添加过程列出来供大家分享,如有不同意见请不吝赐教! 1. 添加telnet的支持(busybox中配置) Netw ...
- 在jekyll模板博客中添加网易云模块
最近使用GitHub Pages + Jekyll 搭建了个人博客,作为一名重度音乐患者,博客里面可以不配图,但是不能不配音乐啊. 遂在博客里面引入了网易云模块,这里要感谢网易云的分享机制,对开发者非 ...
- 在Linux(Luna)下向Launch启动器中添加图标
记录下在Luna下向Launch中添加图标的步骤,以供以后参考,这里我以加入eclipse图标为例: 首先,我们来创建一个desktop文件(Luna中到启动器Launch可以看作是Ubuntu中到桌 ...
- 用Retrofit发送请求中添加身份验证
用Retrofit发送请求中添加身份验证====================在安卓应用开发中, retrofit可以极大的方便发送http网络请求,不管是GET, POST, 还是PUT, DEL ...
- 在html中添加script脚本的方法和注意事项
在html中添加script脚本有两种方法,直接将javascript代码添加到html中与添加外部js文件,这两种方法都比较常用,大家可以根据自己需要自由选择 在html中添加<script& ...
- MVC学习随笔----如何在页面中添加JS和CSS文件
http://blog.csdn.net/xxjoy_777/article/details/39050011 1.如何在页面中添加Js和CSS文件. 我们只需要在模板页中添加JS和CSS文件,然后子 ...
- 怎样在Windows资源管理器中添加右键菜单以及修改右键菜单顺序
有时,我们需要在Windows资源管理器的右键菜单中添加一些项,以方便使用某些功能或程序. 比如我的电脑上有一个免安装版的Notepad++,我想在所有文件的右键菜单中添加一项用Notepad++打开 ...
- 在WebStorm环境中给nodejs项目中添加packages
照前文 http://www.cnblogs.com/wtang/articles/4133820.html 给电脑设置了WebStorm的IDE的nodejs开发环境.新建了个express的网站 ...
- dotnet webapi 中添加Swagger文档
首先添加"SwaggerGenerator": "1.1.0","SwaggerUi": "1.1.0" 需要注意的是这 ...
随机推荐
- Java之Hashmap中value为null,则返回json数据中key不存在
前两天干活儿的时候,将实例对象放在Hashmap中返回给前端: ArtificialEntity artificialEntity = artificialService.getInfoById(id ...
- 流式计算(二)-Kafka Stream
前面说了Java8的流,这里还说流处理,既然是流,比如水流车流,肯定得有流的源头,源可以有多种,可以自建,也可以从应用端获取,今天就拿非常经典的Kafka做源头来说事,比如要来一套应用日志实时分析框架 ...
- Android Studio出现Failed to open zip file问题的解决方法
直接在网上找到gradle-3.3-all.zip下载下来,不要解压缩,放在类似下面的目录中 C:\Users\Administrator\.gradle\wrapper\dists\gradle-3 ...
- .Net Core 项目发布到Linux - CentOS 7(一)
由于项目的需求,需要发布到Linux服务器上,在这里记录一下我发布的过程. 安装Linux 安装liunx系统很简单,网上也有很多教程,我是直接使用阿里云的CentOS 7.7 64位 部署环境 Li ...
- Asp.net Core3.0 跨域配置
原文:http://www.zilaohu.cn/Jie/Detail_Jie?ID=78840a04-55b8-4988-80b2-f964fd822d63 下面配置后:被拒绝的域请求后,可以进入方 ...
- golang的缓冲channel简单使用
目录 golang的缓冲channel简单使用 阻塞型 非阻塞 golang的缓冲channel简单使用 我们常用的是无缓冲channel : make(chan type) 其实make() 创建c ...
- CSS之border绘制三角形
用CSS的border可以画出高质量的三角形. 我们一般会这么使用border: #test-border { width: 100px; height: 100px; margin: 100px a ...
- Ligg.EasyWinApp-101-Ligg.EasyWinForm: Application--启动,传入参数、读取Application级别配置文件、验证密码、软件封面、启动登录、StartForm
首先请在VS里打开下面的文件,我们将对源码分段进行说明: 步骤1:读取debug.ini文件 首先读取当前文件夹(.\Clients\Form)的debug.ini文件,该文件的args用于调试时传参 ...
- VC遍历访问目录下的文件
访问目录文件夹下的文件是经常需要的操作,C/C++和win32接口都没有提供直接调用的函数.在这里总结了几个经常用到的函数,通过MFC的CFileFind函数递归遍历实现,包括以下几个功能函数: 查找 ...
- Burp Suite渗透操作指南 【暴力破解】
1.1 Intruder高效暴力破解 其实更喜欢称Intruder爆破为Fuzzing.Intruder支持多种爆破模式.分别是:单一字典爆破.多字段相同字典爆破.多字典意义对应爆破.聚合式爆破.最常 ...