before starting the code, let's take a look at what a shell is. Shell English is also called the shell layer. In a computer, "system" software that "provides user interface", usually refers to the command parser of the command line interface. In general, this term refers to the program that provides access to the services provided by the kernel in the operating system. But the word also refers to the application software, or any other "software" on the periphery of a particular component ... Omit 300 words ...-----> Thanks for 36,000
Common Shell Categories:
-
BASH: is the GNU Bourne Again Shell, which is the default shell on the GNU operating system
Korn Shell: The development of the Bourne Shell, which is compatible with Bourne Shell (Bash) on most content
C Shell: The BSD version of Sun's shell
Z Shell:z is the last letter, the ultimate Shell. It integrates the critical features of Bash Ksh while adding its own unique features.
Look at where the shell is on the computer and what it uses
650) this.width=650; "Src=" Http://s5.51cto.com/wyfs02/M01/82/96/wKiom1dcGw7hC9cAAADHHF1XCqk395.png-wh_500x0-wm_3 -wmp_4-s_755992057.png "title=" Computer hardware and software components. png "alt=" wkiom1dcgw7hc9caaadhhf1xcqk395.png-wh_50 "/>
This custom shell uses a multi-process approach, with interprocess communication using pipe (pipe).
directly on the code.
#include <stdio.h> #include <stdlib.h> #include <string.h> #include < unistd.h> #include <sys/wait.h> #include <sys/types.h> #include <fcntl.h># Include <sys/stat.h> #include <errno.h>typedef struct __info{charbuf[1024];// User input Information unsigned intpipenum;//count the number of pipelines}info;//record host name default localhoststatic char hostname[1024] = "localhost";//Error hint Int sys_err (const char* err) {perror (err); exit (exit_failure);} Message hint Void display () {static unsigned int sum = 1;//record input count char buf[1024] = { 0 };//gets the current path GETCWD (buf, sizeof (BUF));p rintf ("[#%d#%[email protected]%s]> ", sum, hostname, buf); sum++;} /* * user Input content processing * @reminder info incoming structure * return: * success: Exit_ success * failure: Exit_failure*/int handle (info* info) {if (null == info) {priNTF ("func %s err: [null == info]\n", __function__); exit (Exit_failure); char* p = info->buf;//count the number of pipes while (null != (P&NBSP;=&NBSP;STRCHR (p, ' |))) {info->pipenum++;p + +;} p = info->buf;//Remove Carriage return if (null != (P&NBSP;=&NBSP;STRCHR (p, ' \ n '))) {*p = ' ‘;} return exit_success;} Character Substitution int replate (char* str, const char src, const char des) {if (NULL &NBSP;==&NBSP;STR) {printf ("func %s error: [null == str]\n", __function__); exit ( Exit_failure);} Char* p =str;while (*p) {if (src == *p) {*p = des;} p++;} return exit_success;} Command parsing Int resolverun (CHAR*&NBSP;PTR,&NBSP;CHAR**&NBSP;ARGV) {if (null == ptr | | &NBSP;NULL&NBSP;==&NBSP;ARGV) {printf ("func %s error:[null == ptr | | null == argv]\n ", __function__); exit (exit_failure);} Int i = 0;iNt fd;char* inptr = null;char* p = strtok_r (ptr, " ", & INPTR) Argv[i++] = p;while (null != (P = strtok_r (null, " ", & INPTR))) {argv[i++] = p;} Determine if there is a redirect I--;while (i) {if (0 == strcmp (argv[i], > ")) {Fd = open (argv[i+1], o_ wronly | o_creat | o_trunc, 0644), if (0&NBSP;>&NBSP;FD) {Sys_err ("func Resolverun () open error: ");} Backup output to 1023 descriptor Dup2 (stdout_fileno, 1023);d up2 (Fd, stdout_fileno); Argv[i] = null;close (FD); /Find First >int n = 1;while (n < i) {if (0 == strcmp (argv[n], >)) { Argv[n] = null;break;} n++;} break;} if (0 == strcmp (argv[i], ">>")) {Fd = open (argv[i+1], o_append| O_creat| o_wronly, 0644); if (0&NBSP;>&NBSP;FD) {Sys_err ("Func resolverun () open error: ");} Dup2 (stdout_fileno, 1023);d up2 (Fd, stdout_fileno); Argv[i] = null;close (FD);//Find the first >int n = 1;while (n < i) {if (0 == strcmp (argv[n], >>)) {Argv[n] = null ; break;} n++;} break;} if (0 == strcmp (argv[i], "<")) {Fd = open (argv[i+1], o_rdonly); if (0 > &NBSP;FD) {Sys_err ("Func resolverun () open error: ");} Char buf[1024] = { 0 };int len = 0;while (0 != (len = read (fd, buf, sizeof (BUF))) {if (0 > len) {Sys_err ("Func resolverun () read error: ");} Write (Stdin_fileno, buf, len); Bzero (Buf, sizeof (BUF));} Outputs a terminator to the end -1PUTC ( -1, stdin_fileno); Argv[i] = null;close (FD);//Find the first >int n = 1;while (n < i) {if (0 == strcmp (argv[n], <)) {argv[n] = null; break;} n++;} break;} i--;} return exit_success;} Split command int&Nbsp;seve (Info* info) {if (null == info) {printf ("func %s err: [null == Info]\n ", __function__); exit (exit_failure);} Determines whether the empty data if (0 == * (info->buf)) {return exit_success;} pid_t pid;pid_twpid;char buf[1024] = { 0 };char* p = buf;char* inptr = null;int i = 0;int fd[2];char* argv[256] = {null};/ /Copy the original data memcpy (buf, info->buf, sizeof (BUF));//Processing tab replate (buf, ' \ t ', ' ');//Processing ' Number replate (buf, ' \ ', ' ');//Processing "number replate (buf, ' \" ', ' '); for (i = 0; i <= info->pipenum; i++) {if (0 == i) {p = strtok_r (p, "|", &NBSP;&INPTR);} Else{p = strtok_r (null, "|", &inptr);} Initialize Bzero (argv, sizeof (argv));//Command parsing resolverun (P,&NBSP;ARGV);//Determine if the built-in command if (0 == i & &&NBSP;0&NBSP;==&NBSP;STRCMP ("CD", Argv[0]) {if (0 > chdir (argv[1])) {//Judgment error type, prompt user information if (enoent == errno) {printf ("-sea_bash: cd: %s: does not have that file or directory \ n ", argv[1]);} if (Eacces == errno) {printf ("-sea_bash: cd: %s: permissions not enough \ n", argv[1]);} if (Enotdir == errno) {printf ("-sea_bash: cd: %s: is not a directory \ n", argv[1]);}} return exit_success;} Else if (0 == i && 0 == strcmp ("pwd", argv[0])) {char buf[ 1024]&NBSP;=&NBSP;{&NBSP;0&NBSP;};GETCWD (buf, sizeof (BUF));//Get Current working directory Buf[strlen (buf)] = ' \ n '; Add a newline write (Stdout_fileno, buf, strlen (BUF)) at the end of the //,//print the current path to the screen return exit_success;//the successful end}else if (0 == i && 0 == strcmp ("hostname", argv[0]) {//emptying bzero ( HOSTNAME,&NBSP;SIZEOF (hostname));//Empty the original hostname memcpy (Hostname, argv[1], strlen (argv[1]));// Reset hostnamereturn exit_success;} Else if (0 == i &&amP;&NBSP;0&NBSP;==&NBSP;STRCMP ("Exit", argv[0])) {//End Process printf ("-------------------- God-bey-----------------------------\ n "), Kill (Getpid (), sigint),//Send the end signal to the process exit (exit_success);//Direct Process exit}/ /Create Pipeline if (0 > pipe (FD)) {Sys_err ("Func seve () pipe error: ");} Pid = fork (); if (0 > pid) {Sys_err ("Func seve () fork error:");} Else if (0 == pid) {close (fd[0]);//Sub-process close read dup2 (1022, fd[0]);//Direct read end multiplicity of the previous pipe to Fd[0]close (1022) ;//Close 1022 read end of the previous signal, avoid the existence of multiple read end break;//out}//restore output descriptor dup2 (1023, stdout_fileno);//Save the read end to the next process using Dup2 (fd[0], 1022); Close (fd[1]); Close (fd[0]);} The child process handles if (i != info->pipenum+1) {//No pipe command if (0 != info->pipenum) {if (i == Info->pipenum) {Close (fd[1]);d up2 (Fd[0], stdin_fileno);} if (0 == i) {dup2 (Fd[1], stdout_fileno);} Else{dup2 (Fd[0], stdin_fileno);d up2 (Fd[1], stdout_fileno);}} EXECVP (ARGV[0],&NBSP;ARGV);p rintf ("-sea_bash: %s: command&Nbsp;not found\n ", argv[0]); exit (exit_failure);} The parent process waits for the child process to end if (i == info->pipenum+1) {do{wpid = waitpid ( -1, null, wnohang); 0 < wpid) {i--;}} while (0 < i);} return exit_success;} Int main (int argc, char* argv[]) {info info = {{0}, 0};for (;;) {display ();//Get user input fgets (info.buf, sizeof (INFO.BUF), stdin);//Information processing handle (&info);//Split command Seve (& info);//emptying Initialization bzero (&info, sizeof (info));} return exit_success;}
This article is from the "Sea" blog, be sure to keep this source http://lisea.blog.51cto.com/5491873/1788026
Make your own Linux-->shell