編寫shell (一)

編寫shell

刺蝟@http://blog.csdn.net/littlehedgehog

 

 

 

 

 

編寫shell的第一步: 讓shell可以執行程序

 

只有兩個要點需要注意,第一,unix/linux提供相應的執行函數exec,我們只需要將我們輸入的命令行分解成字符串數組即可。
比如: ls -al  那麼我們只需要將這個字符串拆成argv[0]="ls",argv[1]="-al" 即可。 第二點,需要用fork新建一個進程,在子進程中執行我們的命令,即是execvp(argv[0],argv)

 

代碼參照<understanding unix/linux programming>


 

  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <string.h>
  4. #include <signal.h>
  5. #define BUFSIZE 256
  6. #define PROMPT "kiss winona $:" 
  7. void setup()
  8. {
  9.     signal(SIGINT,SIG_IGN);
  10.     signal(SIGQUIT,SIG_IGN);
  11. }
  12. void fatal(char *err,int n)
  13. {
  14.     perror(err);
  15.     exit(n);
  16. }
  17. /* 下面是封裝malloc 和 remalloc*/
  18. void * emalloc(size_t n)
  19. {
  20.     void *ret_p=NULL;
  21.     if((ret_p=malloc(n))!=NULL)
  22.         return ret_p;
  23.     fatal("Out of memory! ",-1);
  24. }
  25. void *erealloc(void *p,size_t n)
  26. {
  27.     void *ret_p=NULL;
  28.     if((ret_p=realloc(ret_p,n))!=NULL)
  29.         return ret_p;
  30.     fatal("Realloc failed! ",-1);
  31. }
  32. char * makestr(char *p)
  33. {
  34.     int len=strlen(p);
  35.     char *ret=emalloc(len+1);
  36.     strncpy(ret,p,len);
  37.     ret[len]='/0';
  38.     return ret;
  39. }
  40. /* 我們需要把一個命令行 轉化爲字符串數組 */
  41. char ** splitline(char *line)
  42. {
  43.     char *p;
  44.     char **argv;
  45.     int argc=0;
  46.     if(!line)
  47.         return NULL;
  48.     argv=emalloc(BUFSIZE);
  49.     p=strtok(line," ");         //目前只是處理了空格
  50.     while(p)
  51.     {
  52.         argv[argc++]=makestr(p);
  53.         p=strtok(NULL," ");
  54.     }
  55.     argv[argc]=0;
  56.     return argv;
  57. }
  58. /* 從標準輸入獲取命令字符串  注意我們用了個動態空間裝載*/
  59. char * get_cmd(char *prompt,FILE *fp)
  60. {
  61.     char c;
  62.     char *buffer;
  63.     int pos=0,bufsize=0;    
  64.     printf("%s ",prompt);
  65.     if(!fp)
  66.         return NULL;
  67.     while((c=getc(fp))!=EOF)
  68.     {
  69.         if(pos+1>=bufsize)  
  70.         {
  71.             if(!bufsize)    
  72.                 buffer=emalloc(BUFSIZE);    
  73.             else            
  74.                 buffer=erealloc(buffer,bufsize+BUFSIZE);
  75.             bufsize+=BUFSIZE;   
  76.         }
  77.         if(c=='/n')
  78.             break;
  79.         buffer[pos++]=c;
  80.     }
  81.     buffer[pos]='/0';
  82.     return buffer;
  83. }
  84. /* 小心內存泄露 */
  85. void freelist(char **argv)
  86. {
  87.     while(*argv)
  88.         free(*argv++);
  89.     free(argv);
  90. }
  91. /* 主要函數: 原理簡單 父進程fork一個子進程並等待  子進程執行命令 */
  92. int execute(char **argv)
  93. {
  94.     int pid,info=-1;
  95.     
  96.     if(!argv[0])
  97.         return 0;
  98.     if((pid=fork())==-1)
  99.         fatal("Fork error ",1);
  100.     else if(!pid)   
  101.     {
  102.         signal(SIGINT,SIG_DFL);
  103.         signal(SIGQUIT,SIG_DFL);
  104.         execvp(argv[0],argv);
  105.         fatal("command not found ",1);
  106.     }
  107.     else
  108.     {
  109.         if(wait(&info)==-1)
  110.             fatal("wait error ",1);
  111.         return info;
  112.     }
  113. }
  114. int main()
  115. {
  116.     char *cmd=NULL,*prompt=NULL,**argv=NULL;        
  117.     prompt=PROMPT;
  118.     setup();
  119.     while((cmd=get_cmd(prompt,stdin))!=NULL)
  120.     {
  121.         if((argv=splitline(cmd))!=NULL)
  122.         {
  123.             execute(argv);
  124.             free(argv);
  125.         }
  126.         free(cmd);      //注意cmd也要釋放
  127.     }
  128.     return 0;
  129. }

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章