gpt4 book ai didi

C Minishell 命令扩展打印乱码

转载 作者:行者123 更新时间:2023-11-30 15:53:52 25 4
gpt4 key购买 nike

我正在用 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展开.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);

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

char expanded_line[EXPANDEDLEN];

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

expand(line, expanded_line, EXPANDEDLEN);

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

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

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

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

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

最佳答案

您的问题在于expCmdOutput。正如您已经注意到的,使用 read 读取子进程的输出时,您不会获得 NUL 终止的字符串。您想要做的是通过添加类似的内容来手动终止字符串

    buf[bytes_read] = '\0';

在第 29 行 (expand.c) 中调用 read 之后。因为 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 附加到末尾(或者通过保存指向字符串末尾的指针以提高效率)。

关于C Minishell 命令扩展打印乱码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13447205/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com