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

快速回忆

bash 复制代码
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的文件

bash 复制代码
#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);

实操

脚本创建:

bash 复制代码
[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如果变化名字,需要修改这几个地方:

bash 复制代码
#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。

综述

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

相关推荐
旅行的橘子汽水2 小时前
【C语言-全局变量】
c语言·开发语言·数据库
沐墨专攻技术2 小时前
顺序表专题(C语言)
c语言·开发语言·数据结构·顺序表
liuluyang53010 小时前
C语言C11支持的结构体嵌套的用法
c语言·开发语言·算法·编译·c11
明飞198711 小时前
C_内存 内存地址概念
c语言·开发语言
牛奶咖啡.85411 小时前
第十四届蓝桥杯大赛软件赛省赛C/C++ 大学 A 组真题
c语言·数据结构·c++·算法·蓝桥杯
头发尚存的猿小二14 小时前
2024年第十五届蓝桥杯C&C++大学A组--成绩统计
c语言·开发语言·c++·蓝桥杯
Spiffo_Sir17 小时前
【Spiffo】光速项目:LVGL v9框架下的MIPI简易相机_Part2
linux·c语言·数码相机
xueyinan17 小时前
小刚说C语言刷题——第21讲 一维数组
c语言
ん贤18 小时前
蓝桥杯考前复盘
c语言·c++·算法·职场和发展·蓝桥杯
khazix10119 小时前
【C语言】--- 文件操作
c语言·开发语言