实现一个简单shell(支持重定向)
2017-05-10 22:55
886 查看
5.16更新:支持重定向
我们知道对于Linux,shell就是个命令行解释器,当我们输入相关的命令,会去执行相关的操作。
比如当我们输入ls -a -l命令,shell就会打印出当前目录的内容,这是如何实现的?shell自己就是一个进程,当我们输入ls之类的命令,它会通过fork,exec函数去创建一个新的子进程去执行相关操作。因此我们也可以利用这个来实现一个简单的shell。
当然,这个shell足够简单,并不能像Linux内置的shell那么强大支持各种操作,报错,等等。
先来看看实现后的效果图:
红色圈起来的是系统本身的shell,而蓝色则是我自己模拟实现的一个简单shell,可以看到当我输入ls命令,它也完成打印操作,输入./hello也成功执行了hello程序输入hello。当然,类似管道等操作并没有实现,具体可以参考shell去进一步了解。
下面我们来聊聊如何实现简单shell:
首先是提示符,xuyang@host以及当前路径,这个可以调用系统api直接获取打印,这里为了简便,我直接用了printf实现。
解析命令,对于ls -a -l这种命令解析,我们只需要将存入到指针数组中,char* shell _ argv[32],ls存到shell _ argv[0] ,-a存到shell _ argv[1],-l存入到shell _ argv[2] 。。。最后一个设置为NULL
利用exev调用新的程序
代码如下:
效果如下图:
我们知道对于Linux,shell就是个命令行解释器,当我们输入相关的命令,会去执行相关的操作。
比如当我们输入ls -a -l命令,shell就会打印出当前目录的内容,这是如何实现的?shell自己就是一个进程,当我们输入ls之类的命令,它会通过fork,exec函数去创建一个新的子进程去执行相关操作。因此我们也可以利用这个来实现一个简单的shell。
当然,这个shell足够简单,并不能像Linux内置的shell那么强大支持各种操作,报错,等等。
先来看看实现后的效果图:
红色圈起来的是系统本身的shell,而蓝色则是我自己模拟实现的一个简单shell,可以看到当我输入ls命令,它也完成打印操作,输入./hello也成功执行了hello程序输入hello。当然,类似管道等操作并没有实现,具体可以参考shell去进一步了解。
下面我们来聊聊如何实现简单shell:
首先是提示符,xuyang@host以及当前路径,这个可以调用系统api直接获取打印,这里为了简便,我直接用了printf实现。
解析命令,对于ls -a -l这种命令解析,我们只需要将存入到指针数组中,char* shell _ argv[32],ls存到shell _ argv[0] ,-a存到shell _ argv[1],-l存入到shell _ argv[2] 。。。最后一个设置为NULL
利用exev调用新的程序
代码如下:
#include<stdio.h> #include<unistd.h> #include<stdlib.h> #include<sys/types.h> #include<sys/stat.h> #include<sys/wait.h> #include<string.h> #include<ctype.h> #include<fcntl.h> int main() { for (;;) { printf("myshell@host:"); fflush(stdout); //解析输入到shell上的字符串 ls -a -l char buffer[1024]; int read_size = read(1, buffer, sizeof(buffer)); if (read_size > 0) { buffer[read_size - 1] = 0; } char* shell_argv[32] = {NULL}; int shell_index = 0; char* start = buffer; while (*start != '\0') { while (*start != '\0' && isspace(*start)) { *start = '\0'; start++; } shell_argv[shell_index++] = start; while (*start != '\0' && !isspace(*start)) { start++; } } //创建子进程来exec pid_t pid = vfork(); if (pid < 0) { printf("vfork failure\n"); exit(1); } else if (pid == 0) { //考虑重定向 > //在字符串数组中找重定向标志 int i = 0; int flag = 0; for (; shell_argv[i] != NULL; ++i ) { if (strcmp(">", shell_argv[i]) == 0) { flag = 1; break; } } int copyFd; shell_argv[i] = NULL; if (flag) { if (shell_argv[i+1] == NULL) { printf("command error\n"); exit(1); } close(1); int fd = open(shell_argv[i+1], O_WRONLY | O_CREAT, 0777); copyFd = dup2(1, fd); } execvp(shell_argv[0], shell_argv); if (flag) { close(1); dup2(copyFd, 1); } exit(1); } else //father process { int status = 0; int ret = waitpid(pid, &status, 0); if (ret == pid) { if (WIFEXITED(status)) { // printf("exitCode is %d\n", WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { printf("signal is %d\n", WTERMSIG(status)); } } } } return 0; }
效果如下图:
相关文章推荐
- C语言 实现一个简单的Shell (支持管道和"cd")
- 用Qt实现一个简单的shell (Qt5+V8)
- CListCtrlEx:一个支持文件拖放和实时监视的列表控件——用未公开API函数实现Shell实时监视
- Clojure:在REPL上实现一个简单的shell(三)
- 一个简单的wed服务器SHTTPD(4)————SHTTPD支持CGI的实现
- 一个简单地Shell-like 的实现
- Linux.实现一个简单的shell
- CListCtrlEx:一个支持文件拖放和实时监视的列表控件——用未公开API函数实现Shell实时监视
- Clojure:在REPL上实现一个简单的shell(二)
- 自己实现一个简单的支持并发的Web服务器
- 用C语言实现一个简单的Linux壳层(Shell)
- 使用Jquery原理实现一个简单的Ajax的支持JS类
- 【C语言】实现一个简单SHELL应用
- shell实现一个简单进度条
- 一个简单的wifi开关shell脚本实现
- Linux编程实现一个简单的Shell
- 利用线性布局和相对布局实现一个简单的页面并且使应用支持国际化语言
- CListCtrlEx:一个支持文件拖放和实时监视的列表控件——用未公开API函数实现Shell实时监视
- Clojure:在REPL上实现一个简单的shell(一)
- 关于一个简单的shell的实现