Linux_C smsh1

这是一个模拟shell端的程序。

使用了execvp,fork,wait,malloc,realloc以及strtok()函数。

smsh.h

1 char* next_cmd();
2 char** splitline(char* );
3 void freelist(char **);
4 int execute(char** );

smsh1.c

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <unistd.h>
 4 #include <signal.h>
 5 #define DFL_PROMPT ">:"
 6 int main(){
 7   char * cmdline, *prompt, **arglist;
 8   int i;
 9   void setup();
10   prompt = DFL_PROMPT;
11   setup();
12   while((cmdline=next_cmd(prompt, stdin)) != NULL ){
13     if((arglist=splitline(cmdline))!=NULL){
14       for(i=0; i<2; i++)
15     printf("%s  ", arglist[i]);
16       printf("\n");
17       printf("will execute.\n");
18       execute(arglist);
19       freelist(arglist);
20     }
21     free(cmdline);
22   }
23   
24   return 0;
25 }
26 void setup(){
27   /*
28    * purpose: initialize shell
29    * 在shell中忽略信号SIGINT&SIGQUIT, 但是在子进程中恢复对
30    * SIGINT&SIGQUIT的默认操作,允许用户通过按表示结束多文件多Ctrl-D来退出
31    */
32   signal(SIGINT, SIG_IGN);
33   signal(SIGQUIT, SIG_IGN);
34 }

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=='\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 }

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\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 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 }

 关于为什么要开一个进程给execvp()使用,是因为unix运行一个程序;1.将指定的程序复制到调用它的进程。2.将指定的字符串数组作为argv[]传给这个程序。3.运行这个程序。

如果不开进程就来执行execvp(),就会运行完一个命令后就会结束退出。这是因为execvp()用命令指定的程序代码覆盖了shell的程序代码,然后在命令指定的程序结束之后就退出。

posted on 2014-10-31 22:21  Zachary_wiz  阅读(328)  评论(0编辑  收藏  举报

导航