Linux下 Mini-shell的实现(C/C++)
来源:互联网 发布:在联通云数据工作好吗 编辑:程序博客网 时间:2024/06/13 22:25
问题描述:
使用C语言在Linux下实现一个mini-shell,该shell从是stdin里面读取命令,然后执行该命令。
输入:
输入包含单行多命令,命令之间使用管道符('|')连接,可以使用输入输出重定向功能,
输入的BNF规范 :
line ::= command ("|" command)* [redirection] redirection ::= [input_redirection] [output_redirection] | [output_redirection] [input_redirection] input_redirecton ::= "<" filename output_redirecton ::= ">" filename command ::= file_name argument*
输出:
程序本身不输出任何东西,它的exit code就是输入一行命令中最后一个子命令的exit code
源码:
//Written by Openking 2014-11-15/*Usage: inputs a line of commands connected by '|'For example: ls -l | less > test.txt*/#include <stdio.h>#include <stdlib.h>#include <ctype.h>#include <string.h>#include <unistd.h>#include <fcntl.h>#include <sys/types.h>#include <sys/wait.h>#include <dirent.h>#include <stdbool.h>char buf[150]; // save the input commandchar command[20][30]; //save the commands that is splitedint commandNum = 0; // save the numbers of commandchar inputFilename[30]; //save the input file name if it existsbool isInputExist = 0; //save the state of existence of input filechar outputFilename[30]; //save the output file name if it existsbool isOutputExist = 0; //save the state of existence of output filechar *arg[20];char * trim(char * src){int i = 0;char *begin = src;while(src[i] != '\0'){ if(src[i] != ' ') { break; } else { begin++; } i++;}for(i = strlen(src)-1; i >= 0; i--){ if(src[i] != ' ') { break; } else { src[i] = '\0'; }}return begin;}int DealCommandStr() //analysis the command{int i=0,j=0;int p=0,q=0;int state = 0; //state = 0,1,2char *str = buf;char ch;int flag = 0;while(ch=*str++){if(ch == '|') //start to save another command{state = 0; //command statei++;j=0;continue;}else if(ch == '<') //start to save the input file name{state = 1; //input file name stateisInputExist = 1;continue;}else if(ch == '>'){state = 2; //output file name stateisOutputExist = 1;continue;}else{if(state == 0) //command state{command[i][j++] = ch;}else if(state == 1) //input file name state{inputFilename[p++] = ch;}else //output file name state{outputFilename[q++] = ch;}}commandNum = i; //get the number of commands}//for(i = 0;i <= commandNum; i++)//{//puts(command[i]);//}}int main(){int i=0,j=0;gets(buf); //get commandsDealCommandStr(); //deal the input stringchar * str_temp;char * readStr;char * writeStr;pid_t pid[30];int pipefd1[2] = {-1,-1};int pipefd2[2] = {-1,-1};int fdr,fdw;int ii=0; /* fork count child process */if(commandNum == 0){ //pid_t fork(void); pid[0] = fork();if(pid[0] == 0){if(isInputExist) { fdr = open(trim(inputFilename),O_RDONLY); dup2(fdr, STDIN_FILENO); } if(isOutputExist) { fdw = open(trim(outputFilename),O_WRONLY|O_CREAT|O_TRUNC,0600); dup2(fdw, STDOUT_FILENO); } /* child process */ //int execvp(const char *file, char *const argv[]); //PureCommandStr(command[0]); int iii=0; char *buffer = trim(command[0]); //puts(buffer); while((arg[iii++] = strsep(&buffer," "))!= NULL); //setbuf(stdout, NULL);//char *a = "ls";//char *b[]={"ls","-a"};//execvp(b[0],b);//printf("%s %s\n",arg,argv2); execvp(arg[0], arg); exit(0); } } else {//printf("command num %d\n",commandNum); for(i = 0; i <= commandNum+1; i++) { //printf("i num: %d\n",i); /* init pipe file descriptor */ pipe(pipefd1); /* fork child i */ pid[i] = fork(); //printf("pid num: %d\n",pid[i]); if(pid[i] == 0) { /* child i */ //int dup2(int oldfd, int newfd); if(i == 0) { /* the first child */ close(pipefd1[0]); if(isInputExist) { fdr = open(trim(inputFilename),O_RDONLY); dup2(fdr, STDIN_FILENO); } dup2(pipefd1[1], STDOUT_FILENO); close(pipefd1[1]); } else if(i == commandNum) { /* the last child */ dup2(pipefd2[0], STDIN_FILENO); close(pipefd2[1]); /* close prev process end of write */ close(pipefd2[0]); /* close curr process end of read */ if(isOutputExist) { fdw = open(trim(outputFilename),O_WRONLY|O_CREAT|O_TRUNC,0600); dup2(fdw, STDOUT_FILENO); } } else { dup2(pipefd1[1], STDOUT_FILENO); close(pipefd1[0]); close(pipefd1[1]); dup2(pipefd2[0], STDIN_FILENO); close(pipefd2[0]); close(pipefd2[1]); } //int execvp(const char *file, char *const argv[]); //PureCommandStr(command[i]);//char *argv2 = command[i];int iii=0; char *buffer = trim(command[i]); //puts(buffer); while((arg[iii++] = strsep(&buffer," "))!= NULL);//printf("%s %s\n",arg,argv2);execvp(arg[0], arg);//printf("i num: %d\n",i); } if(i!=0) { close(pipefd2[0]); close(pipefd2[1]); } pipefd2[0]=pipefd1[0]; pipefd2[1]=pipefd1[1];}} for(i = 0; i <=commandNum; i++) { //pid_t waitpid(pid_t pid, int *status, int options); waitpid(pid[i], NULL, 0); }}
测试:我们使用命令:
ls -l | less > test.txt
total 32-rw------- 1 openking openking 33 1月 18 13:22 1.txt-rw-rw-r-- 1 openking openking 8294 11月 21 16:42 shell.cc-rwxrwxr-x 1 openking openking 13471 1月 18 13:21 shell.o-rw------- 1 openking openking 0 1月 18 13:24 test.txt
0 0
- Linux下 Mini-shell的实现(C/C++)
- Linux下C语言实现简单Shell
- C-mini 程序设计语言的设计与实现
- Linux C下的shell命令调用
- Linux Shell命令的C语言实现
- 用c实现的简单linux shell
- Linux C实现简单的shell
- 利用linux下的c语言编程来简单的实现一个shell功能实现!
- c 实现的shell
- linux环境下使用c语言实现shell(一)
- linux c实现简单shell
- Linux下C语言引用shell脚本的简单例子
- linux下模拟shell的C程序--操作系统作业
- linux下C和shell调用的popen函数
- linux下C和shell调用的popen函数
- linux下C和shell调用的popen函数
- linux下C和shell调用的popen函数
- mini webserver on linux with c
- Linux 磁盘划分
- Eclipse中Java应用程序调试常用断点介绍
- 数据结构Java实现——③串--->串的模式匹配:Brute-Force算法和 KMP算法
- c内存操作函数
- 12.1 生成序列
- Linux下 Mini-shell的实现(C/C++)
- Managed Metadata Service Application(一)创建Managed Metadata Service Application
- zinnia下user各自的category
- BJFU-ACM-1009 抽奖
- Java – Convert String To Enum Object
- poj3107--Godfather(树形DP练习3)
- 【C语言】01-类型总结
- WV.10-动态链表-搜索某值存在个数
- 机器学习基础(三)Logistic回归模型