2016-10-02 108 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

相关问题