构建一个基本的shell,更具体地使用execvp()

问题描述:

在我的程序中,我将用户输入并将其解析为2d char数组。该阵列声明为:构建一个基本的shell,更具体地使用execvp()

char parsedText[10][255] = {{""},{""},{""},{""},{""}, 
      {""},{""},{""},{""},{""}}; 

我使用fgets来抓取用户输入并用sscanf解析它。这一切都按我的想法运作。

在此之后,我想将parsedText传递给execvp,parsedText [0]应该包含路径,如果提供了任何参数,那么它们应该在parsedText [1]通过parsedText [10]。

execvp(parsedText [0],parsedText [1])有什么问题?

有一点可能值得一提的是,如果我只提供一个没有任何参数的“ls”这样的命令,它似乎工作得很好。

这是我的代码:

#include <stdio.h> 
#include <string.h> 
#include <unistd.h> 
#include "308shell.h" 

int main(int argc, char *argv[]) 
{ 
char prompt[40] = "308sh"; 
char text[40] = ""; 
char parsedText[10][40] = {{""},{""},{""},{""},{""}, 
          {""},{""},{""},{""},{""}}; 

// Check for arguments to change the prompt. 
if(argc >= 3){ 
    if(!(strcmp(argv[1], "-p"))){ 
     strcpy(prompt, argv[2]); 
    } 
} 

strcat(prompt, "> "); 

while(1){ 
    // Display the prompt. 
    fputs(prompt, stdout); 
    fflush(stdout); 

    // Grab user input and parse it into parsedText. 
    mygetline(text, sizeof text); 
    parseInput(text, parsedText); 

    // Check if the user wants to exit. 
    if(!(strcmp(parsedText[0], "exit"))){ 
     break; 
    } 
    execvp(parsedText[0], parsedText[1]); 
    printf("%s\n%s\n", parsedText[0], parsedText[1]); 
} 

return 0; 
} 

char *mygetline(char *line, int size) 
{ 
if (fgets(line, size, stdin)) 
{ 
    char *newline = strchr(line, '\n'); /* check for trailing '\n' */ 
    if (newline) 
    { 
     *newline = '\0'; /* overwrite the '\n' with a terminating null */ 
    } 
} 

return line; 
} 

char *parseInput(char *text, char parsedText[][40]){ 
char *ptr = text; 
char field [ 40 ]; 
int n; 
int count = 0; 

while (*ptr != '\0') { 
    int items_read = sscanf(ptr, "%s%n", field, &n); 
    strcpy(parsedText[count++], field); 
    field[0]='\0'; 
    if (items_read == 1) 
     ptr += n; /* advance the pointer by the number of characters read  */ 
    if (*ptr != ' ') { 
     strcpy(parsedText[count], field); 
     break; /* didn't find an expected delimiter, done? */ 
    } 
    ++ptr; /* skip the delimiter */ 
} 

} 

execvp需要一个指针的指针(char **),而不是一个指针数组。它应该是指向char *指针数组的第一个元素的指针,由空指针终止。

编辑:这里有一个(不太好)的方式来作出适当的指针数组为execvp

char argbuf[10][256] = {{0}}; 
char *args[10] = { argbuf[0], argbuf[1], argbuf[2], /* ... */ }; 

当然在现实世界中你的争论很可能来自一个命令行字符串用户输入,并且它们之间可能至少有一个字符(例如空格),所以更好的方法是修改原始字符串,或者复制它,然后修改重复项,添加空终止符在每个参数之后并设置args[i]指向字符串的右偏移量。

您可以在每个步骤中做很多动态分配(malloc),但是您必须编写代码来处理每个可能的故障点。 :-)

+0

我想我还是有点困惑(char **)。那么我会如何正确定义这些char数组? 此外,这是作业,所以我完全用一个简单的例子。不要试图把我的作业当作/。 – tgai 2011-02-05 22:25:45