【工具】如何将一个脚本作为C语言的一个文件被include到新的C文件中然后执行?(C语言 array的方式)

快速回忆

vim my_shell.sh #如果修改shell名字,也需要修改c中对应的array和len宏定义
xxd -i my_shell.sh > my_shell.h
vim c_shell.c #拷贝本文的c_shell.c
gcc c_shell.c
./a.out
./a.out 1 2 3 #带参数执行,参数会被带到sub cmd中
# 修改脚本后需要全部重新来一遍,并且要删除掉默认路径的脚本,不然不会重新生成
注意的一点是,需要删掉脚本

背景

有些时候,用C语言想包括一个文件到运行态,因为C语言是静态程序,并且include的关键值只支持C格式,如何做到将某个文件存在于C语言中。
本文以一个C语言的例子,执行一个shell脚本,并且该脚本存在于C语言的bin文件中。
有什么用呢?
有些场景下不想提供脚本,只提供一个bin二进程程序。

方式

方式就是将脚本存储在C语言的数组中,作为内存动态加载,如果要执行,将该内存写入临时文件并且修改权限后执行。

先生成脚本的头文件

使用xxd命令,将二进制文件转化为C语言数组,然后C语言 include,然后动态的比如创建文件,然后执行文件。
xxd命令是用来制作一个十六进制dump的命令。比如:xxd -i 1.sh > shell_array.h
他会将文件按照十六进制生成一个C语言的头文件,并且头文件会用原来文件的名字创建数组(如果数字开头会添加__前缀,如果字母不会),并且把长度也标注出来
在这里插入图片描述
字母开头的文件:
在这里插入图片描述
可以看到 0x75是117,对应字符是u;最后一个字符是0xa, 表示\n
在这里插入图片描述
在这里插入图片描述

然后将该头文件包含

c_shell.c的文件

#include "stdio.h"
#include "unistd.h"
#include "string.h" //strlen需要

#include "my_shell.h" //脚本的数组
#define SHELL_ARRAY_NAME my_shell_sh //这里是xxd -i生成文件中的数组名字
#define SHELL_ARRAY_LEN my_shell_sh_len //这里是xxd -i生成文件中的数组长度
#define SHELL_TMP_NAME "/tmp/my_shell.sh"


int del_shell_script() {
        unlink(SHELL_TMP_NAME);
}

int gen_shell_script() {
        printf("Will locate script at :%s\n", SHELL_TMP_NAME);
        FILE *fp = fopen(SHELL_TMP_NAME, "wb");
        if (!fp) {
                printf("Failed open 1.log\n");
                return -1;
        }

        if (fwrite(SHELL_ARRAY_NAME, 1, SHELL_ARRAY_LEN, fp) != SHELL_ARRAY_LEN){
                printf("Failed to write %s\n", SHELL_TMP_NAME);
                fclose(fp);
                //unlink("1.log"); //删除文件
                return 1;
        }
        fclose(fp);

实操

脚本创建:

[root@localhost lab]# cat my_shell.sh 
echo $@
uname -r

生成C的array:xxd -i my_shell.sh > my_shell.h
在这里插入图片描述

创建c_shell.c:如果不变化名字,可以直接使用前面的c_shell.c如果变化名字,需要修改这几个地方:

#include "my_shell.h" //脚本的数组
#define SHELL_ARRAY_NAME my_shell_sh //这里是xxd -i生成文件中的数组名字
#define SHELL_ARRAY_LEN my_shell_sh_len //这里是xxd -i生成文件中的数组长度
#define SHELL_TMP_NAME "/tmp/my_shell.sh"

my_shell.h是根据xxd输出文件决定。
my_shell_sh和my_shell_sh_len是xxd的输入文件名字决定
SHELL_TMP_NAME是指定动态创建的地方。

编译新的bin文件和执行:gcc c_shell.c
在这里插入图片描述

如果要带参数执行,参数会被透传到脚本或者sub的bin代码中:
在这里插入图片描述

其他

这里除了shell,还可以是可执行程序。玩法有很多。可以用一个bin包含另外一个bin。

综述

本文这种方式有挺多挺好玩的模式,比如常见的一些工具,可以用它来把命令封装,比如需要输入的特殊参数,比如不想让别人看到的。甚至还可以做一些加解密的动作在里面。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值