Simulate Linux shell and Linuxshell
After learning about Linux Process Control, I learned about fork and exec Function Families. Through these functions, I can simply implement a shell, which is to implement a command line interpreter, of course, it is a simple version. The implementation functions are as follows:
The regular expression cannot be implemented yet. To implement this code, I cannot use it at all. I need to rewrite it again...
Post Code below
1 # include <stdio. h> 2 # include <unistd. h> 3 # include <string. h> 4 # include <sys/types. h> 5 # include <sys/wait. h> 6 # include <stdlib. h> 7 # include <pwd. h> 8 # include <sys/utsname. h> 9 # include <libgen. h> 10 11 12 void eatblank (char ** buf) 13 {14 while (** buf = '') 15 {16 (* buf) ++; 17} 18} 19 20 21 void GetHostName (char * hostname, int length) 22 {23 gethostname (hostname, length); 24 char * p = hostna Me; 25 while (* p! = '\ 0') 26 {27 if (* p = '. ') 28 {29 * p =' \ 0'; 30} 31 p ++; 32} 33} 34 35 void Pipe (char ** my_argv, char * buf ); 36 void BuildCommand (char ** my_argv, char * buf) 37 {38 eatblank (& buf); 39 my_argv [0] = buf; 40 int index = 1; 41 char * p = buf; 42 while (* p! = '\ 0') 43 {44 if (* p = '') 45 {46 * p =' \ 0'; 47 p ++; 48 eatblank (& p); 49 if (* p! = '|') 50 {51 my_argv [index ++] = p; 52} 53 continue; 54} 55 else if (* p = '| ') 56 {57 p ++; 58 // p ++; 59 my_argv [index] = NULL; 60 Pipe (my_argv, p ); 61} 62 else 63 {64 p ++; 65} 66} 67 my_argv [index] = NULL; 68} 69 70 71 72 void Pipe (char ** my_argv, char * buf) 73 {74 int fd [2]; 75 pipe (fd); 76 pid_t id2 = fork (); 77 if (id2 = 0) 78 {79 close (1); 80 dup (fd [1]); 81 close (fd [1]); 82 close (fd [0]); 83 execvp (my_argv [0], my_argv); 84} 85 else 86 {87 waitpid (id2, NULL, 0); 88 close (0 ); 89 dup (fd [0]); 90 close (fd [0]); 91 close (fd [1]); 92 BuildCommand (my_argv, buf ); 93 execvp (my_argv [0], my_argv); 94} 95 // Add the exec family function 96} 97 98 99 int main () 100 {101 while (1) here) 102 {103 char * my_argv [64]; 104 struct passwd * pwd = getpwuid (getuid (); 105 char hostname [256] = {'\ 0 '}; 106 char cwd [256] = {'\ 0'}; 107 getcwd (cwd, 256); 108 GetHostName (hostname, 256 ); 109 printf ("[% s @ % s] #", pwd-> pw_name, hostname, basename (cwd); 110 fflush (stdout ); 111 char buf [1024]; 112 buf [0] = '\ 0'; 113 114 int count = read (0, buf, sizeof (buf )); 115 buf [count-1] = '\ 0'; 116 my_argv [0] = buf; 117 pid_t id = fork (); 118 if (id = 0) 119 {120 // child121 122 if (strncmp (buf, "cd", 2) = 0) 123 {124 exit (1); 125} 126 BuildCommand (my_argv, buf); 127 execvp (my_argv [0], my_argv); 128 printf ("if the process has some problem, I shocould run here \ n"); 129 exit (0 ); 130} 131 else132 {133 // father134 int status = 0; 135 wait (& status); 136 if (status = 256) 137 {138 my_argv [0] + = 3; 139 chdir (my_argv [0]); 140} 141} 142 return 0; 143}
Use gethostname to obtain the host name.GetcwdObtain the current working directoryGetpwuidObtains information about the currently logged-on user.
This completes the command prompt;
- Implementation of Common commands
The Implementation of Common commands is not difficult. My goal is to let sub-processes execute commands, that is, to let the sub-processes generated by fork execute the exec family functions.And then die, Recycle resources through the parent process, and create a new sub-process. This is the shell framework, where execvp function is used to execute commands, the function prototype will not be discussed much. You can find it in the manual. briefly explain the parameters. The first parameter is the command line string, and the second parameter is a string array, which is stored from top to bottom, command, parameter (there may be multiple parameters, one parameter occupies one subscript), and the end is indicated by NULL occupying one subscript.
- Cd command implementation
There are some problems with the implementation of cd commands, not the implementation of common commands. That is to say, it is impossible to simply use execvp, because even if the sub-process changes the directory, it will also kill itself, the parent process and child process are disconnected (That is to say, the parent process and the child process do not share the environment variables. The environment variables modified by the child process in the current working directory have no impact on the parent process.). Later, if you use system to execute system calls, it will also fail, because more often the shell will generate a sub-process to execute commands, because the shell itself may be executed at risk, the user may be suspended due to incorrect operations, so the sub-process is used to execute the command. This is the same as the result just now and will not affect the parent process, finally, the chdir function is used to change the working directory in the environment variable of the current process (specifically used to change dir) and run the parent process, the child process that comes out of fork will have a copy of the environment variable of the parent process. This completes Directory change and passes the result.
1 else 2 { 3 //father 4 int status=0; 5 wait(&status); 6 if(status==256) 7 { 8 my_argv[0]+=3; 9 chdir(my_argv[0]);10 }11 }
- Pipeline operator implementation
Pipeline operator implementation is very simple. When we execute commands, results are automatically output to the computer screen. This shows that the output of General commands is written to stdout, the parameter of the output command is through the keyboard, which indicates that the input source of the command is standard input stdin. If we disable it,Standard output and standard input, but a pipeline is used to write the results into the pipeline, then, let the parameters be read from the pipeline (simply put, let the two sections of the pipeline Replace the standard input and standard output), and the pipeline operator is implemented..
1 void Pipe(char ** my_argv,char *buf) 2 { 3 int fd[2]; 4 pipe(fd); 5 pid_t id2=fork(); 6 if(id2==0) 7 { 8 close(1); 9 dup(fd[1]);10 close(fd[1]);11 close(fd[0]);12 execvp(my_argv[0],my_argv);13 }14 else15 {16 waitpid(id2,NULL,0);17 close(0);18 dup(fd[0]);19 close(fd[0]);20 close(fd[1]);21 BuildCommand(my_argv,buf);22 execvp(my_argv[0],my_argv);23 }