手写简易shell

news2024/11/24 11:38:42

我们如果要写一个简易的shell我们要,其实我们搞一个程序替换就行了。
我们分为五部完成


在其中我们最难搞的就是环境变量的更新,因为当我们搞一个子程序出来时,我们子进程的环境变量表是从父进程继承下来的,当我们用cd命令时只会更改子进程的cwd,而不会改变系统shell的cwd。因为cd命令本是是一个自建命令(我认为的自建命令就会改变环境变量的命令),而遇到cd这样的命令我们需要手动更改shell的cwd,就是做一个特殊处理。而当我们每次更改后我们也需要手动更改我们自己myshell的pwd环境变量。

重点一:更新pwd


我们在每次获取系统shell的pwd时,还需要手动修改一下自己env的pwd

说实话直接讲会很晦涩不如源码自己研究
我这里直接展现源码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<unistd.h>

 #include <sys/types.h>
#include <sys/wait.h>

extern char**environ;

using namespace std;

const int maxsize=1024;

//获取命令提示:
char comandInfo[maxsize];
int comandInfoSize=0;

//获取命令
char getComand[maxsize];
//处理后的命令
char *gargv[64];
int gargc=0;

//获取shell的pwd
char pwd[maxsize];
//更新pwdenv
char pwdenv[maxsize];
//为子进程创建环境变量
char *env[64];


string getNAME()
{
    string name=getenv("USER");
    if(name.empty())
    {
        return "NONE";   
    }
    return name;
}

string getHOSTNAME()
{
    string hostname=getenv("HOSTNAME");
    if(hostname.empty())
    {
        return "NONE";
    }
    return hostname ;
}

string getPWD()
{
    getcwd(pwd,sizeof(pwd));
    snprintf(pwdenv,sizeof(pwdenv),"PWD=%s",pwd);
    putenv(pwdenv);
    return pwd;
}


 string MakeComandInfo()
 {
    snprintf(comandInfo,maxsize,"[%s@%s %s]*",getNAME().c_str(),getHOSTNAME().c_str(),getPWD().c_str());
    return comandInfo;
 }


void  printComandInfo()//打印命令提示
{
    memset(comandInfo,0,sizeof(comandInfo));
    printf("%s",MakeComandInfo().c_str());
    fflush(stdout);
}



bool GetComand()
{
    char*str= fgets(getComand,maxsize,stdin); 
    if(str==NULL)
        return false;
    getComand[strlen(str)-1]=0;
    return true;
}


void  HandComand()
{
    gargc=0;
    memset(gargv,0,sizeof(gargv));
    char buff[]=" ";
    gargv[gargc++]= strtok(getComand,buff);
    while(gargv[gargc++]=strtok(NULL,buff));
    gargc--;
}

void debug()
{
    //printf("%d\n",strlen(env[1]));
    for(int i=0;env[i];i++)
    {
        printf("argv[%d]:%s\n",i,gargv[i]);
    }
}



void MyShell()
{
     execvpe(gargv[0],gargv,env);
     exit(0);
}

void run()
{
    pid_t id=fork();
    if(id==0)
    {
        MyShell();
        exit(1);
    }
    else if(id>0)
    {
        int status=0;
        pid_t cid=waitpid(id,&status,0);
    }
}

bool CheckBiuldComand()
{
    if(strcmp("cd",gargv[0])==0)
    {
        if(gargc==2)
        {
            for(int i=0;environ[i];i++)
                if(strncmp(environ[i],"PWD",3)==0)
                    cout<<environ[i]<<endl;
            chdir(gargv[1]);
        }
        return true;
    }
    return false;
}

void Initenv()
{
    int i;
    for(i=0;environ[i];i++)
    {
        //cout<<environ[i]<<endl;
        env[i]=(char*)malloc(strlen(environ[i]+1));
        strncpy(env[i],environ[i],strlen(environ[i]));
    }
    env[i]=nullptr;
}
int main()
{
    
    while(1)
    {
        Initenv();
         printComandInfo(); //打印命令提示
       // MakeComandInfo();
        if( GetComand()==false) continue; //获取用户输入信 
        
    
      HandComand();  //分析命令
      //vardebug(); 
      
      if(CheckBiuldComand()) continue; //判断是否为内建命令
      run(); //执行命令 
    }
      return 0;
}

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

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

相关文章

C# 屏幕录制工具

屏幕录制工具 开发语音&#xff1a;C# vb.net 下载地址&#xff1a;https://download.csdn.net/download/polloo2012/89879996 功能&#xff1a;屏幕录制&#xff0c;声卡采集&#xff0c;麦克风采集。 屏幕录制&#xff1a;录制屏幕所有操作&#xff0c;并转换视频格式&…

电脑无线网wifi和有线网同时使用(内网+外网同时使用)

一、要求 我这里以无线网wifi为外网&#xff0c;有线网卡为内网为例&#xff1a; 一、基本信息 无线wifi&#xff08;外网&#xff09;&#xff1a;ip是192.168.179.235&#xff0c;网关是192.168.179.95有线网&#xff08;内网&#xff09;&#xff1a;ip是192.168.10.25&…

《鸟哥的Linux私房菜基础篇》---1 Linux的介绍与如何开启Linux之路

目录 一、Linux的简单介绍 1、Linux的简介 2、Linux的起源与发展 3、主要特点 4、应用场景 二、开启Linux之路 1、学习Linux的相关知识 2、正规表示法、管线命令、数据流重导向 前言 整体大纲预览 一、Linux的简单介绍 1、Linux的简介 &#xff08;1&#xff09;Linu…

【Trulens框架】用TruLens 自动化 RAG 应用项目评估测试

前言&#xff1a; 什么是Trulens TruLens是面向神经网络应用的质量评估工具&#xff0c;它可以帮助你使用反馈函数来客观地评估你的基于LLM&#xff08;语言模型&#xff09;的应用的质量和效果。反馈函数可以帮助你以编程的方式评估输入、输出和中间结果的质量&#xff0c;从而…

K8S---01初识Kubernetes

一.简介 摘取官网: 概述 | KubernetesKubernetes 是一个可移植、可扩展的开源平台&#xff0c;用于管理容器化的工作负载和服务&#xff0c;方便进行声明式配置和自动化。Kubernetes 拥有一个庞大且快速增长的生态系统&#xff0c;其服务、支持和工具的使用范围广泛。https://k…

【C++堆(优先队列)】1882. 使用服务器处理任务|1979

本文涉及知识点 C堆(优先队列) LeetCode1882. 使用服务器处理任务 给你两个 下标从 0 开始 的整数数组 servers 和 tasks &#xff0c;长度分别为 n​​​​​​ 和 m​​​​​​ 。servers[i] 是第 i​​​​​​​​​​ 台服务器的 权重 &#xff0c;而 tasks[j] 是处理…

【寻找one piece的算法之路】前缀和(一)

&#x1f490;个人主页&#xff1a;初晴~ &#x1f4da;相关专栏&#xff1a;寻找one piece的刷题之路 什么是前缀和&#xff1f; 主要是通过预先计算数组或矩阵的前缀和&#xff0c;来快速查询子数组或子矩阵的和。这种算法可以用空间换时间&#xff0c;提高查询效率。 概念…

FileOutputStream类

1.操作本地文件的字节输出流&#xff0c;可以把程序中的数据写到本地文件中。 2.书写步骤&#xff1a; 3.实例代码 结果&#xff1a;可以看到my io下面已经生成了一个a.txt文件。 4.注意细节 &#xff08;1&#xff09;参数是字符串表示的路径或者是File对象 &#xff08;2&…

怎么把音频的速度调慢?6个方法调节音频速度

怎么把音频的速度调慢&#xff1f;调慢音频速度不仅可以帮助我们更好地捕捉细节&#xff0c;还能让我们在分析和学习时更加从容。这对于音乐爱好者来说&#xff0c;尤其有助于理解复杂的旋律和和声&#xff0c;使学习过程变得更加高效。而在语言学习中&#xff0c;放慢语速则能…

Spring Cloud 3.x 集成eureka快速入门Demo

1.什么是eureka&#xff1f; Eureka 由 Netflix 开发&#xff0c;是一种基于REST&#xff08;Representational State Transfer&#xff09;的服务&#xff0c;用于定位服务&#xff08;服务注册与发现&#xff09;&#xff0c;以实现中间层服务的负载均衡和故障转移&#xff…

基于webrtc实现音视频通信

与传统通信方式不同&#xff0c;p2p通信的实现过程不依赖于中间服务器的信息收发&#xff0c;直接通过信令等完成通信过程的建立&#xff1b; 通过websocket实现信令服务器的建立&#xff0c;而通过信令来确定通信双方&#xff1b; webrtc通过 sdp协议来完善通信双方间协议的…

React01 开发环境搭建

React 开发环境搭建 一、创建 React 项目二、项目精简 一、创建 React 项目 执行下述命令创建 react 项目 blu-react-basis npx create-react-app blu-react-basis项目目录结构如下&#xff1a; 执行下述命令启动项目 npm run start启动效果如下&#xff1a; 二、项目精简 …

Java Agent 技术解析

什么是Java Agent Java Agent是在 JDK1.5 引入的一种可以动态修改 Java 字节码的技术。Java 类编译之后形成字节码被 JVM 执行&#xff0c;在 JVM 在执行这些字节码之前获取这些字节码信息&#xff0c;并且通过字节码转换器对这些字节码进行修改&#xff0c;来完成一些额外的功…

维生素对于生活的重要性

在探索健康奥秘的旅途中&#xff0c;维生素作为人体不可或缺的微量营养素&#xff0c;扮演着至关重要的角色。它们虽不直接提供能量&#xff0c;却是酶促反应、细胞代谢、免疫功能乃至心理健康的基石。今天&#xff0c;让我们一同深入探讨人体所需补充的维生素&#xff0c;这些…

Keepalived高可用和Haproxy负载均衡

一、概念 简介 keepalived是集群管理中保证集群高可用的一个服务软件&#xff0c;用来防止单点故障。 工作原理 keepalived是以VRRP协议为实现基础的&#xff0c;N台路由器组成一个路由器组。master上有一个对外提供服务的vip&#xff0c;master会向backup进行发送组播&…

4.stable-diffusion-webui1.10.0--图像修复(adetailer)插件

ADetailer是Stable Diffusion WebUI的一个插件&#xff0c;它通过深度学习模型智能检测图像中的人脸、手部及身体等关键部位&#xff0c;并自动进行重绘修复&#xff0c;使得生成的图像更加自然、符合预期。 ADetailer插件主要应用于图像的细节增强、降噪和修复&#xff0c;特…

Git-bug001 VScode中git clone的地址首次push报错push.default is unset

问题现象&#xff1a; 解释&#xff1a;Git 提醒用户 push.default 配置未设置&#xff0c;且其隐式值已在最新版本的 Git 中更改 解决-输入&#xff1a;git config --global push.default simple 然后重新push就可以了 然后继续报问题&#xff1a;点击OK即可 解释&#xff1…

计算机网络(十一) —— 数据链路层

目录 一&#xff0c;关于数据链路层 二&#xff0c;以太网协议 2.1 局域网 2.2 Mac地址 2.3 Mac帧报头 2.4 MTU 三&#xff0c;ARP协议 3.1 ARP是什么 3.2 ARP原理 3.3 ARP报头 3.4 模拟ARP过程 3.5 ARP周边问题 四&#xff0c;NAT技术 4.1 NAT技术背景 4.2 NAT转…

Windows11安装CUDA、cuDNN、PyTorch详解

目录 CUDA查看 CUDA下载 CUDA安装 cuDNN安装 PyTorch安装 复现环境&#xff1a; 系统版本CUDA12.3cuDNN9.5.0Python3.9PyTorch2.3.1Windows11 CUDA查看 首先我们需要看一下操作系统是否支持GPU。打开任务管理器&#xff0c;点击性能&#xff0c;如图&#xff1a; 这表明作…

RabbitMQ 入门(二)入门案例

一、RabbitMQ的基本结构、角色和消息模型 MQ的基本结构&#xff1a; RabbitMQ中的一些角色&#xff1a; - publisher&#xff1a;生产者 - consumer&#xff1a;消费者 - exchange个&#xff1a;交换机&#xff0c;负责消息路由 - queue&#xff1a;队列&#xff0c;存储消息…