[Linux入门]---使用exec函数实现简易shell

文章目录

  • 1.简易实现
  • 2.人机交互,获取命令行
  • 3.命令行分割
  • 4.执行命令
  • 5.内建命令
  • 6.myshell代码

1.简易实现

2.人机交互,获取命令行

代码如下:

int quit=0;
#define LEFT "["
#define RIGHT "]"
#define LABLE "#"
#define LINE_SIZE 1024char pwd[LINE_SIZE];
char commandline[LINE_SIZE];const char* getusername()
{return getenv("USER");
}void getpwd()
{getcwd(pwd, sizeof(pwd));
}
void interact(char* cline, int size)
{//获取主机名char hostname[256];gethostname(hostname, sizeof(hostname));//获取当前路径getpwd();printf(LEFT"%s@%s %s"RIGHT""LABLE" ", getusername(),hostname, pwd);char* s = fgets(cline, size, stdin);assert(s);//debug版本下assert才起效果//release,assert失效(void)s;//使用一下,可以在不同版本都生效,抵挡编译器报警//"abcd\n\0"cline[strlen(cline)-1] = '\0';
}
int main()
{while(!quit){//交互问题,获取命令行interact(commandline,sizeof(commandline));printf("%s\n",commandline );}return 0;
}

代码运行的的结果为:
在这里插入图片描述
运行结果如上,程序获取命令行以及提示行显示的功能已经完成了。

3.命令行分割

代码如下:

#define DELIM " "
#define ARGC_SIZE 32char* argv[ARGC_SIZE];int splitstring(char cline[], char* _argv[])
{int i = 0;_argv[i++] = strtok(cline, DELIM);//stork函数扫描字符串末尾时,返回空指针while(_argv[i++] = strtok(NULL,DELIM));//故意写的=return i - 1;
}
int main()
{while(!quit){//交互问题,获取命令行interact(commandline,sizeof(commandline));//3.子串分割问题,解析命令行int argc = splitstring(commandline,argv);if(argc == 0) continue;for(int i = 0; i < argc; i++){printf("%s\t",argv[i]);}printf("\n");}return 0;
}

代码运行的的结果为:
在这里插入图片描述
运行结果如上,命令行分割成字符串并存放进入数组使用。

4.执行命令

代码如下:

#define EXIT_CODE 44int lastcode = 0;void NormalExcute(char* _argv[])
{pid_t id = fork();if(id < 0){perror("fork");return;}else if(id == 0){//让子进程执行命令execvp(_argv[0],_argv);exit(EXIT_CODE);}else{int status = 0;pid_t rid = waitpid(id, &status,0);if(rid == id){lastcode = WEXITSTATUS(status);}}
}
int main()
{while(!quit){//1.交互问题,获取命令行interact(commandline,sizeof(commandline));//2.子串分割问题,解析命令行int argc = splitstring(commandline,argv);if(argc == 0) continue;for(int i = 0; i < argc; i++){//printf("%d:",i);//printf("%s\n",argv[0]);printf("%s\n",argv[i]);}printf("\n");//3.普通命令的执行//if(!n)NormalExcute(argv);}return 0;
}

代码运行的结果:
在这里插入图片描述
运行结果如上,可以让子进程执行替换函数,调用系统程序命令执行!

5.内建命令

在这里插入图片描述
我们发现使用一些命令的时候没有结果,诸如“”cd\echo”等命令,因为这些命令属于内建命令,是要父进程执行的。
代码如下:

#define EXIT_CODE 44int lastcode = 0;//自定义环境变量表
char myenv[LINE_SIZE];
//自定义本地变量表int buildCommand(char* _argv[], int _argc)
{if(_argc == 2 && strcmp(_argv[0], "cd") == 0){//修改父进程中的当前路径chdir(argv[1]);//把修改路径放到pwd数组中getpwd();//把pwd数组的路径,放到环境变量中sprintf(getenv("PWD"), "%s", pwd);return 1;}else if(_argc == 2 && strcmp(_argv[0], "export") == 0){strcpy(myenv, _argv[1]);putenv(myenv);//增加环境变量到父进程中return 1;}else if(_argc == 2 && strcmp(_argv[0], "echo") == 0){if(strcmp(_argv[1],"$?") == 0){printf("%d\n", lastcode);lastcode=0;}else if(*_argv[1] == '$'){char* val = getenv(_argv[1]+1);if(val) printf("%s\n", val);}return 1;}//特殊处理一下if(strcmp(_argv[0], "ls") == 0){_argv[_argc++] = "--color";_argv[_argc] = NULL;}return 0;
}
int main()
{while(!quit){//1.交互问题,获取命令行interact(commandline,sizeof(commandline));//2.子串分割问题,解析命令行int argc = splitstring(commandline,argv);if(argc == 0) continue;for(int i = 0; i < argc; i++){//printf("%d:",i);//printf("%s\n",argv[0]);printf("%s\n",argv[i]);}printf("\n");//指令的判断//内建命令,本质就是一个shell内部的一个函数int n = buildCommand(argv, argc);//3.普通命令的执行if(!n) NormalExcute(argv);}return 0;
}

代码运行的结果如下:
在这里插入图片描述
在执行普通命令之前,我们需要判断是不是内建命令,如果是的话,分析之后让父进程执行!

6.myshell代码

#include <stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<assert.h>
#include<string.h>
#include<sys/types.h>
#include<sys/wait.h>#define LEFT "["
#define RIGHT "]"
#define LABLE "#"
#define LINE_SIZE 1024
#define DELIM " "
#define ARGC_SIZE 32
#define EXIT_CODE 44int quit=0;
char pwd[LINE_SIZE];
char commandline[LINE_SIZE];
char* argv[ARGC_SIZE];
int lastcode = 0;//自定义环境变量表
char myenv[LINE_SIZE];
//自定义本地变量表const char* getusername()
{return getenv("USER");
}
//const char* gethostname()
//{
//    return getenv("HOSTNAME");
//}
const char* mygethostname()
{//char myhostname[LINE_SIZE];return getenv("HOSTNAME");
}
void getpwd()
{getcwd(pwd, sizeof(pwd));
}
void interact(char* cline, int size)
{//获取主机名char hostname[256];gethostname(hostname, sizeof(hostname));//获取当前路径getpwd();//printf("%s\n",mygethostname());//printf(LEFT"%s@%s%s"RIGHT""LABLE" ",getusername(),mygethostname(),pwd);printf(LEFT"%s@%s %s"RIGHT""LABLE" ", getusername(),hostname, pwd);char* s = fgets(cline, size, stdin);assert(s);//debug版本下assert才起效果//release,assert失效(void)s;//使用一下,可以在不同版本都生效,抵挡编译器报警//"abcd\n\0"cline[strlen(cline)-1] = '\0';
}int splitstring(char cline[], char* _argv[])
{int i = 0;_argv[i++] = strtok(cline, DELIM);//stork函数扫描字符串末尾时,返回空指针while(_argv[i++] = strtok(NULL,DELIM));//故意写的=return i - 1;
}void NormalExcute(char* _argv[])
{pid_t id = fork();if(id < 0){perror("fork");return;}else if(id == 0){//让子进程执行命令execvp(_argv[0],_argv);exit(EXIT_CODE);}else{//创建子进程失败int status = 0;pid_t rid = waitpid(id, &status,0);if(rid == id){lastcode = WEXITSTATUS(status);}}
}
int buildCommand(char* _argv[], int _argc)
{if(_argc == 2 && strcmp(_argv[0], "cd") == 0){//修改父进程中的当前路径chdir(argv[1]);//把修改路径放到pwd数组中getpwd();//把pwd数组的路径,放到环境变量中sprintf(getenv("PWD"), "%s", pwd);return 1;}else if(_argc == 2 && strcmp(_argv[0], "export") == 0){strcpy(myenv, _argv[1]);putenv(myenv);//增加环境变量到父进程中return 1;}else if(_argc == 2 && strcmp(_argv[0], "echo") == 0){if(strcmp(_argv[1],"$?") == 0){printf("%d\n", lastcode);lastcode=0;}else if(*_argv[1] == '$'){char* val = getenv(_argv[1]+1);if(val) printf("%s\n", val);}return 1;}//特殊处理一下if(strcmp(_argv[0], "ls") == 0){_argv[_argc++] = "--color";_argv[_argc] = NULL;}return 0;
}
int main()
{while(!quit){//1.交互问题,获取命令行interact(commandline,sizeof(commandline));//2.子串分割问题,解析命令行int argc = splitstring(commandline,argv);if(argc == 0) continue;//指令的判断//内建命令,本质就是一个shell内部的一个函数int n = buildCommand(argv, argc);//3.普通命令的执行if(!n) NormalExcute(argv);}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1535075.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

无线安全(WiFi)

免责声明:本文仅做分享!!! 目录 WEP简介 WPA简介 安全类型 密钥交换 PMK PTK 4次握手 WPA攻击原理 网卡选购 攻击姿态 1-暴力破解 脚本工具 字典 2-Airgeddon 破解 3-KRACK漏洞 4-Rough AP 攻击 5-wifi钓鱼 6-wifite 其他 WEP简介 WEP是WiredEquivalentPri…

小程序开发之我见

现在越来越多的人在用微信&#xff0c;不管是工作还是生活&#xff0c;很多都离不开微信&#xff0c;不管是吃饭、买东西&#xff0c;手机内存虽然在增加&#xff0c;但是也总觉得不够用&#xff0c;然后也不喜欢装太多的软件&#xff0c;所以微信小程序越来越多人喜欢用&#…

随着Batch size增加,最佳learning rate如何选择?

最近读到《Surge Phenomenon in Optimal Learning Rate and Batch Size Scaling》这篇论文&#xff0c;里面通过实验和理论证明了learning rate和batch size之间的关系&#xff0c;觉得很有意思&#xff0c;就简答写个blog记录下。 1. 简介 在影响模型训练效果的所有参数中&a…

PD虚拟机占用多少内存?使用电脑的虚拟内存会损害电脑吗

当我们讨论虚拟机及其对电脑性能的影响时&#xff0c;常常会出现两个关键问题&#xff1a;“PD虚拟机需要占用多少内存&#xff1f;”以及“启用电脑的虚拟内存是否会损害硬件&#xff1f;”对于依赖虚拟机进行日常工作的用户而言&#xff0c;这些问题尤为重要。 在本文中&…

Qt_按钮类控件

目录 1、QAbstractButton 2、设置带图标的按钮 3、设置带有快捷键的按钮 4、QRadioButtion&#xff08;单选按钮&#xff09; 4.1 QButtonGroup 5、QCheckBox 结语 前言&#xff1a; 按钮类控件是Qt中最重要的控件类型之一&#xff0c;该类型的控件可以通过鼠标的点击…

【案例72】Apache检测到目标 URL 存在 http host 头攻击漏洞的解决方案

在网络安全中&#xff0c;我们经常会遇到各种漏洞和攻击&#xff0c;其中 http host 头攻击漏洞是一种比较常见的安全问题。最近&#xff0c;我在处理一个项目时&#xff0c;检测到目标 URL 存在 http host 头攻击漏洞&#xff0c;下面我将分享两种Apache解决这个问题的方法。 …

浅谈线性表——队列

文章目录 一、什么是队列&#xff1f;二、队列底层三、自我实现一个队列3.1、链式存储3.1.1、单向链表实现队列的实现代码3.1.2、双向链表实现队列的实现代码 3.2、顺序存储3.2.1、循环队列的实现代码 一、什么是队列&#xff1f; 队列是只允许在一端进行插入数据操作&#xf…

性能诊断的方法(五):架构和业务诊断

关于性能诊断的方法&#xff0c;我们可以按照“问题现象—直接原因—问题根源”这样一个思路去归纳。我们先从问题的现象去入手&#xff0c;包括时间的分析、资源的分析和异常信息的分析。接下来再去分析产生问题现象的直接原因是什么&#xff0c;这里我们归纳了自上而下的资源…

Streaming OpenAI results from a Lambda function using Python

题意&#xff1a;使用 Python 从 Lambda 函数流式传输 OpenAI 结果 问题背景&#xff1a; Im trying to stream results from Open AI using a Lambda function on AWS using the OpenAI Python library. For the invoke mode I have: RESPONSE_STREAM. And, using the exampl…

调用智谱AI异步请求流式方法回复

官方代码可以去查看https://github.com/MetaGLM/zhipuai-sdk-java-v4/blob/main/src/test/java/com/zhipu/oapi/AllToolsTest.java 效果展示 提问效果: 回答效果: 1、Maven配置 <dependency><groupId>cn.bigmodel.openapi</groupId><artifactId>…

怎么很多张图片拼接成一张?试试这几种图片拼接方法!

怎么很多张图片拼接成一张&#xff1f;在繁忙的现代生活中&#xff0c;我们不断地捕捉和累积着各式各样的图像&#xff0c;它们如同记忆的珍珠&#xff0c;串联起生活的每一个瞬间&#xff0c;然而&#xff0c;随图片数量的激增&#xff0c;管理它们成为了一项挑战&#xff0c;…

JavaScript --函数作用域变量的使用规则(局部和访问)

访问规则&#xff0c;就近原则 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"w…

通过实时平衡生物反馈系统和XSENS动捕系统,改善康复训练流程

最新研究表明&#xff0c;通过将Xsens动作捕捉技术与创新的实时生物反馈设备相结合&#xff0c;可以有效改善患者的康复治疗方式。该解决方案有望显著提高患者的平衡控制和康复效果&#xff0c;帮助其应对各种平衡和运动挑战。 案例关键点一览 一种改善平衡训练的新装置&#x…

C++:STL详解(一)string类的基本介绍与使用方式

✨ Blog’s 主页: 白乐天_ξ( ✿&#xff1e;◡❛) &#x1f308; 个人Motto&#xff1a;实践是检验真理的唯一标准&#xff01;&#xff01;&#xff01;敲代码需要勤快点&#xff01;&#xff01;&#xff01;&#xff01; &#x1f4ab; 欢迎来到我的学习笔记&#xff0…

2024年度10款视频剪辑软件分享

在视频创作日益盛行的今天&#xff0c;一款强大而易于上手的视频剪辑软件成为了每位创作者不可或缺的工具。无论是专业电影制作人、Vlog博主&#xff0c;还是视频编辑爱好者&#xff0c;都能在市场上找到适合自己的那一款。以下是2024年度推荐的10款视频剪辑软件&#xff0c;涵…

OpenHarmony(鸿蒙南向开发)——轻量和小型系统三方库移植指南(二)

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 鸿蒙&#xff08;OpenHarmony&#xff09;南向开发保姆级知识点汇总~ OpenHarmony&#xff08;鸿蒙南向开发&#xff09;——轻量系统芯片移植指南(一) Op…

Windows 环境下 vscode 配置 C/C++ 环境

vscode Visual Studio Code&#xff08;简称 VSCode&#xff09;是一个由微软开发的免费、开源的代码编辑器。它支持多种编程语言&#xff0c;并提供了代码高亮、智能代码补全、代码重构、调试等功能&#xff0c;非常适合开发者使用。VSCode 通过安装扩展&#xff08;Extension…

Spring Cloud常见面试题

1.请说说你用过Spring Cloud哪些组件&#xff1f;这些组件分别有什么作用&#xff1f; 1、注册中心&#xff1a;Eureka、Nacos、Zookeeper、Consul&#xff1b;&#xff08;服务注册&#xff09; 2、负载均衡&#xff1a;Ribbon、LoadBalancer&#xff1b;&#xff08;客户端的…

SpringBoot框架下的房产销售系统开发

第一章 绪 论 1.1背景及意义 房产销售也都将通过计算机进行整体智能化操作&#xff0c;对于房产销售系统所牵扯的管理及数据保存都是非常多的&#xff0c;例如管理员&#xff1b;首页、个人中心、用户管理、销售经理管理、房源信息管理、房源类型管理、房子户型管理、交易订单管…

MYSQL数据库——InnoDB存储引擎

一.逻辑存储结构 二.架构 1.内存结构 1.缓冲池&#xff08;buffer_pool&#xff09; 缓冲池buffer_pool:缓冲池是主内存中的一个区域&#xff0c;里面可缓存磁盘上经常操作的真实数据&#xff0c;在执行增删改查操作时&#xff0c;先操作缓冲池中的数据&#xff08;若缓冲池没…