1, first understand the Shell's basic framework
650) this.width=650; "src=" Http://s4.51cto.com/wyfs02/M00/83/46/wKioL1duhrXze92MAAAmKDBM0i0805.png "title=" 2016-06-25 21-26-40 screen. png "alt=" Wkiol1duhrxze92maaamkdbm0i0805.png "/>
As shown
[User name @ Host name current path]$ command
Execute command result
Goal: Complete a simple shell (input command to get execution results)
So the framework is divided into:
1, "Prompt" $ display-----a bunch of function calls can be
2, the execution of the command-----read into the data, to parse, get argv[], the implementation of EXECVP
3. Separate processing for built-in command CD
#include <stdio.h> #include <pwd.h> #include <sys/types.h> #include < unistd.h> #include <string.h> #include <stdlib.h>void prompt () { struct passwd * p1; char username[64]; char hostname[256]; char pathname[1024]; //Get user name p1=getpwuid (getuid ()); //Get path &NBSP;GETCWD (pathname,sizeof (pathname)); //gets the hostname---returns 0 correct if (gethostname (hostname,sizeof ( hostname) ==0) { printf ("[diy %[email protected]%s:%s ]", p1- >pw_name,hostname,pathname); } else { printf ("[DIY %[email protected]:%s ] ", p1->pw_name,pathname); } if (Geteuid () ==0) { printf ("#"); } else { &NBSP;PRINTF ("$"); &NBSP;&NBSP;}} Int main () { while (1) { prompt (); Fflush (stdout); //Get environment Variables char buf[1024]; memset (buf,0,sizeof (BUF)) size_t size=read (0,buf,sizeof (BUF)-1); if (size>0) { buf[size-1]= ' + '; } // printf ("%s\n", buf); char *p=buf; int i=0; char * my_ Argv[64]={0}; my_argv[0]=p; while (*p!=0) { if (*p== ' ') { *p= '; ++p; my_argv[++i]=p; } else { ++p; } } pid_t id=fork (); if (id==0) //sub-process { if (strcmp (my_argv[0], "CD") ==0) { chdir (my_argv[1]); } else { EXECVP (MY_ARGV[0],MY_ARGV); } } else //Parent Process { pid_t ret=waitpid (id,null,0); } } return 0;}
650) this.width=650; "src=" Http://s3.51cto.com/wyfs02/M01/83/47/wKiom1duiU2wxA1cAADByI6Cdq0004.png "title=" 2016-06-25 21-37-58 screen. png "alt=" Wkiom1duiu2wxa1caadbyi6cdq0004.png "/>
So look like everything's hot? Perfect ~ ~ ~
However, there is no way to quit unless you press the CONTROL+Z key to force it out
So, I think the exit can also be achieved
if (id==0) {if (strcmp (my_argv[0], "exit") ==0) {exit (0); } ... } else {pid_t ret=waitpid (id,null,0); if (strcmp (my_argv[0], "exit") ==0) {exit (0); }}} return 0;}
The result is:
650) this.width=650; "src=" Http://s1.51cto.com/wyfs02/M02/83/46/wKioL1duiwLx0ERIAAA7cmQlWiE896.png "title=" 2016-06-25 21-44-56 screen. png "alt=" Wkiol1duiwlx0eriaaa7cmqlwie896.png "/>
But then this exit is going to be amazing.
650) this.width=650; "src=" Http://s5.51cto.com/wyfs02/M02/83/47/wKiom1dui36yZqxBAAB2IyyRz44025.png "title=" 2016-06-25 21-47-02 screen. png "alt=" Wkiom1dui36yzqxbaab2iyyrz44025.png "/>
It took two cd,pwd operations, but exit has to be executed three times to exit, why?
So in order to debug I print analysis of the ID of the process and the ID of the parent process for all instructions executed
650) this.width=650; "src=" Http://s2.51cto.com/wyfs02/M02/83/47/wKiom1dujdXASlAmAACJcz_qrhM324.png "title=" 2016-06-25 21-57-00 screen. png "alt=" Wkiom1dujdxaslamaacjcz_qrhm324.png "/>650) this.width=650;" src= "http:// S4.51cto.com/wyfs02/m02/83/47/wkiom1dukvcg_gjyaafcozhcubw358.png "title=" screen Shot 2016-06-25 at 22.11.24.png "alt = "Wkiom1dukvcg_gjyaafcozhcubw358.png"/>
Conclusion:
LS: The first child process created terminates after executing EXECVP
Cd.. The second time the child process is created does not terminate when the chdir is executed
Cd.. The child process that is created the third time its parent process is the second child process created and does not terminate
When the exit is executed, it is terminated from the top to the outside, and then exits the entire program.
Improvement Program:
Write a function that is executed by the CD to the parent process
#include <stdio.h> #include <pwd.h> #include <sys/types.h> #include < unistd.h> #include <string.h> #include <stdlib.h>void prompt () { struct passwd * p1; char username[64]; char hostname[256]; char pathname[1024]; //Get user name p1=getpwuid (getuid ()); //Get path &NBSP;GETCWD (pathname,sizeof (pathname)); //gets the hostname---returns 0 correct if (gethostname (hostname,sizeof ( hostname) ==0) { printf ("[diy %[email protected]%s:%s ]", p1- >pw_name,hostname,pathname); } else { printf ("[DIY %[email protected]:%s ] ", p1->pw_name,pathname); } if (Geteuid () ==0) { printf ("#"); } else { &NBSP;PRINTF ("$"); &NBSP;&NBSP;}} Int main () { while (1) { prompt (); Fflush (stdout); char buf[1024]; memset (Buf,0,sizeof (BUF)); size_t size=read (0,buf,sizeof (BUF)-1); if (size>0) { buf[size-1]= '; } // printf ("%s\n", buf); char *p=buf; int i=0; char * my_argv[64]={0}; my_argv[0]=p; while (*p!=0) { if (*p== ' ') { *p= ' ++p; my_ '; argv[++i]=p; } else { ++p; } } pid_t id=fork (); if (id==0) { if (strcmp (my_argv[0], "exit") ==0) { exit (0); } if (strcmp (my_argv[0], "CD") ==0) { exit (0); } else &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;{&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;EXECVP (MY_ARGV[0],MY_ARGV); } } else { &Nbsp; pid_t ret=waitpid (id,null,0); if (strcmp (my_argv[0], "CD") ==0) { chdir (my_argv[1]); } if (strcmp (my_argv[0], "exit") ==0 ) { exit (0); } } } return 0;}
Results:
650) this.width=650; "src=" Http://s2.51cto.com/wyfs02/M00/83/46/wKioL1dukv2yavyXAABjovQmLPY644.png "title=" 2016-06-25 22-18-15 screen. png "alt=" Wkiol1dukv2yavyxaabjovqmlpy644.png "/>
This article from "Momo is spicy moe" blog, please be sure to keep this source http://momo462.blog.51cto.com/10138434/1792908
Write a mock shell under Linux