編寫簡單的shell命令解析器
環境:
RedHat 9.0 核心 2.4.20
vi 文書編輯器 6.1.320
gcc 3.2.2-5
實現步驟:
第0步:寫一個最簡單的shell命令直譯器,本程式取自APUE例1-5,命令不能帶參數。
需要完成的內容如下:
命令直譯器首先是一個死迴圈。
列印一個命令提示字元。
取得命令列輸入放在數組裡面,不要求命令帶參數。可以getc()、fgets()、scanf()等。
如果用fgets()的話,取得的字串包括最後輸入的分行符號,故要去掉命令字串末尾的“/n”,變成“/0”。
建立一個子進程,調用exec執行命令。
父進程調用waitpid()等待子進程的退出,然後進入下一次迴圈。
第1步:寫一個shell命令直譯器,使能處理帶參數的命令。
需要完成的內容如下:
命令直譯器首先是一個死迴圈。
列印一個命令提示字元,包含當前路徑資訊。取得命令列輸入,本程式是把命令列輸入儲存在一個字元指標指向的地址中。
分析命令列,把以空格分開的命令和參數
分別取出來放在字元指標數組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