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 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 }
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 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 }
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
原文地址:https://www.cnblogs.com/wizzhangquan/p/4069607.html