mybash---打造自己的命令解释器

news2024/11/24 3:47:27

目前我们Linux的系统默认的命令解释器是bash;
命令解释器(也称为命令行解释器或shell)是计算机操作系统中的一个重要组件,它负责接收用户输入的命令,并解释和执行这些命令。其实命令解释器就是解析命令,执行命令,输出反馈;

1.命令的分类

内置命令和普通命令
1.内置命令:cd exit 2普通命令:ls pwd cp ps   等等
如果是普通命令,那么使用which是可以找到的,比如which ps;which ls;which pwd;which cp;
也就是普通命令是一个可执行程序.
但是我们找cd和exit是找不到的;  因为内置命令cd,exit等它是在bash本身实现的; 而bash也是一个可执行程序,比如:which bash;
简单来讲,就是普通命令是通过fork+exec实现的;而内置命令是bash自身通过调用相应的接口实现的;

2.项目框架

企业微信截图_16537102881089.png


3.strtok的介绍

字符串分割函数

image-20230928220131547.png

注意:

strtok线程不安全,原因就是函数实现使用了一个static的变量(指针记录下次分割的地址,再次调用要沿用上次的,所以需要静态变量).
在多线程中,如果两个线程都使用了strtok的话,这个变量的值就会被另一个线程不定期的进行修改.

4.mybash.c

#include<assert.h>
#include<wait.h>
#include<sys/types.h>
#include<pwd.h>
#include<sys/utsname.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#define ARG_MAX 10
#define CHAR_MAX 128
char* get_cmd(char* buff,char* myargv[])
{
    if(buff==NULL||myargv==NULL)
    {
        perror("buff为NULL或myargv为NULL\n");
        return NULL;
    }
    char* s=strtok(buff," ");
    int i=0;
    while(s!=NULL)
    {
        myargv[i++]=s;
        s=strtok(NULL," ");
    }
    return myargv[0];
}
char* getpath()
{
    char buf[CHAR_MAX];//当前的绝对路径
    getcwd(buf,CHAR_MAX);

    char* stdpath=(char*)malloc(CHAR_MAX);//用户家目录
    uid_t uid=getuid();
    struct passwd* pw;
    pw=getpwuid(uid);
    strcpy(stdpath,pw->pw_dir);

    int i=0;
    char* path=(char*)malloc(CHAR_MAX);
    while(stdpath[i]!='\0')
    {
        if(buf[i]!=stdpath[i])
        {
            strcpy(path,buf);
            break;
        }
        i++;
    }
    if(stdpath[i]=='\0')
    {
        strcpy(path,"~");
        if(strchr(strstr(buf,getlogin()),'/')!=NULL)
        {
            strcat(path,strchr(strstr(buf,getlogin()),'/'));
        }
    }
    return path;
}
int main(int argc,char* argv[])
{
    char* myenvp[]={"/home/stu/bash/mybin"};
    //获取主机名
    struct utsname uts;
    uname(&uts);
    /*char* hostname[128]={0};
     * if(gethostname(hostname,128)==-1)
     * {
     *      printf("mybash1.0>>>  ");
     *      fflush(stdout);
     * }
    */
    //获取用户id
    uid_t uid=getuid();
    char user='$';
    if(uid==0)
    {
        user='#';
    }
    while(1)
    {
        printf("\033[1;35m%s@%s\033[0m:\033[1;34m%s\033[0m%c ",getlogin(),uts.nodename/*hostname*/,getpath(),user);//命令提示符
        fflush(stdout);//刷新缓冲区
        char buff[CHAR_MAX];
        fgets(buff,CHAR_MAX,stdin);//从键盘获取命令
        buff[strlen(buff)-1]='\0';
        //解析命令
        char* myargv[ARG_MAX]={0};
        char* cmd=get_cmd(buff,myargv);//命令
    
        //如果是内置命令
        if(cmd==NULL)
        {
            continue;
        }
        else if(strcmp(cmd,"cd")==0)
        {
            if(myargv[1]!=NULL)
            {
                if(chdir(myargv[1])==-1)
                {
                    perror("path error\n");
                }
            }
            else
            {
                char path[128]="/home/";
                strcat(path,getlogin());
                chdir(path);
            }      
        }
        else if(strcmp(cmd,"exit")==0)
        {
            break;
        }
        //如果是普通命令
        else
        {
            pid_t pid=fork();
            assert(pid!=-1);
            if(pid==0)
            {
                char pathname[CHAR_MAX]={0};
                strcat(strcpy(pathname,"/home/stu/bash/mybin/"),cmd);
                execv(pathname,myargv);
                perror("execve error!\n");
                exit(0);
            }
            else
            {
                wait(NULL);
            }
        }
    }
    exit(0);
}

5.拓展

上面的代码我们实现了通过fork+exec的模式,子进程调用了系统的对应命令的可执行文件,并没有完全自己实现命令,而要实现这个功能呢,就需要你将每一个命令都实现出来,这是一个硕大的工程,但也不要灰心,我们可以实现先一些简单的命令练练手,也算是自己实现过了。

这里给大家放一个ls命令的实现

#include <stdio.h>
    struct dirent *s=NULL;
    while((s=readdir(pdir))!=NULL)
    {   
        if(strncmp(s->d_name,".",1)==0)
        {
            continue;
        }
        //printf("%s   ",s->d_name);
        struct stat filestat;
        stat(s->d_name,&filestat);
        if(S_ISDIR(filestat.st_mode))
        {
            printf("\033[1;34m%s\033[0m  ",s->d_name);
        }
        else
        {
            if(filestat.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))
            {
                printf("\033[1;32m%s\033[0m  ",s->d_name);
            }
            else
            {
                printf("%s  ",s->d_name);
            }
        }
    }   
    printf("\n");

    closedir(pdir);
    exit(0);
}

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

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

相关文章

【c 语言】声明了一个指针,会给指针分配内存吗?

&#x1f388;个人主页&#xff1a;豌豆射手^ &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;C语言 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进步&…

电商API数据采集接口|跨境卖家在追求精细化运营过程中商品选品以及上架物流几方面应用

跨境电商行业与IT行业资深从业者&#xff0c;知名跨境电商人工智能软件创始人。擅长用RPA机器人技术、aPaaS业务应用平台以及AI人工智能技术为跨境卖家提供新的运营模式和思路&#xff0c;用技术的手段来解决跨境行业的痛点问题。 现在跨境卖家都在追求精细化运营&#xff0c;在…

【Git】Git的安装与常用命令

Git的安装与常用命令 一、Git的安装 &#xff08;一&#xff09;下载 官网下载&#xff1a;https://git-scm.com/downloads 镜像网站&#xff1a;https://registry.npmmirror.com/binary.html?pathgit-for-windows/ &#xff08;二&#xff09;安装 双击安装&#xff0c…

06-vscode+espidf开发调试方法(内置JTAG调试)

使用VS Code和ESP-IDF进行ESP32开发和调试 在我们搭建 IDF 框架后&#xff0c;OpenOCD 已经自动下载好了&#xff0c; 我们通过 JTAG 接口连接使用 OpenOCD 进行调试。而ESP32芯片中内置 了JTAG 电路&#xff0c;无需额外芯片即可调试&#xff0c;更加方便&#xff0c;所以这里…

开源相机管理库Aravis例程学习(三)——注册回调multiple-acquisition-callback

开源相机管理库Aravis例程学习&#xff08;三&#xff09;——回调multiple-acquisition-callback 简介例程代码arv_camera_create_streamArvStreamCallbackTypeArvStreamCallback 简介 本文针对官方例程中的&#xff1a;02-multiple-acquisition-callback做简单的讲解。 ara…

ppt里的音乐哪里来的?

心血来潮&#xff0c;想照着大神的模板套一个类似于快闪的ppt。 ppt里是有一段音乐的&#xff0c;那段音乐就是从幻灯片第二页开始响起的。 但是我就找不到音乐在哪。 甚至我把ppt里的所有素材都删除了&#xff0c;再看动画窗格&#xff0c;仍然是空无一物&#xff0c;显然&…

PyCharm 2024.1 发布:全面升级,助力高效编程!

PyCharm 2024.1 发布&#xff1a;全面升级&#xff0c;助力高效编程&#xff01; 文章目录 PyCharm 2024.1 发布&#xff1a;全面升级&#xff0c;助力高效编程&#xff01;摘要引言 Hugging Face&#xff1a;模型和数据集的快速文档预览针对 JavaScript 和 TypeScript 的全行代…

基于有序抖动块截断编码的水印嵌入和提取算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 噪声测试 旋转测试 压缩测试 2.算法运行软件版本 matlab2022a 3.部分核心程序 ............................................................…

基于深度学习网络的鞋子种类识别matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 load gnet.mat % 使用训练好的网络对验证数据进行分类预测 [Predicted_Label, Probability] c…

基于Canvas实现的简历编辑器

基于Canvas实现的简历编辑器 大概一个月前&#xff0c;我发现社区老是给我推荐Canvas相关的内容&#xff0c;比如很多 小游戏、流程图编辑器、图片编辑器 等等各种各样的项目&#xff0c;不知道是不是因为我某一天点击了相关内容触发了推荐机制&#xff0c;还是因为现在Canvas…

开源模型应用落地-chatglm3-6b-批量推理-入门篇(四)

一、前言 刚开始接触AI时&#xff0c;您可能会感到困惑&#xff0c;因为面对众多开源模型的选择&#xff0c;不知道应该选择哪个模型&#xff0c;也不知道如何调用最基本的模型。但是不用担心&#xff0c;我将陪伴您一起逐步入门&#xff0c;解决这些问题。 在信息时代&#xf…

python将pdf转为docx

如何使用python实现将pdf文件转为docx文件 1.首先要安装pdf2docx库 pip install pdf2docx2.实现转换 from pdf2docx import Converterdef convert_pdf_to_docx(input_pdf, output_docx):# 创建一个PDF转换器对象pdf_converter Converter(input_pdf)# 将PDF转换为docx文件pdf…

解读MongoDB官方文档获取mongo7.0版本的安装步骤与基本使用

mongo式一款NOSQL数据库&#xff0c;用于存储非结构化数据&#xff0c;mongo是一种用于存储json的数据数据&#xff0c;可以通过mongo提供的命令解析json获取想要的值。 数据模型 了解关系数据库会很熟悉database,table,row,column的概念&#xff0c;分别是数据库&#xff0c…

leetcode代码记录(Z 字形变换

目录 1. 题目&#xff1a;2. 我的代码&#xff1a;小结&#xff1a; 1. 题目&#xff1a; 将一个给定字符串 s 根据给定的行数 numRows &#xff0c;以从上往下、从左到右进行 Z 字形排列。 比如输入字符串为 “PAYPALISHIRING” 行数为 3 时&#xff0c;排列如下&#xff1a;…

开源模型应用落地-chatglm3-6b-gradio-入门篇(七)

一、前言 早前的文章&#xff0c;我们都是通过输入命令的方式来使用Chatglm3-6b模型。现在&#xff0c;我们可以通过使用gradio&#xff0c;通过一个界面与模型进行交互。这样做可以减少重复加载模型和修改代码的麻烦&#xff0c; 让我们更方便地体验模型的效果。 二、术语 2.…

使用 Fetch API 执行 GraphQL 查询和变体

GraphQL 简介 GraphQL 是从远程服务器查询数据的强大工具&#xff0c;也是我构建 API 的首选方式。对一些人来说&#xff0c;学习它可能有一定难度&#xff0c;因为教程通常使用 Apollo 或 Relay 等工具进行编写。 这些工具很不错&#xff0c;但通常更适用于复杂项目。在某些…

Python基于Django的微博热搜、微博舆论可视化系统

博主介绍&#xff1a;✌IT徐师兄、7年大厂程序员经历。全网粉丝15W、csdn博客专家、掘金/华为云//InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3…

【TEE论文】IceClave: A Trusted Execution Environment for In-Storage Computing

摘要 使用现代固态硬盘&#xff08;SSD&#xff09;的存储中计算使开发人员能够将程序从主机转移到SSD上。这被证明是缓解I/O瓶颈的有效方法。为了促进存储中计算&#xff0c;已经提出了许多框架。然而&#xff0c;其中很少有框架将存储中的安全性作为首要任务。具体而言&…

WPS二次开发系列:WPS SDk功能就概览

作者持续关注WPS二次开发专题系列&#xff0c;持续为大家带来更多有价值的WPS开发技术细节&#xff0c;如果能够帮助到您&#xff0c;请帮忙来个一键三连&#xff0c;更多问题请联系我&#xff08;QQ:250325397&#xff09; 作者通过深度测试使用了WPS SDK提供的Demo&#xff0…

比特币突然暴跌

作者&#xff1a;秦晋 周末愉快。 今天给大家分享两则比特币新闻&#xff0c;也是两个数据。一则是因为中东地缘政治升温&#xff0c;传统资本市场的风险情绪蔓延至加密市场&#xff0c;引发加密市场暴跌。比特币跌至66000美元下方。杠杆清算金额高达8.5亿美元。 二则是&#x…