【问题标题】:Building a basic shell, more specifically using execvp()构建一个基本的 shell,更具体地说是使用 execvp()
【发布时间】:2011-02-05 22:11:38
【问题描述】:

在我的程序中,我接受用户输入并将其解析为二维字符数组。数组声明为:

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 */
}

}

【问题讨论】:

    标签: c linux unix exec execvp


    【解决方案1】:

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

    编辑:这是一种(不是很好)制作适合execvp的指针数组的方法:

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

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

    您可以在每一步都进行大量动态分配 (malloc),但是您必须编写代码来处理每个可能的故障点。 :-)

    【讨论】:

    • 我想我还是对 (char **) 有点困惑。那么我将如何尝试正确定义这些 char 数组呢?这也是家庭作业,所以我对一个简单的例子完全没问题。不要试图在/上典当我的作业。
    猜你喜欢
    • 1970-01-01
    • 2021-02-26
    • 1970-01-01
    • 2011-03-25
    • 2013-12-27
    • 2010-09-16
    • 2012-09-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多