在smsh1的基础上,只是增加了一层process(),以之来处理if,then,else。
smsh.c 只是更变了一行rv=process();
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <unistd.h> 4 #include <signal.h> 5 #include "smsh.h" 6 7 #define DFL_PROMPT ">:" 8 int main(){ 9 char * cmdline, *prompt, **arglist; 10 int i, rv; 11 void setup(); 12 prompt = DFL_PROMPT; 13 setup(); 14 while((cmdline=next_cmd(prompt, stdin)) != NULL ){ 15 if((arglist=splitline(cmdline))!=NULL){ 16 rv=process(arglist); 17 //freelist(arglist); 18 } 19 //free(cmdline); 20 } 21 return 0; 22 } 23 void setup(){ 24 /* 25 * purpose: initialize shell 26 * 在shell中忽略信号SIGINT&SIGQUIT, 但是在子进程中恢复对 27 * SIGINT&SIGQUIT的默认操作,允许用户通过按表示结束多文件多Ctrl-D来退出 28 */ 29 signal(SIGINT, SIG_IGN); 30 signal(SIGQUIT, SIG_IGN); 31 }
process.c
1 /* process.c 2 * command processing layer 3 */ 4 #include <stdio.h> 5 #include "smsh.h" 6 7 int is_control_command(char *); 8 int do_control_command(char **); 9 int ok_to_execute(); 10 11 int process(char** arglist) { 12 int rv=1; 13 if(arglist[0] == NULL) 14 rv=0; 15 else if(is_control_command(arglist[0]) ) 16 rv=do_control_command(arglist); 17 else if(ok_to_execute()) 18 rv=execute(arglist); 19 return rv; 20 }
controlflow.c
1 /* controlflow.c 2 * "if"processing is done with two state variables 3 * if_state and if_result 4 */ 5 #include <stdio.h> 6 #include "smsh.h" 7 8 enum states {NEUTRAL, WANT_THEN, THEN_BLOCK, WANT_ELSE, ELSE_BLOCK}; 9 // 0 1 2 3 4 10 11 enum results {SUCCESS, FAIL}; 12 // 0 1 13 14 static int if_state = NEUTRAL; 15 static int if_result = SUCCESS; 16 static int last_stat = 0; 17 18 int syn_err(char *); 19 20 int ok_to_execute() { 21 /* purpose: determine to the shell should execute a command 22 * returns: 1 for yes, 0 for no 23 * details: if in THEN_BLOCK and if_result was SUCEESS then yes 24 * if in THEN_BLOCK and if_result was FAIL then no 25 * if in WANT_THEN then syntax error (sh is different) 26 */ 27 int rv = 1; //default is possitive 也就是说如果没有if条件判断的,以下几行都不会执行,直接返回rv=1; 28 if(if_state == WANT_THEN || if_state == WANT_ELSE){ 29 syn_err("then expected"); 30 rv = 0; 31 } 32 else if(if_state==THEN_BLOCK && if_result==SUCCESS){ 33 rv = 1; 34 printf("if_state=THEN_BLOCK if_result=SUCCESS. "); 35 } 36 else if(if_state==THEN_BLOCK && if_result==FAIL){ 37 rv = 0; 38 printf("if_state=WANT_THEN if_result=SUCCESS. "); 39 } 40 else if(if_state==ELSE_BLOCK && if_result==SUCCESS){ 41 rv = 0; 42 printf("if_state=WANT_ELSE if_result=SUCCESS"); 43 } 44 else if(if_state==ELSE_BLOCK && if_result==FAIL) { 45 rv = 1; 46 printf("if_state=ELSE_BLOCK if_result=FAIL"); 47 } 48 printf("rv= %d if_state=%d if_result=%d. ",rv, if_state, if_result); 49 return rv; 50 } 51 52 int is_control_command(char *s) { 53 return (strcmp(s, "if")==0 || strcmp(s,"then")==0 || strcmp(s, "fi")==0 || strcmp(s, "else")==0); 54 } 55 56 int do_control_command(char ** arglist) { 57 char *cmd = arglist[0]; 58 int rv = -1; 59 60 printf("****now in do_control_command begin: if_state=%d, if_result=%d.**** ", if_state, if_result); 61 62 if(strcmp(cmd, "if")==0){ 63 printf("if now. "); 64 if(if_state!=NEUTRAL) 65 rv = syn_err("if unexpected"); 66 else { 67 last_stat=process(arglist + 1); 68 if_result=(last_stat==0?SUCCESS:FAIL); 69 if(if_result==SUCCESS) 70 if_state=WANT_THEN; 71 else 72 if_state=WANT_ELSE; 73 rv=0; 74 } 75 } 76 else if( strcmp(cmd, "then")==0){ 77 printf("then now "); 78 if(if_state!=WANT_THEN && if_state!=WANT_ELSE) 79 rv=syn_err("then unexpected"); 80 if(if_result==SUCCESS) { 81 if_state=THEN_BLOCK; 82 rv=0; 83 } 84 } 85 else if(strcmp(cmd, "else")==0) { 86 printf("else now. "); 87 if(if_state!=WANT_ELSE) 88 rv=syn_err("then unexpected"); 89 if(if_result==FAIL){ 90 if_state=ELSE_BLOCK; 91 rv=0; 92 } 93 else if(if_state==SUCCESS) { //这里是说明一下如果if判断语句为真,执行了then后面的命令后,再出现了else,则需要将if_state更改,不然else后命令依然会执行。 94 if_state=WANT_THEN; 95 rv=0; 96 } 97 } 98 else if(strcmp(cmd, "fi")==0) { 99 printf("fi. "); 100 if(if_state != THEN_BLOCK || if_state!=ELSE_BLOCK) 101 rv=syn_err("fi unexpected"); 102 else { 103 if_state=NEUTRAL; 104 rv=0; 105 } 106 } 107 printf("****now in do_control_command end: if_state=%d if_result=%d**** ", if_state, if_result); 108 return rv; 109 } 110 111 int syn_err(char* msg) { 112 if_state = NEUTRAL; 113 fprintf(stderr, "syntax error: %s ", msg); 114 return -1; 115 }
execute.c
1 /* execute.c- code used by small shell to execute commands 2 */ 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <unistd.h> 6 #include <signal.h> 7 #include <sys/wait.h> 8 9 int execute(char** arglist){ 10 /* 11 *purpose: run a program passing it arguments; 12 *return: status returned via wait, or -1 on error 13 *errors: -1 on fork() on wait() errors 14 */ 15 int pid; 16 int child_info = -1; 17 // printf("now its go into the function execute "); 18 if((pid=fork()) == -1) 19 perror("fork"); 20 else if(pid == 0) { 21 signal(SIGINT, SIG_DFL); 22 signal(SIGQUIT, SIG_DFL); 23 execvp(arglist[0], arglist); 24 perror("cannot execute command"); 25 exit(1); 26 } 27 else { 28 if(wait(&child_info) == -1) 29 perror("wait"); 30 } 31 return child_info; 32 } 33 void freelist(char** list) { 34 /* 35 *purpose: free the list returned by splitline 36 *returns: nothing 37 *actoin: free all strings in list and then free the list 38 */ 39 char **cp=list; 40 while(*cp) 41 free(*cp++); 42 free(list); 43 }
splitline.c
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include "smsh.h" 5 6 char* next_cmd(char* prompt, FILE *fp){ 7 /* 8 * purpose: read next command line from fp 9 * return: dynamically allocated string holding command line 10 * note: allocates space in BUFSIZ chunks.其中BUFSIZ是库函数中define过了的 11 */ 12 char* buf; 13 int bufspace = 0; 14 int pos = 0; 15 int c; 16 printf("%s", prompt); 17 while((c=getc(fp)) != EOF) { 18 if(pos+1>=bufspace) { 19 if(bufspace==0) 20 buf = malloc(BUFSIZ); 21 else 22 buf = realloc(buf, bufspace+BUFSIZ); 23 bufspace+=BUFSIZ; 24 } 25 if(c==' ') 26 break; 27 buf[pos++]=c; 28 } 29 if(c==EOF || pos==0) 30 return NULL; 31 buf[pos]=0; 32 //printf("u cin is end. "); 33 return buf; 34 } 35 36 char** splitline(char* cmdline){ 37 /* 38 * purpose: split a line 39 * note:注意:在最后一次给arglist赋值时,也就是strtok()返回为NULL的时候,也需要给 40 * arglist[i]=malloc(sizeof(char*));一下,即使最后赋的为NULL也需要分配一个指针空间给它。 41 */ 42 char **arglist; 43 char *delim=" "; 44 char *cmdbuf; 45 int i=1; 46 cmdbuf=strtok(cmdline,delim); 47 //printf("cmdbuf0: %s ", cmdbuf); 48 arglist = malloc(sizeof(char*)); 49 arglist[0]=malloc(strlen(cmdbuf)*sizeof(char)); 50 strcpy(arglist[0], cmdbuf); 51 while((cmdbuf=strtok(NULL, delim))) { 52 arglist = realloc(arglist, (1+i)*sizeof(char*)); 53 arglist[i]=malloc(strlen(cmdbuf)*sizeof(char)); 54 strcpy(arglist[i], cmdbuf); 55 //printf("cmdbuf%d: %s ",i,cmdbuf); 56 i++; 57 } 58 arglist[i]=malloc(sizeof(char*)); 59 arglist[i]=NULL; 60 return arglist; 61 }
smsh.h
1 int process(char**); 2 char* next_cmd(); 3 char** splitline(char* ); 4 void freelist(char **); 5 int execute(char** );