输入包含单行多命令,命令之间使用管道符('|')连接,可以使用输入输出重定向功能,
输入的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
#include
#include
#include
#include
#include
#include
#include
#include
#include
char buf[150]; // save the input command
char command[20][30]; //save the commands that is splited
int commandNum = 0; // save the numbers of command
char inputFilename[30]; //save the input file name if it exists
bool isInputExist = 0; //save the state of existence of input file
char outputFilename[30]; //save the output file name if it exists
bool isOutputExist = 0; //save the state of existence of output file
char *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,2
char *str = buf;
char ch;
int flag = 0;
while(ch=*str++)
{
if(ch == '|') //start to save another command
{
state = 0; //command state
i++;
j=0;
continue;
}
else if(ch == '<') //start to save the input file name
{
state = 1; //input file name state
isInputExist = 1;
continue;
}
else if(ch == '>')
{
state = 2; //output file name state
isOutputExist = 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 commands
DealCommandStr(); //deal the input string
char * 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