2016-10-02 184 views
0

我正在編寫一個shell模擬器,如果用戶鍵入「lsh ls」,我將運行命令ls並忽略用戶輸入的「lsh」。所以我使用readline庫來獲取輸入,然後解析這一行。然後我使用fork()和execvp()來運行ls命令。然而,當我鍵入lsh ls我得到以下輸出:execvp()ls no such file or directory

lsh: ls: No such file or directory 

這裏是我的代碼。我認爲它把ls當作一個搜索文件,但我不明白爲什麼它會這樣做。

int main(){ 
    pid_t id; 
    char* line; 
    char **args; 
    while(1){ 
    line = readline("shell: > "); 
    if(strcmp(line,"exit") == 0){ 
     break; 
    } 
    args = parse(line); 
    if(strcmp(args[0],"lsh") == 0){ 
     id = fork(); 
     if (id == 0){ 
      if(execvp(args[1],args) < 0){ 
       perro("no such command"); 
      } 
     } 
     if(id > 0){ 
      printf("I am the parent process, id %d\n",getppid()); 
     } 
    } 
    free(line); 
    } 
} 

以下是解析該行的函數。

#define LSH_TOK_BUFSIZE 64 
#define LSH_TOK_DELIM " \t\r\n\a" 
char **parse(char *line){ 
    int bufsize = LSH_TOK_BUFSIZE, position = 0; 
    char **tokens = malloc(bufsize * sizeof(char*)); 
    char *token; 
    if (!tokens) { 
    fprintf(stderr, "lsh: allocation error\n"); 
     exit(EXIT_FAILURE); 
    } 

    token = strtok(line, " \n"); 
    while (token != NULL) { 
    tokens[position] = token; 
    position++; 

    if (position >= bufsize) { 
    bufsize += LSH_TOK_BUFSIZE; 
    tokens = realloc(tokens, bufsize * sizeof(char*)); 
    if (!tokens) { 
    fprintf(stderr, "lsh: allocation error\n"); 
    exit(EXIT_FAILURE); 
    } 
    } 

    token = strtok(NULL, LSH_TOK_DELIM); 
    } 
    tokens[position] = NULL; 
    return tokens; 
    free(tokens); 
} 
+1

通過strace -f運行可執行文件來檢查它到底產生了什麼。 execvp最有可能應該是execvp(args [1],args + 1)。 – arsv

+0

在調用'exec之前,添加一些打印所有'args'元素的調試代碼怎麼樣? – alk

+0

我得到args [0] = lsh,args [1] = ls,args [2] = null – penatozawa

回答

3

您看到錯誤消息從ls,不lsh到來。

你有,實際上:

char *args[] = { "lsh", "ls", 0 }; 

execvp(args[1], args); 

這意味着你試圖執行ls,並且做得很成功,但你告訴ls,它被稱爲lsh因爲argv[0]設置爲lsh,並要求其列出當前目錄中的文件ls。所以,當ls嘗試查找文件時,它會失敗,並使用您給它的命令名稱報告錯誤lsh

你可以試試這個(在Mac OS塞拉利昂獲得所示的輸出):

$ cp /bin/ls xx97 
$ ./xx97 23-ish 
xx97: 23-ish: No such file or directory 
$ rm xx97 

您需要使用:

execvp(argv[1], &argv[1]); 

然後你就會在一個正統的方式調用ls

相關問題