Unknowingly two weeks did not post, because "10,000 U.S. dollar Ford Scholarship Defense", ACM Contest, network paper reading and network work a lot of things to disperse the time, so write a blog post to fill up before a hole.
A blog post about Linux using C to implement a simple shell, when it was just contacted by Linux, was processed:
1) External command
2) Pwd,cd,exit built-in commands
3) input/output redirection
And the code is a step-by-step addition, the code is relatively ugly qaq, so after learning the pipeline, I believe I have to re-write code to achieve.
I changed the code relative to the previous version:
1) for shell instructions using structural storage, easy to cut and execute the pipeline;
2) The use of strtok_r for the instruction is more reasonable cutting;
3) Increased multi-pipe processing;
4) Some simple exception problems are dealt with, including file path problem, blank line problem, instruction error, etc.
/*author:samsons date:2015.4.28 1) for shell instructions using the structure of the storage, easy to cut and execute the pipeline, 2) The use of strtok_r for the instruction is more reasonable cutting; 3) increased multi-pipe processing; 4) Some simple exception problems are dealt with, including file path problem, blank line problem, instruction error and so on. */#include<stdio.h>#include<signal.h>#include<unistd.h>#include<string.h>#include<stdlib.h>#include<fcntl.h>#include<sys/wait.h>#defineMAX 100#defineLEN 100//shell Directive single pipe structure bodystructcmd_list{intargc//number of individual pipe parameters Char*Argv[max];};structCmd_list *cmdv[max];//Shell InstructionsintNum//number of shell pipes//Execute external CommandvoidExecuteChar*argv[]) { interror; Error=EXECVP (argv[0],argv); if(error==-1) printf ("failed!\n"); Exit (1);}//slicing a single pipevoidSplit_cmd (Char*Line ) { structcmd_list * cmd = (structCmd_list *)malloc(sizeof(structcmd_list)); Cmdv[num++] =cmd; CMD->ARGC =0; Char*Save; Char*arg = Strtok_r (line,"\ t", &save);//Splitting spaces while(Arg) {cmd->ARGV[CMD->ARGC] =Arg; Arg= Strtok_r (NULL,"\ t", &save); CMD->argc++; } cmd->ARGV[CMD->ARGC] =NULL;}//cut in charge of the roadvoidSplit_pipe (Char*Line ) { Char*Save; Char* cmd = Strtok_r (line,"|", &save); while(cmd) {split_cmd (cmd); CMD= Strtok_r (NULL,"|", &save); }}//Execute Pipeline CommandvoidDo_pipe (intindex) { if(index = = num-1) Execute (cmdv[index]-argv); intfd[2]; Pipe (FD);//Create pipe, 0 read, 1 write if(fork () = =0) {dup2 (fd[1],1); Close (fd[0]); Close (fd[1]); Execute (Cmdv[index]-argv); } dup2 (fd[0],0); Close (fd[0]); Close (fd[1]); Do_pipe (Index+1);}//executing internal DirectivesintInnerChar*Line ) { Char*save,*Tmp[max]; CharT[len],p[len]; strcpy (T,line); Char*arg = Strtok_r (line,"\ t", &save);//Splitting spaces intI=0; while(ARG) {Tmp[i]=Arg; I++;//Record command Countarg = Strtok_r (NULL,"\ t", &save); } Tmp[i]=NULL; if(strcmp (tmp[0],"Exit")==0)//Exit{exit (0); return 1; } Else if(strcmp (tmp[0],"pwd")==0)//pwd { CharBuf[len]; GETCWD (BUF,sizeof(BUF));//Get current pathprintf"Current dir is:%s\n", BUF); return 1; } Else if(strcmp (tmp[0],"CD")==0)//CD { CharBuf[len]; if(ChDir (tmp[1]) >=0) {getcwd (buf,sizeof(BUF)); printf ("Current dir is:%s\n", BUF); } Else{printf ("Error path!\n"); } return 1; } Else return 0;}//Input REDIRECTvoidCat_in (Char*q) { Chart[ -]; intFD; if(q[0]=='<') {strcpy (t,q+1); FD=open (t,o_rdonly); cmdv[0]->argv[cmdv[0]->argc-1]=null;//The default redirection is the last of the parameterscmdv[0]->argc--; if(fd==-1) {printf ("File Open failed\n"); return; } dup2 (FD,0); Close (FD); }}//Output RedirectionvoidCat_out (Char*q) { Chart[ -]; intFD; if(q[0]=='>') {strcpy (t,q+1); Cmdv[num-1]->argv[cmdv[num-1]->argc-1]=NULL; Cmdv[num-1]->argc--; FD=open (t,o_creat| O_RDWR,0666);//0666 for Permissions if(fd==-1) {printf ("File Open failed\n"); return; } dup2 (FD,1); Close (FD); }}intMain () {intI,pid; CharBuf[len],p[len]; while(1) {fgets (Buf,len,stdin);//read into shell instructions if(buf[0]=='\ n')Continue; Buf[strlen (BUF)-1]=' /'; strcpy (P,BUF); intInner_flag; Inner_flag=inner (BUF);//built-in instruction execution if(inner_flag==0) {PID=fork ();//Create a new process if(pid==0) {split_pipe (p);//Cutting of pipes//The default input and output redirection is the last parameter, the first pipe is entered, the output is the last pipe if(cmdv[0]->argv[cmdv[0]->argc-1]!=NULL) { CharQ[len]; strcpy (q,cmdv[0]->argv[cmdv[0]->argc-1]); Cat_in (q);//Input REDIRECT } if(cmdv[num-1]->argv[cmdv[num-1]->argc-1]!=NULL) { CharQ[len]; strcpy (Q,cmdv[num-1]->argv[cmdv[num-1]->argc-1]); Cat_out (q);//Output Redirection} do_pipe (0);//Execution PipelineExit0); } waitpid (Pid,null,0); } } return 0;}
Linux uses C language to implement a simple shell (2)