自主shell命令行解释器

目标

  • 能处理普通命令
  • 能处理内建命令

实现原理

用下面的时间轴来表示时间发生次序。时间从左向右。shell由标识为sh的方块,它随着时间从左向右移动。
shell从用户读入字符串“ls”。shell建立一个新的进程,然后等待进程中运行ls程序并等待进程结束。
在这里插入图片描述
然后shell读取新的一行输入,建立一个新的进程在这个进程中运行程序,等待进程结束。
所以写一个shell,需要循环一下过程

  1. 获取命令行
  2. 解析命令行
  3. 建立子进程(fork)
  4. 替换子进程(execvp)
  5. 父进程等待子进程退出(wait)

源码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<string>#define COMMAND_SIZE 1024
#define FORMAT "[%s@%s %s]# "//下面是shell定义的全局数据
// 1.命令行参数表
#define MAXARGC 128
char *g_argv[MAXARGC];
int g_argc = 0;// 2.环境变量表
#define MAX_ENV 100
char* g_env[MAX_ENV];
int g_envs = 0;char cwd[1024];
char cwdenv[1024];// last code exit
int lastcode = 0;const char* GetUserName()
{const char* name=getenv("USER");return name == NULL ? "None" : name;
}const char* GetHostName()
{const char* host=getenv("HOSTNAME");return host == NULL ? "None" : host;
}const char* GetPwd()
{//const char* pwd=getenv("PWD");const char* pwd = getcwd(cwd,sizeof(cwd));if(pwd != NULL){snprintf(cwdenv,sizeof(cwdenv),"PWD=%s",cwd);putenv(cwdenv);}return pwd == NULL ? "None" : pwd;
}const char* GetHome()
{const char* home=getenv("HOME");return home == NULL ? "None" : home;
}const char* GetOldpwd()
{const char* oldpwd=getenv("OLDPWD");return oldpwd == NULL ? "None" : oldpwd;
}// 处理目录
std::string DirName(const char* pwd)
{
#define SLASH "/"std::string dir = pwd;if(dir == SLASH) return SLASH;auto pos = dir.rfind(SLASH);if(pos == std::string::npos) return pwd;return dir.substr(pos+1);
}void InitEnv()
{extern char** environ;memset(g_env,0,sizeof(g_env));g_envs = 0;//简化操作,从父进程获得环境变量for(int i = 0; environ[i]; i++){g_env[i]=(char*)malloc(strlen(environ[i])+1);strcpy(g_env[i],environ[i]);g_envs++;}g_env[g_envs] = NULL;//2.导成环境变量for(int i = 0; g_env[i]; i++){putenv(g_env[i]);}environ = g_env;
}void MakeCommandLine(char cmd_prompt[], int size)
{snprintf(cmd_prompt, size, FORMAT, GetUserName(), GetHostName(), DirName(GetPwd()).c_str());
}void PrintfCommandPrompt()
{char command[COMMAND_SIZE];MakeCommandLine(command,COMMAND_SIZE);printf("%s",command);fflush(stdout);
}// ls -a -l => "ls -a -l"字符串
bool GetCommandLine(char* out, int size)
{char* c = fgets(out, size, stdin);if(c==NULL) return false;out[strlen(out)-1]=0; // 清理\nif(strlen(out) <= 0) return false;return true;
}// 命令行分析 "ls -a -l" => "ls" "-a" "-l"
bool CommandParse(char* commandline)
{
#define SEP " "g_argc = 0;g_argv[g_argc++] = strtok(commandline, SEP);while((bool)(g_argv[g_argc++] = strtok(nullptr,SEP)));g_argc--;return g_argc > 0 ? true :false;
}// command
bool cd()
{//cdif(g_argc == 1){std::string home = GetHome();if(home.empty()) return true;chdir(home.c_str());}else {std::string where = g_argv[1];//cd ~if(where == "~"){std::string home = GetHome();chdir(home.c_str());}//cd -if(where == "-"){std::string oldpwd = GetOldpwd();chdir(oldpwd.c_str());}chdir(where.c_str());}return true;
}
void PrintEnv()
{extern char** environ;for(int i = 0; environ[i];++i){printf("%-2d->%s\n",i,environ[i]);}
}bool CheckAndExcuteBuildin()
{std::string cmd = g_argv[0];if(cmd == "cd"){cd();return true;}if(cmd == "test"){PrintEnv();return true;}return false;
}void Excute()
{pid_t id = fork();if(id == 0) // child{execvp(g_argv[0], g_argv);exit(1);}// fatherint status = 0;pid_t rid = waitpid(id,&status,0);if(rid > 0){lastcode=WEXITSTATUS(status);        }
}void test_GetCommandLine(char* str)
{printf("%s\n", str);
}
void test_CommandParse()
{for(int i = 0; i < g_argc; ++i)std::cout << g_argv[i] << " " ;
}
void test_InitEnv()
{for(int i = 0; g_env[i]; i++){printf("env[%2d]->%s\n",i,g_env[i]);}printf("envs: %d\n",g_envs);
}int main()
{InitEnv();while(true){// 1. 输出命令行提示符  [jfs@superg-alicloud myshell]$PrintfCommandPrompt();// 2. 获取用户输入的命令 ls -a -lchar commandline[COMMAND_SIZE];if(!GetCommandLine(commandline, sizeof(commandline))) continue;//test_GetCommandLine(commandline);// 3. 命令行分析,"ls -a -l" => "ls" "-a" "-l"if(!CommandParse(commandline))continue;//test_CommandParse();// 4.检测并处理内建命令if(CheckAndExcuteBuildin())continue;// 5. 执行命令Excute();}return 0;
}

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

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

相关文章

如何在sheel中运行Spark

启动hdfs集群&#xff0c;打开hadoop100:9870&#xff0c;在wcinput目录下上传一个包含很多个单词的文本文件。 启动之后在spark-shell中写代码。 // 读取文件&#xff0c;得到RDD val rdd1 sc.textFile("hdfs://hadoop100:8020/wcinput/words.txt") // 将单词进行切…

【入门】数字走向II

描述 输入整数N&#xff0c;输出相应方阵。 输入描述 一个整数N。&#xff08; 0 < n < 10 ) 输出描述 一个方阵&#xff0c;每个数字的场宽为3。 #include <bits/stdc.h> using namespace std; int main() {int n;cin>>n;for(int in;i>1;i--){for(…

Python自动化-python基础(下)

六、带参数的装饰器 七、函数生成器 运行结果&#xff1a; 八、通过反射操作对象方法 1.添加和覆盖对象方法 2.删除对象方法 通过使用内建函数: delattr() # 删除 x.a() print("通过反射删除之后") delattr(x, "a") x.a()3 通过反射判断对象是否有指定…

重新定义高性能:Hyperlane —— Rust生态中的极速HTTP服务器

重新定义高性能&#xff1a;Hyperlane —— Rust生态中的极速HTTP服务器 &#x1f680; 为什么选择Hyperlane&#xff1f; 在追求极致性能的Web服务开发领域&#xff0c;Hyperlane 凭借其独特的Rust基因和架构设计&#xff0c;在最新基准测试中展现出令人惊艳的表现&#xff…

通俗的理解MFC消息机制

1. 消息是什么&#xff1f; 想象你家的门铃响了&#xff08;比如有人按门铃、敲门、或者有快递&#xff09;&#xff0c;这些都是“消息”。 在 MFC 中&#xff0c;消息就是系统或用户触发的各种事件&#xff0c;比如鼠标点击&#xff08;WM_LBUTTONDOWN&#xff09;、键盘输入…

腾讯开源SuperSonic:AI+BI如何重塑制造业数据分析?

目录 一、四款主流ChatBI产品 二、ChatBI应用案例与实际落地情况 三、SuperSonic底层原理 3.1、Headless BI 是什么 3.2、S2SQL 是什么 3.3、SuperSonic 平台架构 四、ChatBI应用细节深挖 五、与现有系统的集成方案 六、部署和安全 七、开源生态、可扩展性与二次开…

AI生成视频推荐

以下是一些好用的 AI 生成视频工具&#xff1a; 国内工具 可灵 &#xff1a;支持文本生成视频、图片生成视频&#xff0c;适用于广告、电影剪辑和短视频制作&#xff0c;能在 30 秒内生成 6 秒的高清视频&#xff08;1440p&#xff09;&#xff0c;目前处于免费测试阶段。 即…

OrangePi Zero 3学习笔记(Android篇)5 - usbutils编译(更新lsusb)

目录 1. Ubuntu中编译 2. AOSP编译 3. 去掉原来的配置 3. 打包 4. 验证lsusb 在Ubuntu中&#xff0c;lsusb的源代码源自usbutils。而OrangePi Zero 3中lsusb的位置可以看文件H618-Android12-Src/external/toybox/Android.bp&#xff0c; "toys/other/lsusb.c",…

bcm5482 phy 场景总结

1,BCM5482是一款双端口10/100/1000BASE-T以太网PHY芯片,支持多种速率和双工模式。其配置主要通过MDIO(Management Data Input/Output)接口进行,MDIO接口用于访问PHY芯片内部的寄存器,从而配置网络速率、双工模式以及其他相关参数。 a,具体以下面两种场景举例 2. 寄存器和…

RedHat磁盘的添加和扩容

前情提要 &#x1f9f1; 磁盘结构流程概念图&#xff1a; 物理磁盘 (/dev/sdX) └── 分区&#xff08;如 /dev/sdX1&#xff09;或整块磁盘&#xff08;直接使用&#xff09; └── 物理卷 (PV, 用 pvcreate) └── 卷组 (VG, 用 vgcreate) …

Lua—元表(Metatable)

原表解析 在 Lua table 中我们可以访问对应的 key 来得到 value 值&#xff0c;但是却无法对两个 table 进行操作(比如相加)。 因此 Lua 提供了元表(Metatable)&#xff0c;允许我们改变 table 的行为&#xff0c;每个行为关联了对应的元方法。 setmetatable(table,metatable…

一种运动平台扫描雷达超分辨成像视场选择方法——论文阅读

一种运动平台扫描雷达超分辨成像视场选择方法 1. 专利的研究目标与意义1.1 研究目标1.2 实际意义2. 专利的创新方法与技术细节2.1 核心思路与流程2.1.1 方法流程图2.2 关键公式与模型2.2.1 回波卷积模型2.2.2 最大后验概率(MAP)估计2.2.3 统计约束模型2.2.4 迭代优化公式2.3 …

Listremove数据时报错:Caused by: java.lang.UnsupportedOperationException

看了二哥的foreach陷阱后&#xff0c;自己也遇见了需要循环删除元素的情况&#xff0c;立马想到了当时自己阴差阳错的避开所有坑的解决方式&#xff1a;先倒序遍历&#xff0c;再删除。之前好使&#xff0c;但是这次不好使了&#xff0c;报错Caused by: java.lang.UnsupportedO…

Ceph集群OSD运维手册:基础操作与节点扩缩容实战

#作者&#xff1a;stackofumbrella 文章目录 一、Ceph集群的OSD基础操作查看osd的ID编号查看OSD的详细信息查看OSD的状态信息查看OSD的统计信息查看OSD在主机上的存储信息查看OSD延迟的统计信息查看各个OSD使用率集群暂停接收数据集群取消暂停 OSD写入权重操作查看默认OSD操作…

PHP框架在分布式系统中的应用!

随着互联网业务的快速发展&#xff0c;分布式系统因其高可用性、可扩展性和容错性成为现代应用架构的主流选择。而PHP作为一门成熟的Web开发语言&#xff0c;凭借其简洁的语法、丰富的框架生态和持续的性能优化&#xff0c;逐渐在分布式系统中崭露头角。本文将深入探讨PHP框架在…

MySQL 索引(一)

文章目录 索引&#xff08;重点&#xff09;硬件理解磁盘盘片和扇区定位扇区磁盘的随机访问和连续访问 软件方面的理解建立共识索引的理解 索引&#xff08;重点&#xff09; 索引可以提高数据库的性能&#xff0c;它的价值&#xff0c;在于提高一个海量数据的检索速度。 案例…

环境搭建-复现ST-GCN输出动作分类视频(win10+openpose1.7.0+VS2019+CMake3.30.1+cuda11.1)

这次我们安装github.com/yysijie/st-gcn这个作者源码环境&#xff0c;安装流程十分复杂这里介绍大体流程。 1.首先编译openpose的python API接口这个编译难度较大&#xff0c;具体参考博文&#xff1a;windows编译openpose及在python中调用_python openpose-CSDN博客 这个博…

HTML属性

HTML&#xff08;HyperText Markup Language&#xff09;是网页开发的基石&#xff0c;而属性&#xff08;Attribute&#xff09;则是HTML元素的重要组成部分。它们为标签提供附加信息&#xff0c;控制元素的行为、样式或功能。本文将从基础到进阶&#xff0c;全面解析HTML属性…

2025年“深圳杯”数学建模挑战赛C题国奖大佬万字思路助攻

完整版1.5万字论文思路和Python代码下载&#xff1a;https://www.jdmm.cc/file/2712073/ 引言 本题目旨在分析分布式能源 (Distributed Generation, DG) 接入配电网系统后带来的风险。核心风险评估公式为&#xff1a; R P_{loss} \times C_{loss} P_{over} \times C_{over}…

两数相加(2)

2. 两数相加 - 力扣&#xff08;LeetCode&#xff09; 解法&#xff1a; class Solution { public:ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {ListNode * dummy new ListNode(0);int carry 0;ListNode * head dummy;while (l1 ! nullptr || l2 ! nullptr ||…