简单模拟实现shell(Linux)

news2024/11/18 11:44:16

目录​​​​​​​

前言

展示效果

实现代码 


前言

该代码模拟了shell的实现,也就是解析类似于“ls -a -l"的命令,当我们启动我们自己写的shell的可执行程序时,我们输入"ls"的命令,也可以展示出在shell中输入"ls"时同样的效果,一下为展示效果

展示效果

当我们在系统的shell下输入"ls"时,会显示 

以下代码是我自主模拟实现shell的程序执行"ls"命令时的情况  

是不是很类似呢,感兴趣的同学可以看看以下代码,自己也模仿模仿哦ε=ε=ε=(~ ̄▽ ̄)~ 

实现代码 

#include <stdio.h>
#include <string.h>
#include <unistd.h>//sleep函数

//wait函数头文件
#include <sys/types.h>
#include <sys/wait.h>

//exit的函数
#include <stdlib.h>

#define NUM 2024
#define SIZE 100
#define SEP " "
//注意是"",而不是''.因为strtok的参数是char*类型

int main()
{
  //0.shell或者软件,只要启动了,使用者不去终止,就始终不能停止,因此要一个死循环
  while (1)
  {
    //1.打印类似于shell命令行前的 [xkjtx@locathost shell@] 的信息
    printf("[xkjtx@locatehost myshell]# ");//不要换行,否则就不像shell了,用fflush去刷新缓冲区,避免没有'\n'而导致的不输出"[xkjtx@locatehost myshell]# "的问题(我在《制作进度条》的那篇博客讲过)
    fflush(stdout);

    //2.获取命令行
    char cmd_line[NUM];//可以定义为全局变量,注意每次使用前memset(cmd_line, '\0', sizeof cmd_line);
    if (fgets(cmd_line, SIZE, stdin) == NULL)//推荐使用fgets,建立对标准输入输出流概念,方便以后学习基础IO
    {
      continue;//读取失败,重新读取
    }

    cmd_line[strlen(cmd_line) - 1] = '\0';

    //char* fgets(char* str, int size, FILE* stream);//如果输入成功,则返回str的起始地址,否则为NULL
    //3.拆分命令行
    char* g_argv[NUM];
    g_argv[0] = strtok(cmd_line, SEP);//第一次调用第一个参数传参目标字符串,后面都传NULL
    int index = 1;


    //使得ls命令时带上颜色
    if (strcmp(g_argv[0], "ls") == 0)
    {
      g_argv[index++] = "--color=auto";
    }
   
    //使得ll命令也可以执行
    if (strcmp(g_argv[0], "ll") == 0)
    {
      g_argv[0] = "ls";
      g_argv[index++] = "-l";
      g_argv[index++] = "--color=auto";
    }
    
    while(g_argv[index++] = strtok(NULL, SEP));

    // printf("index = %d\n", index);


  //  //检测分割是否正确
  // for (index = 0; g_argv[index]; index++)//C99标准不支持在for循环内定义int
  //   printf("g_argv[%d] = %s\n", index, g_argv[index]);
  
    //4.TODO
    //内置命令的处理(要父进程去执行的命令,如cd命令)
    //目前写法发现:cd ~, cd -, rm等命令做不了
    


    //错误写法
    // if (g_argv[0] == "cd")
    if (strcmp(g_argv[0], "cd") == 0)
    {
      if (g_argv[1] != NULL)//路径合法
      {
        chdir(g_argv[1]);
        continue;//不去创建子进程
      }
    }



    //5.创建子进程//好处:不会影响父进程//shell本来就是媒婆招实习生,让实习生干活,不影响媒婆
    pid_t id = fork();
   

    int status = 0;

    if (id == 0)//child
    {
      execvp(g_argv[0], g_argv);//选这个函数的原因:(1)v:用的是数组,恰好有数组  (2)每个都要绝对路径,这是没有必要的,因此可以使用带p的函数
      exit(1);//进行到这里,一定是函数调用失败
    }

    //这里一定是父进程
    //father
    //获取子进程信息
    pid_t ret = waitpid(-1, &status, 0);
    /*
       #include <sys/types.h>
       #include <sys/wait.h>

       pid_t wait(int *status);

       pid_t waitpid(pid_t pid, int *status, int options);

     */
    if (ret > 0) //等待子进程成功
    {
      printf("exit code = %d\n", WEXITSTATUS(status));//打印子进程退出码
    }
  }
  return 0;
}

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

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

相关文章

广告联盟收款的解决方案

目前国内的affiliate&#xff0c;收海外联盟款就六种主要的解决方案(使用何种方式收款&#xff0c;不是我们决定的&#xff0c;是你操作的联盟决定的&#xff0c;你要根据联盟的要求提供相应的收款方式) 1 直接注册国外当地的银行账户 比如我收美国的广告联盟佣金用的是我美国银…

【设计模式】JAVA Design Patterns——Dependency Injection(依赖注入模式)

&#x1f50d;目的 依赖注入是一种软件设计模式&#xff0c;其中一个或多个依赖项&#xff08;或服务&#xff09;被注入或通过引用传递到一个依赖对象&#xff08;或客户端&#xff09;中&#xff0c;并成为客户端状态的一部分。该模式将客户的依赖关系的创建与其自身的行为分…

Java集合—TreeSet和TreeMap

一、TreeSet 1.当使用无参构造器&#xff0c;创建TreeSet时&#xff0c;仍然是无序的。 2.若希望添加的元素有序&#xff0c;需要使用TreeSet提供的构造器,传入一个比较器。 该比较器是一个接口&#xff0c;里面有一个方法叫compare()&#xff0c;传入一个实现该接口的类(匿名内…

使用PyAutoGUI识别PNG图像并自动点击按钮

在自动化测试、任务批处理等场景中,我们常常需要控制GUI程序的鼠标键盘操作。PyAutoGUI就是一个非常方便的Python模块,可以帮助我们实现这些操作。今天我们就来看看如何使用PyAutoGUI识别屏幕上的PNG图像,并自动点击图像所在位置。 C:\pythoncode\new\autoguirecongnizepng.py …

树--搜索二叉树

现有一棵结点数目为n的二叉树&#xff0c;采用二叉链表的形式存储。对于每个结点均有指向左右孩子的两个指针域&#xff0c;而结点为n的二叉树一共有n-1条有效分支路径。那么&#xff0c;则二叉链表中存在2n-(n-1)n1个空指针域。那么&#xff0c;这些空指针造成了空间浪费。 例…

Redis 中 Set 数据结构详解

用法 Redis 中的 Set 是一个无序&#xff0c;不重复集合&#xff08;里面的元素为字符串&#xff09;&#xff0c;支持常用的集合操作。 常见命令 1. 增 添加一个或多个元素到 set 中 SADD key member [ member ... ] 返回值&#xff1a; 添加成功的元素个数 将一个元素移到…

react跨组件通信Context

案例&#xff1a;现在有个父-子-孙组件 需要进行组件通信 import { useState } from "react"; // 创建上下文 const CountContext React.createContext();//子组件 const SonComponent (props) > {return (<div><h2>子组件</h2><Grandson…

spdlog 使用

spdlog 是一个日志库&#xff0c;直接引用头文件即可使用&#xff0c;速度快&#xff0c;异步打印日志。 对应的git地址 spdloggit地址 对应的目录 把上面划线的文件夹引入到自己的工程中&#xff0c;即可使用spdlog 下面是使用例子 inline static void create_logging(const…

LeetCode hot100-57-G

17. 电话号码的字母组合 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。不会&#xff0c;放IDEA里执行了一下大概理解了流程 …

Django序列化器中validate没起作用?validate的触发时机

今天上班的时候分配了一个任务&#xff0c;是修复前端的一个提示优化&#xff0c;如下图所示&#xff1a; 按照以往的经验我以为可以直接在validate上进行校验&#xff0c;如何抛出一个异常即可 &#xff0c;例如&#xff1a; class CcmSerializer(serializers.ModelSerialize…

划重点来了,计算机组成原理之计算机存储介绍与汉明码纠错

存储器 1. 分类 &#xff08;1&#xff09;按存储介质分类&#xff1a; 存储介质是能寄存”0“或"1"两种代码的物质或元器件。 包括半导体器件&#xff0c;磁性材料&#xff0c;光盘等。 半导体存储器&#xff1a;半导体器件组成的存储器。断电后数据会丢失&…

关于Word目录的更新

左侧标题顺序如有调整&#xff0c;自动目录并不会同步更新&#xff0c;每次都要记得在正文目录左上角点击更新目录

【Linux终端探险】:从入门到熟练,玩转基础命令的秘密(一)

文章目录 &#x1f680;Linux基础命令⭐1. 查看目录命令&#x1f4a5;2. 切换目录&#x1f44a;3. 创建目录❤️4. 删除目录/文件&#x1f6b2;5. 修改目录/文件&#x1f308;6. 拷贝目录/文件 &#x1f680;Linux基础命令 ⭐1. 查看目录命令 在Linux中&#xff0c;查看目录的…

【Paddle】Inplace相关问题:反向传播、影响内存使用和性能

【Paddle】Inplace相关问题&#xff1a;反向传播、影响内存使用和性能 写在最前面inplace 的好处有哪些&#xff1f;能降低计算复杂度吗在反向传播时&#xff0c;Inplace为什么会阻碍呢&#xff1f;“计算图的完整性受损”表达有误原地操作 sin_()为什么原地操作会阻碍反向传播…

【AIGC】GPT-4o技术分析-浅谈

GPT-4o&#xff1a;人工智能技术的全新里程碑 一、引言二、GPT系列版本间的对比分析三、GPT-4o的技术能力分析多模态处理能力速度与性能优化情感理解与表达能力 四、个人整体感受五、结语 一、引言 在人工智能技术的浪潮中&#xff0c;OpenAI再次以其卓越的创新能力引领潮流。近…

Java基础:面向对象(二)

Java基础&#xff1a;面向对象&#xff08;二&#xff09; 文章目录 Java基础&#xff1a;面向对象&#xff08;二&#xff09;1. 面向对象编程思想2. 类与对象2.1 类2.1.1 类的定义2.1.2 成员变量2.1.3 局部变量 2.2 对象2.2.1 对象的定义2.2.2 对象的使用2.2.3 对象创建的原理…

灯下黑”挖出国内知名安全平台某BUF的CSRF漏洞

漏洞复现&#xff1a; 漏洞点在删除文章的地方&#xff0c;首先为了测试先发布一篇文章 发布之后我们可以查看文章&#xff0c;注意url中的一串数字&#xff0c;就是这篇文章的id&#xff0c;如下如&#xff1a; 这里的文章id是“271825”&#xff0c;首先抓一下删除文章的数据…

装机数台,依旧还会心念i5-12600KF的性能和性价比优势:

近几个月的时间中&#xff0c; 装机差不多4台电脑&#xff0c;由于工作需要&#xff0c;计划年中再增添一台。 目前市场上英特尔CPU促销非常火爆&#xff0c;第12代、第13代以及第14代的产品在年中有适当的优惠。 年中也是装机的旺季&#xff0c;各种相关配件也相对便宜一些。…

新版IDEA没有办法选择Java8版本解决方法

2023年11月27日后&#xff0c;spring.io 默认不再支持创建jdk1.8的项目 解决方法就是把 Spring的Server URL 改为阿里的。 阿里的Server URL https://start.aliyun.com/ 默认的Server URL https://start.spring.io 阿里的Server URL https://start.aliyun.com/

如何使用宝塔面板搭建Tipask问答社区网站并发布公网远程访问

文章目录 前言1.Tipask网站搭建1.1 Tipask网站下载和安装1.2 Tipask网页测试1.3 cpolar的安装和注册 2. 本地网页发布2.1 Cpolar临时数据隧道2.2 Cpolar稳定隧道&#xff08;云端设置&#xff09;2.3 Cpolar稳定隧道&#xff08;本地设置&#xff09; 3. 公网访问测试4.结语 前…