前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >简单模拟实现shell(Linux)

简单模拟实现shell(Linux)

作者头像
用户11039529
发布2024-05-30 12:58:29
1440
发布2024-05-30 12:58:29
举报
文章被收录于专栏:算法学习日常

目录​​​​​​​

前言

展示效果

实现代码


前言

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

展示效果

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

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

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

实现代码

代码语言:javascript
复制
#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;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-05-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 展示效果
  • 实现代码
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档