模拟实现命令行解释器shell

shell本质就是一个进程,它提供了一个用户界面,用于接收用户输入的命令,并将这些命令解释成操作系统能够理解和执行的操作。它充当了用户和操作系统内核之间的中介。例如,在 Linux 系统中,当用户在终端输入ls命令时,shell 会解释这个命令,告诉操作系统去列出当前目录下的文件和目录信息。

下面是模拟实现shell的基本代码:

#include <iostream>
#include <string>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
using namespace std;const int basesize = 1024;
const int argvnum = 64;
const int envnum = 64;//全局的命令行参数表
char *gargv[argvnum];
int gargc = 0;//我自己的环境变量
char *genv[envnum];//全局变量,用来表示退出结果
int lastcode = 0;// 全局的工作路径
char pwd[basesize];
char pwdenv[basesize * 2];string GetName()
{string name = getenv("USER");return name.empty() ? "None" : name;
}string GetHostName()
{char hostname[basesize];gethostname(hostname, sizeof(hostname));;return gethostname(hostname, sizeof(hostname)) != 0 ? "None" : hostname;
}string GetPwd()
{// getcwd获取当前工作路径if (nullptr == getcwd(pwd, sizeof(pwd)))return "None";// 讲获取的当前路径输入到pwdenvsnprintf(pwdenv, sizeof(pwdenv), "PWD=%s", pwd);// 导入环境变量putenv(pwdenv);return pwd;// string pwd = getenv("PWD");// return pwd.empty() ? "None" : pwd;
}string LastDir()
{string curr = GetPwd();if(curr == "/" || curr == "None") return curr;// /home/xzl/xxxsize_t pos = curr.rfind("/");if(pos == std::string::npos) return curr;return curr.substr(pos+1);
}string MakeCommandLine()
{char Command_Line[basesize];snprintf(Command_Line, basesize, "[%s@%s %s]#",\GetName().c_str(), GetHostName().c_str(), LastDir().c_str());return Command_Line;
}// 打印命令行提示符
void PrintCommandLine()
{printf("%s", MakeCommandLine().c_str());fflush(stdout);
}
// 获取用户命令
bool GetCommandLine(char command_buffer[])
{// 获取字符串char *result = fgets(command_buffer, basesize, stdin);if (!result){return false;}command_buffer[strlen(command_buffer) - 1] = 0;if (strlen(command_buffer) == 0)return false;return true;
}//  分析命令
void ParseCommandLine(char command_buffer[])
{memset(gargv, 0, sizeof(gargc));gargc = 0;const char *seq = " ";gargv[gargc++] = strtok(command_buffer, seq);while (gargv[gargc++] = strtok(nullptr, seq));gargc--;
}void debug()
{printf("argc: %d\n", gargc);for (int i = 0; gargv[i]; i++){printf("argv[%d]: %s\n", i, gargv[i]);}
}//执行命令
bool ExecuteCommand()
{pid_t id = fork();if (id < 0)return false;else if (id == 0){// 子进程//执行命令execvpe(gargv[0], gargv,genv);//退出exit(1);}int status = 0;pid_t rid = waitpid(id, &status, 0);if (rid > 0){if(WIFEXITED(status)){lastcode = WEXITSTATUS(status);}else//表示代码异常退出{lastcode = 100;}return true;}return false;
}void AddEnv(const char *item)
{int index = 0;while(genv[index]){index++;}genv[index] = (char*)malloc(strlen(item)+1);strncpy(genv[index],item,strlen(item)+1);index++;genv[index] = nullptr;
}//在shell中
//有些命令,必须由子进程执行
//有些命令,不能由子进程执行,要由shell自己执行 -----内建命令 built command
bool CheckAndExecBuiltCommand()
{//不能让子进程进行,因为子进程退出就结束了,并不能影响下一个进程的工作路径if (strcmp(gargv[0], "cd") == 0){if (gargc == 2){chdir(gargv[1]);lastcode = 0;}else{lastcode = 1;}return true;}else if(strcmp(gargv[0],"export")==0){if(gargc == 2){AddEnv(gargv[1]);lastcode = 0;}else{lastcode = 2;}}else if(strcmp(gargv[0],"env") == 0){for(int i = 0 ;genv[i];i++){printf("%s\n",genv[i]);}lastcode = 0;return true;}else if(strcmp(gargv[0],"echo") == 0){if(gargc == 2){//echo $?//echo $PATH//echo helloif(gargv[1][0] == '$'){if(gargv[1][1] == '?'){printf("%d\n",lastcode);lastcode = 0;}}else{printf("%s\n",gargv[1]);lastcode = 0;}}else{lastcode = 3;}return true;}return false;
}//作为一个shell,获取环境变量应该从系统环境变量获取
//今天外面做不到就直接从父进程shell中获取环境变量
void InitEnv()
{extern char **environ;int index = 0;while (environ[index]){genv[index] = (char*)malloc(strlen(environ[index])+1);strncpy(genv[index],environ[index],strlen(environ[index]));index++;}genv[index] = nullptr;}int main()
{//初始化环境变量表InitEnv();char command_buffer[basesize];while (true){// 打印命令行提示符PrintCommandLine();// 获取用户命令if (!GetCommandLine(command_buffer)){continue;}// printf("%s\n", command_buffer);//  分析命令ParseCommandLine(command_buffer);// 判断是不是内建命令if (CheckAndExecBuiltCommand()){continue;}// debug();// 执行命令ExecuteCommand();}return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

可变电阻和电位器

1.可变电阻和电位器 &#xff08;1&#xff09;可变电阻&#xff1a;阻值可以调整的电阻。 &#xff08;2&#xff09;电位器&#xff1a;为了获得某个电位&#xff08;电势、电压&#xff09;的器件。其本质就是在一个固定阻值的电阻中间增 加一个触点&#xff0c;滑动电阻的中…

.NET Md5加密异常处理

操作系统更新后&#xff0c;软件出现各种bug~ 乍一看&#xff0c;md5加密算法跪了&#xff01; 为啥会出现md5算法崩溃呢&#xff1f; 原因是操作系统开启了FIPS&#xff0c;而md5并不是FIPS&#xff08;Federal Information Processing Standards 即&#xff08;美国&#x…

RK3568平台开发系列讲解(PWM篇)PWM 子系统框架

🚀返回专栏总目录 文章目录 一、PWM 设备驱动层二、PWM 核心层三、PWM 适配器驱动层沉淀、分享、成长,让自己和他人都能有所收获!😄 📢整个 PWM 子系统可以用下面的框图来描述: 再上图中 PWM 子系统被划分为了三个层次, 分别为用户空间、 内核空间和硬件层, 内核空…

CSAPP Cache Lab(缓存模拟器)

前言 理解高速缓存对 C 程序性能的影响&#xff0c;通过两部分实验达成&#xff1a;编写高速缓存模拟器&#xff1b;优化矩阵转置函数以减少高速缓存未命中次数。Part A一开始根本不知道要做什么&#xff0c;慢慢看官方文档&#xff0c;以及一些博客&#xff0c;和B站视频&…

android studio Terminal控制台命令打包 apk

在Android Studio中&#xff0c;可以使用Gradle命令来构建APK。 1&#xff0c;打开终端&#xff1a; &#xff08;Windows上为Terminal&#xff0c;macOS或Linux上为Terminal或Shell&#xff09;&#xff0c;然后开始输入命令执行构建。 2&#xff0c;转到项目的根目录&…

【趣味升级版】斗破苍穹修炼文字游戏HTML,CSS,JS

目录 图片展示 开始游戏 手动升级&#xff08;满100%即可升级&#xff09; 升级完成&#xff0c;即可解锁打怪模式 新增功能说明&#xff1a; 如何操作&#xff1a; 完整代码 实现一个简单的斗破苍穹修炼文字游戏&#xff0c;你可以使用HTML、CSS和JavaScript结合来构建…

MySQL查询缓存详解

一、查询缓存的基本概念 MySQL 的查询缓存是一种用于存储查询结果的内存区域。当一个查询被执行时&#xff0c;MySQL 首先检查查询缓存中是否已经存在相同的查询结果。如果存在&#xff0c;直接从查询缓存中返回结果&#xff0c;而无需再次执行查询语句&#xff0c;从而大大提高…

C#里怎么样使用Array.BinarySearch函数?

C#里怎么样使用Array.BinarySearch函数? 因为二分算法如此重要,所以要多加练习。 但是它的返回值,也有三种状态,导致很多人使用它的时候, 也感觉到迷惑的。 在这里的例子演示了三种返回值的使用: /** C# Program to Search an element with Array Indices*/ using …

hadoop环境配置-vm安装+麒麟ubantu

一.VM版本 选择16版本&#xff0c;15版本存在windows蓝屏的情况&#xff0c;也不用设置HV等相关设置 激活下载参考下述博客&#xff1a;https://blog.csdn.net/matrixlzp/article/details/140674802 提前在bois打开SVM设置&#xff0c;不设置无法打开新建的虚拟机 ubantu下载…

C#结合.NET框架快速构建和部署AI应用

在人工智能&#xff08;AI&#xff09;的浪潮中&#xff0c;C#作为一种功能强大且类型安全的编程语言&#xff0c;为AI工程开发提供了坚实的基础。C#结合.NET框架&#xff0c;使得开发者能够快速构建和部署AI应用。本文将通过一个简单的实例&#xff0c;展示如何使用C#进行AI工…

会议直击|美格智能亮相2024紫光展锐全球合作伙伴大会,融合5G+AI共拓全球市场

11月26日&#xff0c;2024紫光展锐全球合作伙伴大会在上海举办&#xff0c;作为紫光展锐年度盛会&#xff0c;吸引来自全球的众多合作伙伴和行业专家、学者共同参与。美格智能与紫光展锐竭诚合作多年&#xff0c;共同面向5G、AI和卫星通信为代表的前沿科技&#xff0c;聚焦技术…

工业公辅车间数智化节能头部企业,蘑菇物联选择 TDengine 升级 AI 云智控

小T导读&#xff1a;在工业节能和智能化转型的浪潮中&#xff0c;蘑菇物联凭借其自研的灵知 AI 大模型走在行业前沿&#xff0c;为高能耗设备和公辅能源车间提供先进的 AI 解决方案。此次采访聚焦于蘑菇物联与 TDengine 的合作项目&#xff0c;通过 AI 云智控平台的建设&#x…

华为IPD流程学习之——深入解读123页华为IPD流程体系设计方法论PPT

该方案全面介绍了华为IPD流程体系设计方法论&#xff0c;包括流程体系建设的背景、理念、架构、核心特征、构建模型、与组织和战略的关系、运营机制、数字化转型以及流程管理组织等内容&#xff0c;旨在为企业提供一套系统的流程体系建设指导&#xff0c;以提升运营效率、质量和…

插入数据报错:Data truncation: Out of range value for column ‘id‘ at row 1

问题描述&#xff1a; 使用Mybatis-plus插入用户数据报错 错误&#xff1a; SQL: INSERT INTO t_user ( id, username, pwd ) VALUES ( ?, ?, ? ) Cause: com.mysql.cj.jdbc.exceptions.MysqlDataTruncation: Data truncation: Out of range value for column ‘id’ at …

IntelliJ+SpringBoot项目实战(十九)--在API接口中实现SpringSecurity登录并生成JWT的accessToken

在上节中实现了SpringBootJWT登录&#xff0c;但是介绍的登录是基于SpringSecurity的默认登录页实现的。但是项目开发目前很多都是前后端分离的&#xff0c;也就是VUEAPI接口的模式。所以我们需要实现在API接口中使用SpringSecurity登录。 首先需要在WebSecurityConfig中增加Au…

C/C++中的调用约定

在C/C编程中&#xff0c;调用约定(calling conventions)是一组指定如何调用函数的规则。主要在你调用代码之外的函数(例如OS API&#xff0c;操作系统应用程序接口)或OS调用你(如WinMain的情况)时起作用。如果编译器不知道正确的调用约定&#xff0c;那么你很可能会遇到非常奇怪…

流水线并行,重计算:GPipe;1F1B(一前一后)调度机制

目录 GPipe 一、GPipe的背景与目的 二、GPipe的功能与特点 三、GPipe的应用与效果 四、GPipe的开源与可扩展性 1F1B(一前一后)调度机制 一、背景与基本概念 二、1F1B调度机制的要求 三、应用与挑战 GPipe 是一个基于Lingvo(Lingvo是Google基于TensorFlow二次开发的…

1-1 Gerrit实用指南

注&#xff1a;学习gerrit需要拥有git相关知识&#xff0c;如果没有学习过git请先回顾git相关知识点 黑马程序员git教程 一小时学会git git参考博客 git 实操博客 1.0 定义 Gerrit 是一个基于 Web 的代码审查系统&#xff0c;它使用 Git 作为底层版本控制系统。Gerrit 的主要功…

如何解决服务器扫描出的ASP木马问题

随着互联网的发展&#xff0c;网站安全问题日益凸显。其中&#xff0c;ASP&#xff08;Active Server Pages&#xff09;木马因其隐蔽性和危害性成为攻击者常用的手段之一。本文将详细介绍如何检测和清除服务器上的ASP木马&#xff0c;以保障网站的安全。 1. ASP木马概述 ASP…

基于TensorFlow的手写体数字识别训练与测试

需求&#xff1a; 选择一个最简单的细分方向&#xff0c;初步了解AI图像识别的训练、测试过程TensorFlow、PyTorch、c&#xff0c;三种代码方案&#xff0c;先从TensorFlow入手探讨最基本问题的优化问题 总结&#xff1a; 基于TensorFlow的python代码库自带了mnist 训练数据…