首页 > 代码库 > Linux_C smsh2(if,then,else)

Linux_C smsh2(if,then,else)

在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 shell26    * 在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.\n"); 35   } 36   else if(if_state==THEN_BLOCK && if_result==FAIL){ 37     rv = 0; 38     printf("if_state=WANT_THEN  if_result=SUCCESS.\n"); 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.\n",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.****\n", if_state, if_result); 61  62   if(strcmp(cmd, "if")==0){ 63     printf("if now.\n"); 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\n"); 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.\n"); 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.\n");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****\n", 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\n", 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 error13    *errors: -1 on fork() on wait() errors14    */15   int pid;16   int child_info = -1;17   //  printf("now its go into the function execute\n");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 splitline36    *returns: nothing37    *actoin: free all strings in list and then free the list38    */39   char **cp=list;40   while(*cp)41     free(*cp++);42   free(list);43 }
execute.c

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 line10    * 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==\n)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.\n");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\n", 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\n",i,cmdbuf);56     i++;57   }58   arglist[i]=malloc(sizeof(char*));59   arglist[i]=NULL;60   return arglist;61 }
splitline.c

smsh.h

1 int process(char**);2 char* next_cmd();3 char** splitline(char* );4 void freelist(char **);5 int execute(char** );
smsh.h

 

Linux_C smsh2(if,then,else)