自定义命令执行器:C++中命令封装的深度探索(C/C++实现)
在现代软件开发中,执行系统命令是一项常见的需求,无论是自动化脚本、系统管理工具,还是需要调用外部程序的复杂应用程序,都离不开对系统命令的调用。然而,直接使用系统调用(如 execve)虽然简单,但存在诸多问题,例如安全性不足、灵活性差以及可维护性低等。为了克服这些问题,我们可以通过封装命令执行逻辑,设计一个自定义的命令执行器。本文将深入探讨如何在 C++ 中实现一个安全、灵活且易于管理的命令执行器。
一、背景与动机
在许多应用程序中,执行系统命令是一项常见需求。例如,自动化脚本、系统管理工具或需要调用外部程序的复杂应用程序。然而,直接使用系统调用(如 execve)存在以下问题:
安全性问题:直接拼接命令字符串可能导致命令注入攻击。
灵活性不足:系统调用通常需要手动管理参数和环境变量,容易出错。
可维护性差:直接调用系统调用的代码通常难以阅读和维护。
为了解决这些问题,我们设计了一个自定义的命令执行器包装器,通过封装命令执行逻辑,提供更安全、灵活且易于管理的接口。
二、设计与实现
1. 命令执行器类的设计
命令执行器的核心是一个 command 类,它封装了命令名称、参数列表和环境变量。以下是 command 类的主要设计:
类定义
class command
{
public:command(const std::string cmd, const std::vector<std::string>& arguments, const environ_map& envs = environ_map());command(const command&) = default;command(command&&) = default;command& operator=(const command&) = default;command& operator=(command&&) = default;~command() = default;void exec();private:std::string m_cmd;std::vector<std::string> m_arguments;environ_map m_envs;
};
构造函数
构造函数接受命令名称、参数列表和环境变量。其中,环境变量通过 environ_map 类型传递,这是一个自定义的环境变量映射类,支持从当前进程环境变量初始化。
执行逻辑
exec() 方法是命令执行的核心。它使用 execve 系统调用执行命令,同时处理参数和环境变量的转换。为了安全地管理动态分配的内存,我们使用 std::shared_ptr 来管理参数数组。
2. 参数和环境变量的处理
为了将参数列表和环境变量转换为 execve 所需的格式,我们设计了以下辅助函数:
参数转换
std::shared_ptr<char*> to_argv(const std::string& cmd, const std::vector<std::string>& vec)
{char **argv = new char*[vec.size() + 2];argv[0] = ::strdup(cmd.c_str());for(size_t i = 0 ; i < vec.size(); ++i)argv[i+1] = ::strdup(vec[i].c_str());argv[vec.size()+1] = nullptr;return std::shared_ptr<char*>(argv, argv_deleter);
}
环境变量转换
environ_map 类提供了一个 raw() 方法,将环境变量映射转换为 execve 所需的格式。它使用 动态分配内存,并通过自定义的 raw_environ_holder 类管理内存生命周期。
3. 环境变量管理
environ_map 类是一个封装了环境变量的映射类,支持从当前进程环境变量初始化,并提供安全的内存管理机制。以下是其主要实现:
环境变量映射
class environ_map : public std::map<std::string, std::string>
{
public:environ_map() = default;environ_map(const std::map<std::string, std::string>& map) : std::map<std::string, std::string>(map) {};environ_map(const environ_map&) = default;raw_environ_holder raw() const;static environ_map get_for_current_process();
};
从当前进程环境变量初始化
environ_map environ_map::get_for_current_process()
{environ_map result;int i = 0;while(environ[i]){std::string str(environ[i++]);size_t indx = str.find('=');if(indx == std::string::npos)throw std::runtime_error("Failed to parse env");result[str.substr(0, indx)] = str.substr(indx +1);}return result;
}
三、自定义命令执行器的包装器:实现与应用(C/C++实现)
展示如何使用自定义的命令执行器:
cpp复制
#include "command.h"
#include "environ_map.h"class command
{
public:command(const std::string cmd, const std::vector<std::string>& arguments, const environ_map& envs = environ_map());command(const command&) = default;command(command&&) = default;command& operator=(const command&) = default;command& operator=(command&&) = default;~command() = default;void exec();private:std::string m_cmd;std::vector<std::string> m_arguments;environ_map m_envs;
};...
class raw_environ_holder
{
public:raw_environ_holder() = delete;raw_environ_holder(const raw_environ_holder&) = delete;raw_environ_holder(raw_environ_holder&&);raw_environ_holder& operator=(const raw_environ_holder&) = delete;raw_environ_holder& operator=(raw_environ_holder&&);~raw_environ_holder();operator char**() { return ppenv;};private:friend class environ_map;explicit raw_environ_holder(char** ppenv) : ppenv(ppenv){};void destroy();char** ppenv;
};class environ_map : public std::map<std::string, std::string>
{
public:environ_map() = default;environ_map(const std::map<std::string, std::string>& map) : std::map<std::string, std::string>(map) {};environ_map(const environ_map&) = default;raw_environ_holder raw() const;static environ_map get_for_current_process();
};...
int main()
{// 获取当前进程的环境变量environ_map m = environ_map::get_for_current_process();for(const auto& p: m){std::cout << p.first << "=" << p.second << std::endl;}// 创建并执行命令command cmd("/bin/ls", std::vector<std::string>());cmd.exec();
}
我们首先获取当前进程的环境变量,然后创建一个 command 对象来执行 /bin/ls 命令。通过封装命令执行逻辑,代码更加清晰且易于维护。
If you need the complete source code, please add the WeChat number (c17865354792)
四、优势与总结
通过实现自定义命令执行器,我们可以更加灵活和安全地执行系统命令。上述实现不仅支持环境变量的设置和传递多个参数,还能够处理执行过程中的错误,并提供输出捕获的功能。这种封装方式使得命令执行变得更加简洁和易于维护,同时也提高了代码的安全性和可读性。未来,我们可以进一步扩展该执行器,添加更多的功能,如异步执行、超时控制等,以满足更多复杂的需求。
Welcome to follow WeChat official account【程序猿编码】
相关文章:
自定义命令执行器:C++中命令封装的深度探索(C/C++实现)
在现代软件开发中,执行系统命令是一项常见的需求,无论是自动化脚本、系统管理工具,还是需要调用外部程序的复杂应用程序,都离不开对系统命令的调用。然而,直接使用系统调用(如 execve)虽然简单&…...

C语言程序设计十大排序—选择排序
文章目录 1.概念✅2.选择排序🎈3.代码实现✅3.1 直接写✨3.2 函数✨ 4.总结✅5.十大排序 1.概念✅ 排序是数据处理的基本操作之一,每次算法竞赛都很多题目用到排序。排序算法是计算机科学中基础且常用的算法,排序后的数据更易于处理和查找。在…...

C语言初阶牛客网刷题——HJ73 计算日期到天数转换【难度:简单】
1. 题目描述——HJ73 计算日期到天数转换 牛客网OJ题链接 描述 每一年中都有 12 个月份。其中,1,3,5,7,8,10,12 月每个月有 31 天; 4,6,9,11 月每个月有 30 天;而对于 2 月,闰年时有29 天,平年时有 28 天。 现在&am…...
MATLAB中alphanumericsPattern函数用法
目录 语法 说明 示例 从文本中提取字母和数字 匹配所设置数目的字母和数字 匹配不同大小的字母和数字集合 alphanumericsPattern函数的功能是匹配字母和数字字符。 语法 pat alphanumericsPattern pat alphanumericsPattern(N) pat alphanumericsPattern(minCharact…...
人工智能在教育领域的创新应用与前景展望
人工智能在教育领域的创新应用与前景展望 摘要:本文围绕人工智能在教育领域的应用展开深入探讨,分析了人工智能为教育带来的创新变革,如个性化学习支持、智能教学辅助、教育资源优化等方面的显著成效,同时探讨了其在应用过程中面…...
约束布局 ConstraintLayout
鸿蒙操作系统(HarmonyOS)是华为公司自主研发的面向全场景的分布式操作系统,旨在为用户提供流畅、安全、可靠的智能生活体验。随着鸿蒙操作系统的不断发展和完善,越来越多的开发者开始关注并投入到鸿蒙应用开发中来。对于想要深入理…...

校园商铺管理系统设计与实现(代码+数据库+LW)
摘 要 信息数据从传统到当代,是一直在变革当中,突如其来的互联网让传统的信息管理看到了革命性的曙光,因为传统信息管理从时效性,还是安全性,还是可操作性等各个方面来讲,遇到了互联网时代才发现能补上自…...

react native在windows环境搭建并使用脚手架新建工程
截止到2024-1-11,使用的主要软件的版本如下: 软件实体版本react-native0.77.0react18.3.1react-native-community/cli15.0.1Android Studio2022.3.1 Patch3Android SDKAndroid SDK Platform 34 35Android SDKAndroid SDK Tools 34 35Android SDKIntel x…...

vulnhub DC-1靶机 walkthrough
描述 DC-1 是专门为获得渗透测试经验而建造的易受攻击实验室。 它旨在成为初学者的挑战,但其难易程度取决于您的技能和知识以及学习能力。 要成功完成此挑战,您需要具备 Linux 技能、熟悉 Linux 命令行以及使用基本渗透测试工具的经验,例如 …...

计算机网络 (58)无线局域网WLAN
前言 无线局域网WLAN(Wireless Local Area Network)是一种利用无线通信技术将计算机设备互联起来,构成可以互相通信和实现资源共享的网络体系。 一、定义与特点 定义: WLAN通过无线信道代替有线传输介质连接两个或多个设备形成一个…...

基于物联网的风机故障检测装置的设计与实现
1 系统总体设计方案 通过对风机故障检测装置的设计与实现的需求、可行性进行分析,本设计风机故障检测装置的设计与实现的系统总体架构设计如图2-1所示,系统风机故障检测装置采用STM32F103单片机作为控制器,并通过DS18B20温度传感器、ACS712电…...
【AI日记】25.01.25
【AI论文解读】【AI知识点】【AI小项目】【AI战略思考】【AI日记】【读书与思考】 AI kaggle 比赛:Forecasting Sticker Sales 读书 书名:法治的细节 律己 AI:8 小时,良作息:00:30-8:30, 良短视频&…...
Sourcetree:一款高效便捷的Git版本控制客户端
Sourcetree:一款高效便捷的Git版本控制客户端 引言 在软件开发领域,版本控制是确保代码质量和项目进度的关键工具。Git作为当前最流行的版本控制系统,已经广泛应用于各类项目中。而Sourcetree作为Git的图形化界面客户端,凭借其易…...

图像处理算法研究的程序框架
目录 1 程序框架简介 2 C#图像读取、显示、保存模块 3 C动态库图像算法模块 4 C#调用C动态库 5 演示Demo 5.1 开发环境 5.2 功能介绍 5.3 下载地址 参考 1 程序框架简介 一个图像处理算法研究的常用程序逻辑框架,如下图所示 在该框架中,将图像处…...

GitLab配置免密登录和常用命令
SSH 免密登录 Windows免密登录 删除现有Key 访问目录:C:\Users\Administrator\ .ssh,删除公钥:id_rsa.pub ,私钥:id_rsa 2.生成.ssh 秘钥 运行命令生成.ssh 秘钥目录( ssh-keygen -t rsa -C xxxxxx126.…...

Chameleon(变色龙) 跨平台编译C文件,并一次性生成多个平台的可执行文件
地址:https://github.com/MartinxMax/Chameleon Chameleon 跨平台编译C文件,并一次性生成多个平台的可执行文件。可以通过编译Chameleon自带的.C文件反向Shell生成不同平台攻击载荷。 登录 & 代理设置 按照以下步骤设置 Docker 的代理: 创建配置目…...

第十四讲 JDBC数据库
1. 什么是JDBC JDBC(Java Database Connectivity,Java数据库连接),它是一套用于执行SQL语句的Java API。应用程序可通过这套API连接到关系型数据库,并使用SQL语句来完成对数据库中数据的查询、新增、更新和删除等操作…...

“AI教学实训系统:打造未来教育的超级引擎
嘿,各位教育界的伙伴们,今天我要跟你们聊聊一个绝对能让你们眼前一亮的教学神器——AI教学实训系统。作为资深产品经理,我可是亲眼见证了这款系统如何颠覆传统教学,成为未来教育的超级引擎。 一、什么是AI教学实训系统?…...
java读取设置pdf属性信息
pom <dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>2.0.24</version> </dependency>读取属性 import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmod…...

C语言内存管理详解
C语言不像其他高级语言那样提供自动内存管理,它要求程序员手动进行内存的分配和释放。在C语言中,动态内存的管理主要依赖于 malloc、calloc、realloc 和 free 等函数。理解这些函数的用法、内存泄漏的原因及其防止方法,对于编写高效、可靠的C…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...

CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...
django blank 与 null的区别
1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是,要注意以下几点: Django的表单验证与null无关:null参数控制的是数据库层面字段是否可以为NULL,而blank参数控制的是Django表单验证时字…...

Matlab实现任意伪彩色图像可视化显示
Matlab实现任意伪彩色图像可视化显示 1、灰度原始图像2、RGB彩色原始图像 在科研研究中,如何展示好看的实验结果图像非常重要!!! 1、灰度原始图像 灰度图像每个像素点只有一个数值,代表该点的亮度(或…...

【java面试】微服务篇
【java面试】微服务篇 一、总体框架二、Springcloud(一)Springcloud五大组件(二)服务注册和发现1、Eureka2、Nacos (三)负载均衡1、Ribbon负载均衡流程2、Ribbon负载均衡策略3、自定义负载均衡策略4、总结 …...

【Linux】使用1Panel 面板让服务器定时自动执行任务
服务器就是一台24小时开机的主机,相比自己家中不定时开关机的主机更适合完成定时任务,例如下载资源、备份上传,或者登录某个网站执行一些操作,只需要编写 脚本,然后让服务器定时来执行这个脚本就可以。 有很多方法实现…...