編寫簡單的shell命令解析器

來源:互聯網
上載者:User

                                                     編寫簡單的shell命令解析器

環境:

RedHat 9.0    核心 2.4.20

vi 文書編輯器  6.1.320

gcc  3.2.2-5

 

實現步驟:

 

第0步:寫一個最簡單的shell命令直譯器,本程式取自APUE例1-5,命令不能帶參數。

 

需要完成的內容如下:

  1. 命令直譯器首先是一個死迴圈。

  2. 列印一個命令提示字元。

  3. 取得命令列輸入放在數組裡面,不要求命令帶參數。可以getc()、fgets()、scanf()等。

  4. 如果用fgets()的話,取得的字串包括最後輸入的分行符號,故要去掉命令字串末尾的“/n”,變成“/0”。

  5. 建立一個子進程,調用exec執行命令。

  6. 父進程調用waitpid()等待子進程的退出,然後進入下一次迴圈。

 

第1步:寫一個shell命令直譯器,使能處理帶參數的命令。

 

需要完成的內容如下:

  1. 命令直譯器首先是一個死迴圈。

  2. 列印一個命令提示字元,包含當前路徑資訊。取得命令列輸入,本程式是把命令列輸入儲存在一個字元指標指向的地址中。

  3. 分析命令列,把以空格分開的命令和參數

分別取出來放在字元指標數組arg[]中。這裡取得的命令列字串儲存在input指向的地址。為了把這一行字串中的命令和參數分開,需要一個臨時數組tmp(本程式是重用前面使用的buf數組),把input指向命令列中的命令和參數分別儲存在arg[0]、arg[1]等等。

    4 .  建立一個子進程,調用exec執行命令。

    5.   父進程(即shell命令直譯器)根據命令是在前台還是後台運行,決定是否調用waitpid()。然後進入下一次迴圈。

 

第2步:加入內部命令cd、exit。

 

需要完成的內容如下:

  

     1.以第1步為基礎,在分析完命令列輸入後,看輸入的命令arg[0]是不是“exit”或者“cd”,如果是的話,在執行建立子進程去執行這個命令之前就做為內部命令執行。

     2.exit命令的實現只要列印一句話“Bye bye!”,然後釋放前面分配的記憶體空間,然後退出即可。

       3.cd命令的實現用到函數chdir(arg[1]),它用來改變當前工作目錄。

 

第3步:程式的實現分別放在幾個檔案中,引入標頭檔的概念。引入重新導向和管道函數,但不用具體實現這兩個函數。

 

需要完成的內容如下:

     1.引入標頭檔,把公用的變數和函數放在標頭檔中,注意防止標頭檔被重複包含。

     2. 處理使用者輸入的命令列中包含重新導向符號和管道符號的情況。使用函數redirect()和my_pipe()處理重新導向和管道,這兩個函數的實現放在一個單獨的檔案中,不用具體實現這兩個函數。

 

第4步:引入環境變數設定檔mysh_profile,讀取環境變數,判斷檔案是否存在,若存在,執行命令,否則列印“command not found”。

 

需要完成的內容如下:

    1.建立一個環境變數設定檔,裡面的內容是一行PATH環境變數如下:PATH=/bin:/sbin:/usr/bin:/usr/sbin

      2.建立函數init_environ(),讀取環境變數到數組。

    3.建立函數is_founded(),尋找檔案,看檔案是否存在。

 

第5步:實現重新導向功能。

 

需要完成的內容如下:

    在redirect.c檔案中實現redirect()函數。

 

第6步:實現管道功能

 

需要完成的內容如下:

    在pipe.c檔案中實現my_pipe()函數。

 

第7步:實現記錄命令history

 

需要完成的內容如下:

     1. 在標頭檔mysh.h中增加表示記錄的迴圈數組的資料類型,並定義相應變數。

     2. 在history.c中實現函數add_history()和history_cmd()。

     3.在main.c中,分別在管道、重新導向、內部命令、普通命令執行前,把命令列內容加入到命令記錄迴圈數組中。

 

第8步:實現後台作業隊列,加入內部命令jobs、bg、fg命令。

 

 

 

 

 

測試完成的功能:

第0步驟:
1. 要求每個命令完成後,重新列印出提示符
2. 測試:ls cat 等命令

第1步驟:參數
1. 提示符中出現當前路徑資訊。
2. 測試命令“ls”,“ls<空格>”,“<空格>ls”,“<空格>ls<空格>”
   “ls -a -l”  ,“<空格>ls <多個空格> -a <多個空格>-l”

第2步驟:cd exit
1. 測試"cd ..", "cd /home" , "cd -" , "cd~" 等命令

第4步驟:環境變數
1. 把/bin/ls檔案拷貝到/home目錄,
    並將/bin/ls重新命名為/bin/ls-bk,測試ls命令
2.在環境變數檔案mysh_profile中添加"/home"目錄,測試ls命令

第5步驟:重新導向
1. 測試 "ls>test" , "ls(空格)>(空格)test" , "ls(空格)>test"命令
2. 測試 "ls>>test" , "ls(空格)>>(空格)test" , "ls(空格)>>test"命令
3. 測試"cat<test" , "cat(空格)<(空格)test",  "cat(空格)<test"命令
4. 測試"cat>test<test1", "cat>test1<test"命令。test由 "ls -al >> test"產生

第6步驟:管道
1. 測試"ls(空格)|(空格)more"命令

第7步驟:記錄
1. 測試用上下鍵從記錄中提取命令

第8步驟:作業管理
1. 測試jobs, bg , fg, "Ctrl+c","Ctrl+z" 命令

 

 

總結:這個項目主要涉及到的知識:進程式控制制、進程通訊。當然,c語言的基礎是最重要的。

        項目的準系統已實現,但存在一些待解決問題:1.曆史命令調出,對之進行增減後還不能執行相應的命令;2.jobs鏈表的建立沒加上判斷條件,導致執行後台命令時鏈表儲存重複的內容。

 

原始碼位置:

http://download.csdn.net/source/1237870

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.