2017-02-16 82 views
2

我試圖創建一個簡單的c程序,它接受用戶輸入,將它傳遞給底層shell並返回用戶命令的輸出。例如:pwd會給出當前的工作目錄。在C中創建一個類似於程序的shell

我想在一個無限循環做到這一點使用fork()和EXEC(),但我現在面臨兩個問題:第一次運行後

  1. 我的循環終止
  2. 只需要第一個參數。 「LS -ltr」給我「ls」的輸出,而不是「LS -ltr」

    int runit(char*); 
    
    void main() { 
    
    int pid=0;       
    char command[50]; 
    while(1) 
    
    { 
        int d=0; 
        printf("Please enter your command!\n"); 
        scanf("%s", &command); 
        switch (pid = fork()) 
        { 
         case 0:     // a fork returns 0 to the child 
          printf("Child process \n"); 
          d=runit(command); 
          if(d==-1){ 
          printf("command not found \n");} 
          break; 
    
         default: 
          wait(5);    // a fork returns a pid to the parent 
          printf("Parent process \n"); 
          break; 
    
         case -1:     //if something went wrong 
          perror("fork"); 
          exit(1); 
    
        } 
        }     
    } 
    
    int runit(char* command) {      //executing the command 
    
        char path[50]="/bin/"; 
    
        int d = execl(strcat(path,command),command,NULL,NULL);  
    
        return(d); 
    
    } 
    

有人能告訴我什麼,我做錯了或指導我如何糾正。

回答

2

此輸入讀取

scanf("%s", &command); 

將停止在第一個空格(除非出現輸入故障 - 你應該檢查scanf()在任何情況下返回值)。所以,當你輸入ls -ltr時,command將只有ls。您需要閱讀。例如,使用fgets()讀取輸入(並確保處理尾隨換行符):

fgets(command, sizeof command, stdin); 
command[strcspn(command, "\n")] = 0; /* to remove \n if present */ 

而接下來的問題是,execl()需要多個參數。這意味着 這個用法:

int d = execl(strcat(path,command),command,NULL,NULL);  

壞了。您需要將輸入命令拆分爲多個字符串,並將每個參數傳遞給execl()。將單個字符串存儲在數組中並更改execv()的更好選擇。

你需要知道的另一件事情是exec*()家庭功能做成功的回報。所以,返回代碼檢查並不是很有用 - 相反,只需使用perror()即可知道失敗的原因。

+0

謝謝。這真的很有幫助。我從scanf更改爲獲取和修改execl()命令,它的工作。它也適用於execv()。但哪一個更好?我更喜歡execl(),因爲它比execv簡單() –

+0

execl和execv之間沒有「更好」 - 它們只是在它們的參數上有所不同。因此,請根據您的使用情況選擇適合的方式。 – usr

相關問題