用C语言写一个自己的shell-Part Ⅱ--execute commands
Part Ⅱ–execute commands
Exec
This brings us to the exec
family of functions. Namely, it has the following functions:
execl
execv
execle
execve
execlp
execvp
For our needs,we will use execvp
whose signature looks like this
int execvp(const char *file, char *const argv[]);
execvp function indicates that,it accepts the name of a file,for which it will search for $PATH
variable of the system and an array of arguments to be executed.
A few things to note about the execvp
function:
- The first argument is the name of the command
- The second argument consists of the name of the command and the arguments passed to the command itself. It must also be terminated by
NULL
. - It also swaps out the current process image with that of the command being executed, but more on that later.
execvp.c
#include <unistd.h>int main() {char *argv[] = {"ls","-l","-h","-a",NULL};execvp(argv[0],argv);return 0;
}
If you compile and execute the execvp.c, you will see an output similar to the following:
total 32K
drwxrwxr-x 2 marco marco 4.0K 3月 1 22:07 .
drwxrwxr-x 5 marco marco 4.0K 3月 1 22:04 ..
-rwxrwxr-x 1 marco marco 17K 3月 1 22:07 execvp
-rw-rw-r-- 1 marco marco 123 3月 1 22:07 execvp.c
Which is exactly the same if you manually executels -l -h -a
readline
https://tiswww.case.edu/php/chet/readline/rltop.html
With execvp function,we can perform commands in $PATH
but how to accept the string of commands as stdin?
This brings us to the Readline Library.
#include <stdio.h>
#include <readline/readline.h>
char * readline (const char *prompt);
However,when I used this function,error occured.
Ubuntu that I used doesn’t have the library by default.Hence,the library need to be installed.
sudo apt-get install libreadline-dev
Meanwhile,we should add an another argument to link the library when compiling the File.c
,otherwise you may see an error like
“undefined reference to `readline’
collect2: error: ld returned 1 exit status”.
gcc File.c -o File -lreadline
And here’s the code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <readline/readline.h>
#include <sys/wait.h>char **get_input(char *);int main() {//in C,ptr can be used as array.char **command;char *input;pid_t child_pid;int stat_loc;while(1) {input = readline("mysh> ");//with "mysh> " to be a prompt,the function reads a line of input.command = get_input(input);if(!command[0]) {//empty commandsfree(input);free(command);continue;}child_pid = fork();if(child_pid == 0) {//child processexecvp(command[0],command);} else {waitpid(child_pid, &stat_loc, WUNTRACED);}free(input);free(command);}return 0;
}char **get_input(char *input) {char **command = malloc(8 * sizeof(char *));char *separator = " ";char *parsed;int index = 0;parsed = strtok(input, separator);while (parsed != NULL) {command[index] = parsed;index++;parsed = strtok(NULL, separator);}command[index] = NULL;return command;
}
Let’s test it.
However,the exec
family of function can’t perform built-in commands like cd
.
The code with weak robustness should be revised to be more robust and stronger.
-
Dynamic memory allocation - in
char ** get_input(char *input);
The command variable only malloc 8 sizeof(char *).It’s limited,
so you will see the following error:
To handle the error,command
should malloc dynamic memories.
-
fork failed - If the OS runs out of memory or reaches the maxmum number of allowed processes,a child process will not be created.We add the following segment to our code:
if(child_pid < 0) {perror(command[0]);exit(1);}
-
exev failed - the exev function may fail.We modify the following block to our code:
//child processif (execvp(command[0], command) < 0) {perror(command[0]);exit(1);}
The revised code is here,written by chatGPT.The AI is amazing!!!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <readline/readline.h>
#include <sys/wait.h>char **split_input(char *);int main() {//in C,ptr can be used as array.char **command;char *input;pid_t child_pid;int stat_loc;while(1) {input = readline("mysh> ");//with "mysh> " to be a prompt,the function reads a line of input.command = split_input(input);if(!command[0]) {//empty commandsfree(input);free(command);continue;}//fork failed.child_pid = fork();if(child_pid < 0) {perror(command[0]);exit(1);}if(child_pid == 0) {//child processif (execvp(command[0], command) < 0) {perror(command[0]);exit(1);}} else {waitpid(child_pid, &stat_loc, WUNTRACED);}free(input);free(command);}return 0;
}
char **split_input(char *input) {int capacity = 10;char **command = malloc(capacity * sizeof(char *));if (command == NULL) {fprintf(stderr, "Error: memory allocation failed\n");exit(EXIT_FAILURE);}char *token = strtok(input, " ");int i = 0;while (token != NULL) {if (i == capacity - 1) { // resize the array if it is fullcapacity *= 2;char **new_command = realloc(command, capacity * sizeof(char *));if (new_command == NULL) {fprintf(stderr, "Error: memory allocation failed\n");exit(EXIT_FAILURE);}command = new_command;}command[i] = malloc((strlen(token) + 1) * sizeof(char));if (command[i] == NULL) {fprintf(stderr, "Error: memory allocation failed\n");exit(EXIT_FAILURE);}strcpy(command[i], token);token = strtok(NULL, " ");i++;}command[i] = NULL; // terminate the array with NULLreturn command;
}
相关文章:

用C语言写一个自己的shell-Part Ⅱ--execute commands
Part Ⅱ–execute commands Exec This brings us to the exec family of functions. Namely, it has the following functions: execlexecvexecleexecveexeclpexecvp For our needs,we will use execvp whose signature looks like this int execvp(const char *file, cha…...

案例实践|运营腾讯游戏,Proxima Beta 使用 Apache Pulsar 升级团队协作与数据治理...
文章摘要本文整理自 Pulsar Summit Asia 2022 上,Proxima Beta 软件工程师施磊的分享《How to achieve better team integration and data governance by using Apache Pulsar》。本文首先将为大家介绍 CQRS 和 Event Sourcing 概念,便于了解为何 Proxim…...

Hudi的7种索引
1、Bloom Index Bloom Index (default) 使用根据记录键构建的bloom过滤器,也可以使用记录键范围修剪候选文件.原理为计算RecordKey的hash值然后将其存储到bitmap中,为避免hash冲突一般选择计算3次 HoodieKey 主键信息:主要包含recordKey 和p…...
Linux内核(十三)系统软中断 software
文章目录中断概述Linux内核中断软中断相关代码解析软中断结构体软中断类型软中断两种触发方式函数__do_softirq解析定时器的软中断实现解析定时器相关代码总结Linux版本:linux-3.18.24.x 中断概述 中断要求 快进快出,提高执行效率,…...

Linux -- 查看进程 PS 命令 详解
我们上篇介绍了, Linux 中的进程等概念,那么,在Linux 中如何查看进程呢 ??我们常用到的有两个命令, PS 和 top 两个命令,今天先来介绍下 PS 命令~!PS 命令 :作用 &#x…...
C2科一考试道路通行规定
目录 低能见度等恶劣环境下的通行规定 驾驶机动车禁止行为 停车规定 通行常识 高速公路限速规定 三观不一样的人,无论重来多少次,结果都一样 他不会懂你的委屈 只是觉得自已没错 两个人真正的可悲连吵架都不在一个点上 有句话说得好 我要是没点自我…...

进程概念(详细版)
进程的概念本文主要介绍进程的相关知识 文章目录认识冯诺依曼体系结构操作系统的基本概念操作系统的作用是什么系统调用和库函数相关概念进程基本概念描述进程进程控制块(PCB)task_struct 结构体进程是如何被操作系统管理起来的先描述再组织描述好,组织好࿰…...

学习大数据应该掌握哪些技能
想要了解大数据开发需要掌握哪些技术,不妨先一起来了解一下大数据开发到底是做什么的~ 1、什么是大数据? 关于大数据的解释,比较官方的定义是指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合,是需要新处理模…...

【spring】Spring Data --Spring Data JPA
Spring Data 的委托是为数据访问提供熟悉且符合 Spring 的编程模型,同时仍保留着相关数据存储的特殊特征。 它使使用数据访问技术、关系和非关系数据库、map-reduce 框架和基于云的数据服务变得容易。这是一个伞形项目,其中包含许多特定于给定数据库…...

mysql数据库之视图
视图(view)是一种虚拟的存在,视图中的数据并不在数据库中实际存在,行和列数据来自定义视图的查询中使用的表,并且是在使用视图时动态生成的。 通俗的讲,视图之保存了查询的sql逻辑,不保存查询结…...

数据库事务详解
概述事务就是数据库为了保证数据的原子性,持久性,隔离性,一致性而提供的一套机制, 在同一事务中, 如果有多条sql执行, 事务可以确保执行的可靠性.数据库事务的四大特性一般来说, 事务是必须满足 4 个条件(ACID):原子性(Atomicity&…...

Nessus: 漏洞扫描器-网络取证工具
Nessue 要理解网络漏洞攻击,应该理解攻击者不是单独攻击,而是组合攻击。因此,本文介绍了关于Nessus历史的研究,它是什么以及它如何与插件一起工作。研究了Nessus的特点,使其成为网络取证中非常推荐的网络漏洞扫描工具…...
操作系统实战45讲之现代计算机组成
我以前觉得计算机理论不让我感兴趣,而比较喜欢实践,即敲代码,现在才发现理论学好了,实践才能有可能更顺利,更重要的是理论与实践相结合。 在现代,几乎所有的计算机都是遵循冯诺依曼体系结构,而遵…...
Simple Baselines for Image Restoration
Abstract.尽管近年来在图像恢复领域取得了长足的进步,但SOTA方法的系统复杂性也在不断增加,这可能会阻碍对方法的分析和比较。在本文中,我们提出了一个简单的基线,超过了SOTA方法,是计算效率。为了进一步简化基线&…...
Python数据可视化:局部整体图表可视化(基础篇—6)
目录 1、饼图 2、圆环图 3、马赛克图 4、华夫饼图 5、块状/点状柱形图 在学习本篇博文之前请先看一看之前发过的关联知识:...

CSDN新星计划新玩法、年度勋章挑战赛开启
文章目录🌟 写在前面🌟 逐步亮相的活动🌟 勋章挑战赛🌟 新星计划🌟 有付费课程才可参与?🌟 成就铭牌🌟 博客跟社区的关系🌟 写在最后🌟 写在前面 哈喽&#…...

Docker之部署Mysql
通过docker对Mysql进行部署。 如果没有部署过docker,看我之前写的目录拉取镜像运行容器开放端口拉取镜像 前往dockerHub官网地址,搜索mysql。 找到要拉取的镜像版本,在tag下找到版本。 拉取mysql镜像,不指定版本数,…...

基于C/C++获取电脑网卡的IP地址信息
目录 前言 一、网卡是什么? 二、实现访问网卡信息 1.引入库及相关的头文件 2.操作网卡数据 3. 完整代码实现 4.结果验证 总结 前言 简单示例如何在windows下使用c/c代码实现 ipconfig/all 指令 提示:以下是本篇文章正文内容,下面案例可供参考…...
28相似矩阵和若尔当标准型
一、关于正定矩阵的一些补充 在此之前,先讲一下对称矩阵中那些特征值为正数的矩阵,这样特殊的矩阵称为正定矩阵。其更加学术的定义是: SSS 是一个正定矩阵,如果对于每一个非零向量xxx,xTSx>0x^TSx>0xTSx>0 正…...
springboot操作MongoDB
启动类及配置import com.mongodb.client.MongoClient;import com.mongodb.client.MongoClients;import com.mongodb.client.internal.MongoClientImpl;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplicatio…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...

XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...

dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...
《C++ 模板》
目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板,就像一个模具,里面可以将不同类型的材料做成一个形状,其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式:templa…...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...