【Linux】自定义shell(命令行解释器)

原理: shell是命令行解释器,当有命令需要执行时,shell创建子进程,让子进程执行命令,而shell只需等待子进程退出即可。

其中我们使用了下面这几个函数:

  • 获取命令行(fgets函数)。
  • 解析命令行(strtok分割字符串)。
  • 创建子进程(fork函数)。
  • 替换子进程(exec函数族)。
  • 等待子进程退出(waitpid函数)

 实现简易命令解释行的过程中我们遇到了一些问题:

cd,export等內键命令,在子进程下修改无法影响到bash,所以我们增加了函数来判断命令是否为內键命令,并判断其是否为空,使用chdir修改其所在路径通过argv[1]取出要到的路径。

但是我们发现如果进入的是..  上级路径的话 就会变成下面这样

 

我们的目录名称直接变成了..,此时我们需要使用 snprintf函数 将temp写入pwd中。

以下为简易实现的代码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/wait.h>
#include<sys/types.h>
#define SIZE 1024
#define MAX_ARGC 64
#define SEP " "
char *argv[MAX_ARGC];
char PWD[SIZE];
 const char* HostName()
 {
    char *hostname=getenv("HOSTNAME");
    if(hostname) return hostname;
    else return "none";
 }
 const char* UserName()                       
 {                                            
   char *hostname=getenv("USER");         
   if(hostname) return hostname;              
   else return "none";                        
 }         
 const char* CurrentWorkDir()   
 {                    
   char *hostname=getenv("PWD");         
   if(hostname) return hostname;              
   else return "none";                        
 }  
 char *Home()
 {
   return getenv("HOME");
 }
 int Interactive(char out[],int size)
 {
                                                                                                                                                                                                   
   printf("[%s@%s %s]$",UserName(),HostName(),CurrentWorkDir());
   fgets(out,size,stdin);
   out[strlen(out)-1]=0;//'\0'
   return strlen(out);
 }
void Split(char in[])
 {
   int i=0;
   argv[i++]=strtok(in,SEP);
     while(argv[i++]=strtok(NULL,SEP));
 }
 void Execute()
 {
 pid_t id=fork();
 if(id==0)
 {
   execvp(argv[0],argv);
   exit(1);
 }
   pid_t rid=waitpid(id,NULL,0);
   printf("run done,rid: %d\n",rid);
 }
 int BuildinCmd()
 {
   int ret=0;
   //1.检测是否为内建命令 是1 否0
   if(strcmp("cd",argv[0])==0)                                                                                                                                                                     
   {
     ret=1;
     char *target=argv[1];
     if(!target) target=Home();
     chdir(target);
     char temp[1024];
      getcwd(temp,1024);
      snprintf(PWD,SIZE,"PWD=%s",temp);
      putenv(PWD);
  }
   //2.执行
   return ret;
 }
 int main()
 {
  //1.打印命令行提示符,获取用户输入的命令字符串
  while(1)
  {
   char commandline[SIZE];
   int n= Interactive(commandline,SIZE);
   if(n==0) continue;
   //2.对命令行进行切割
   Split(commandline);
   //3.处理内建命令
   n=BuildinCmd();
   if(n) continue;
   //4.执行这个命令
   Execute();
  }
   //int j=0;
   //for(j=0;argv[j];j++)
   //{
   //  printf("argv[%d]: %s\n",j,argv[j]);
   //}
   return 0;
 }                                       

 Makefile文件的配置:

myshell:myshell.c
		gcc -o $@ $^ 
.PHONY:clean
	rm -f myshell

演示结果如下

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++ 66 之 类模版

#include <iostream> #include <string> using namespace std;// 习惯性 < >中 类模板用class 普通的函数模板就用typename // template<class NAMETYPE, class AGETYPE> template<class NAMETYPE, class AGETYPE int> // 可以设置默认的类型值…

Beyond Compare 文件对比工具下载2024最新版-Beyond Compare详细安装步骤

Beyond Compare是一款不可多得的专业级的文件夹和文件对比工具。使用它可以很方便地对比出两个文件夹或者文件的不同之处&#xff0c;相差的每一个字节用颜色加以表示&#xff0c;查看方便&#xff0c;支持多种规则对比。是程序工程师以及上班族必备的有效辅助工具 安 装 包 获…

并发编程理论基础——解决死锁【等待-通知机制优化循环等待】(五)

在破坏占用且等待条件时&#xff0c;如果使用while死循环 在并发量不大的情况下循环几十上百次也就好了如果while中执行方法时间比较长&#xff0c;或者并发量大时&#xff0c;可能要循环上万次才能获取到锁&#xff0c;非常消耗CPU 相较于使用while死循环&#xff0c;更好的方…

位图法-有效的数独

有效的数独&#xff0c;主要是判断每行每列每宫有无重复元素。 每行每列用二重循环&#xff0c;每宫比较复杂&#xff0c;需要考虑每一宫的坐标与二重循环ij对应关系 行i&#xff0c;每一宫3行&#xff0c;3列 x3*(i/3)j/3 y3*(i%3)j%3

超简洁的待办事项自托管便签todo

什么是todo todo 是一个自托管的 todo web 应用程序&#xff0c;可让您以简单且最少的方式跟踪您的 todo。 搭建 使用Docker命令行方式进行搭建 docker run -d -p 8000:8000 -v todo_db:/usr/local/go/src/todo/todo.db prologic/todo Docker-compose.yml version: 3 ​ se…

全球首个开源类Sora模型大升级,16秒720p画质电影感爆棚!代码和权重全面开源!

目录 01 视频界开源战士 02 深度解码技术 03 打破闭环&#xff0c;开源赋能 潞晨Open-Sora团队刚刚在720p高清文生视频质量和生成时长上实现了突破性进展&#xff01; 全新升级的Open-Sora不仅支持无缝生成任意风格的高质量短片&#xff0c;更令人惊喜的是&#xff0c;团队选…

BC153 [NOIP2010]数字统计

数字统计 一.题目描述二.输入描述&#xff1a;三.输出描述&#xff1a;四.数字范围五.题目思路六.代码实现 一.题目描述 请统计某个给定范围[L, R]的所有整数中&#xff0c;数字2出现的次数。 比如给定范围[2, 22]&#xff0c;数字2在数2中出现了1次&#xff0c;在数12中出现1次…

VM4.3 二次开发04 方案输出结果设置

方案输出结果设置&#xff0c;这个设置是为了在二次开发的上位机软件中显示我们想要的数据&#xff0c;和在二开中如何获取这些结果。 打开方案点下如中的图标。 打开如下图。 再点点红色圈出来的图标&#xff0c;打开参数设置界面。 输出设置可以要输出的数据和参数名称。点上…

基于YOLOv10深度学习的高密度人脸智能检测与统计系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战、目标检测

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

Java23种设计模式(二)

1、单例模式 单例模式&#xff08;Singleton Pattern&#xff09;是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式&#xff0c;它提供了一种创建对象的最佳方式。 这种模式涉及到一个单一的类&#xff0c;该类负责创建自己的对象&#xff0c;同时确保只有…

Linux系统之mtr命令的基本使用

Linux系统之mtr命令的基本使用 一、mtr命令介绍二、mtr命令使用帮助2.1 mtr命令的帮助信息2.2 mtr帮助信息解释 三、安装mtr工具四、mtr命令的基本使用4.1 直接使用4.2 设定ping次数4.3 禁用DNS解析4.4 显示IP地址4.5 调整间隔 五、总结 一、mtr命令介绍 mtr命令是一个网络诊断…

Hype4.0 for Mac软件下载-Hype for Mac HTML5 创作工具下载附加详细安装步骤

Hype 4 Pro Mac正式版是款功能实用的动画创作工具。Hype 4 Pro Mac最新版可以帮您轻松创建令人惊叹的动画和交互式网页内容。并且Hype 4 Pro Mac还可被设计师用来创建动画&#xff0c;为网页、信息图形、演示文稿、数字杂志、广告、iBooks、教育内容、应用程序原型、作品集、动…

46. 【Java教程】Optional 类

上一小节&#xff0c;我们接触到了Optional类&#xff0c;但没有详细展开介绍&#xff0c;Optional类也是 Java 8 新加入的类。本小节我们就来学习一下这个类&#xff0c;你将了解到Optional类的解决了什么问题&#xff0c;如何创建Optioanl类的对象&#xff0c;它又有哪些常用…

【MySQL进阶之路 | 高级篇】SQL执行过程

1. 客户端与服务器的连接 运行中的服务器程序与客户端程序本质上都是计算机的一个进程&#xff0c;所以客户端进程向服务器端进程发送请求并得到相应过程的本质就是一个进程间通信的过程. 我们可以使用TCP/IP网络通信协议&#xff0c;命名管道和共享内存等方式&#xff0c;实…

2024/6/18 英语每日一段

While refusing to attribute various problems to specific labs in order to protect the investigators’ sources, the Gladstone AI team told The Washington Times that it found various assessments of security issues were “totally untethered to reality” about…

【STM32】GPIO简介

1.GPIO简介 GPIO是通用输入输出端口的简称&#xff0c;简单来说就是STM32可控制的引脚&#xff0c;STM32芯片的GPIO引脚与外部设备连接起来&#xff0c;从而实现与外部通讯、控制以及数据采集的功能。 STM32芯片的GPIO被分成很多组&#xff0c;每组有16个引脚。 最基本的输出…

RockChip Android12 System之Datetime

一:概述 本文将针对Android12 Settings二级菜单System中Date&time的UI修改进行说明。 二:Date&Time 1、Activity packages/apps/Settings/AndroidManifest.xml <activityandroid:name="Settings$DateTimeSettingsActivity"android:label="@stri…

ubuntu 18.04 安装vnc

如何在Ubuntu 18.04安装VNC | myfreax sudo apt install xfce4 xfce4-goodies xorg dbus-x11 x11-xserver-utils sudo apt install tigervnc-standalone-server tigervnc-common vncserver sudo apt install xfce4 xfce4-goodies xorg dbus-x11 x11-xserver-utils sudo apt ins…

胡说八道(24.6.17)——STM32以及通信杂谈

之前的文章中咱们谈到了STM32的时钟&#xff0c;今天我们来联系实际&#xff0c;来看看内部时钟下和外部时钟下的两种不同时钟的电平翻转。本次终于有硬件了&#xff0c;是最基础的STM32F103C8T6。 首先是&#xff0c;内部时钟的配置操作。 系统的内部时钟是72MHz&#xff0c;由…

2021年9月电子学会青少年软件编程 中小学生Python编程等级考试三级真题解析(选择题)

2021年9月Python编程等级考试三级真题解析 选择题(共25题,每题2分,共50分) 1、使用map函数可以实现列表数据元素类型的转换,而无需通过循环。则将列表L=[1,3,5,7,9]转换为列表[1,3,5,7,9]的函数写法为 A、map(int,L) B、list(map(int,L)) C、map(L,int) D、list(map…