0

我正在用 C 编写一个 unix minishell,并且正在添加命令扩展。我的意思是我可以将命令嵌套在其他命令中,例如:

$> echo hello $(echo world! ... $(echo and stuff))
hello world! ... and stuff

我想我大部分时间都在工作,但是它没有正确标记扩展字符串的结尾,例如,如果我这样做:

$> echo a $(echo b $(echo c))
a b c
$> echo d $(echo e)
d e c

看到它打印 c,即使我没有要求它。这是我的代码:

msh.c - http://pastebin.com/sd6DZYwB expand.c - http://pastebin.com/uLqvFGPw

我有更多代码,但有很多,这些是我目前遇到问题的部分。我会试着告诉你我这样做的基本方法。

Main 在 msh.c 中,这里它从命令行或 shellfile 中获取一行输入,然后调用 processline (char *line, int outFD, int waitFlag),其中 line 是我们刚刚得到的行,outFD 是输出文件的文件描述符,waitFlag 告诉我们如果我们 fork 是否应该等待。当我们从 main 调用它时,我们这样做:

processline (buffer, 1, 1);

在 processline 中,我们分配一个新行:

char expanded_line[EXPANDEDLEN];

然后我们在 expand.c 中调用 expand:

expand(line, expanded_line, EXPANDEDLEN);

在 expand 中,我们将字符从 line 复制到 expand_line,直到找到 $(,然后调用:

static int expCmdOutput(char *orig, char *new, int *oldl_ind, int *newl_ind)

orig 是线,new 是扩展线。oldl_ind 和 newl_ind 分别是行和扩展行中的当前位置。然后我们通过管道递归调用 processline,将嵌套命令传递给它(例如,如果我们有“echo a $(echo b)”,我们将传递 processline“echo b”)。

这就是我感到困惑的地方,每次调用 expand 时,它是否分配了一块新的内存 EXPANDEDLEN 长?如果是这样,这很糟糕,因为我会很快用完堆栈空间(在大量嵌套的命令行输入的情况下)。在扩展中,我在扩展字符串的末尾插入了一个空字符,那么为什么它会打印过去呢?

如果你们需要更多代码或解释,请询问。其次,我将代码放在 pastebin 中,因为它有很多,而且根据我的经验,当我用代码填满几页时人们不喜欢它。

4

1 回答 1

1

你的问题在于expCmdOutput。正如您已经注意到的,在使用read. 你想要做的是手动终止字符串,通过添加类似

    buf[bytes_read] = '\0';

在您致电read第 29 行 (expand.c) 之后。Sicne 你需要 NUL 的空间,BUF_SIZE - 1当然你最多只能读取字节。

不过,您可能应该重新考虑之后执行的整个循环:

    /* READ OUTPUT OF COMMAND FROM READ END OF PIPE, THEN CLOSE READ END */
    bytes_read = read(fd[0],buf,BUF_SIZE);
    while(bytes_read > 0)
    {
            bytes_read = read(fd[0], buf, BUF_SIZE);
            if (bytes_read == -1) perror("read");
    }
    close(fd[0]);

如果您的命令输出长于 BUF_SIZE,您只需再次读取到buf,覆盖您刚刚读取的输出。您在这里真正想要的是分配内存并使用strcat(或通过持有指向字符串末尾的指针以提高效率)追加到末尾。

于 2012-11-19T10:37:04.650 回答