gpt4 book ai didi

c - 在用户创建的 Shell 中实现重定向工作不正常

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:34:00 24 4
gpt4 key购买 nike

我正在尝试创建一个类似于 bash 的 shell,带有重定向和管道。

在我的 main() 中,我调用了一个解析器,然后调用了下面的函数。我遇到的问题是,当我运行 shell 时,它会正确输出到终端,但在使用 >1>,或 2>

例如,如果我调用:

pwd > foo5.txt

我最终收到:

> 
foo5.txt

在文本文件中,我也写了与 stdout(对于“>”/“1>”)或 stderr(对于“2>”)相反我正在努力实现。

这是我创建子进程的代码:

pid_t create_process(char *part, int const pipes[][2], int pipenum)
{
pid_t pid; // Initialize variables/pointers/arrays.
char *args[64];
int argc=0, n;
char *arg=strtok(part, " \t");
//char const **filename = args;


while(arg != NULL)
{
args[argc++]=arg;
arg=strtok(NULL, " \t");
}

args[argc++]=NULL;

pid = fork(); // Create Fork.

if(pid == 0)
{
int m;

if(pipes[pipenum][STDIN_FILENO] >= 0)
dup2(pipes[pipenum][STDIN_FILENO], STDIN_FILENO); // FD 0.

if(pipes[pipenum][STDOUT_FILENO] >= 0)
dup2(pipes[pipenum][STDOUT_FILENO], STDOUT_FILENO); // FD 1.

// Close all pipes.
for(m=0; m<64; m++)
{
if(pipes[m][STDIN_FILENO] >= 0)
close(pipes[m][STDIN_FILENO]);
if(pipes[m][STDOUT_FILENO] >= 0)
close(pipes[m][STDOUT_FILENO]);
}

char *filename;
char *newargs[64];
newargs[63] = NULL;
int i = 0;
int j = 0;
for(i = 0; i<64; i++)
{
if (args[i] == ">")
{
i++;
if (args[i] != NULL)
{
filename = args[i];
int redir = open(filename, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IRGRP | S_IWGRP | S_IWUSR);
dup2(redir, 1);
close(redir);
}
}
else if (args[i] == "2>")
{
i++;
if (args[i] != NULL)
{
filename = args[i];
int redir = open(filename, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IRGRP | S_IWGRP | S_IWUSR);
dup2(redir, 2);
close(redir);
}
}

else if (args[i] == "2>")
{
i++;
if (args[i] != NULL)
{
filename = args[i];
int redir = open(filename, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IRGRP | S_IWGRP | S_IWUSR);
dup2(redir, 2);
close(redir);
}
}
else if (args[i] == 0)
{
break;
}
else
{
newargs[j] = args[i];
j++;
cout<<"The arg is: " << newargs[j] <<endl;
}
}

execvp(newargs[0], newargs);
fprintf(stderr, "Command not found.\n");
exit(255);

}

else if(pid < 0)
{ // Error checking.
fprintf(stderr, "Fork Failed\n");
}

return(pid);
}

更新:现在我的代码将无法识别这些命令,正在打印的参数(用于错误检查)显示如下:

ls > foo5.txt 
The arg is: fprintf
The arg is:
The arg is: ▒
Command not found.

最佳答案

我在这里看到了一些问题:

首先,您有一个 for 循环,您可以在其中扫描重定向语法的命令参数(if (strcmp(args[i],">")==0)等等)- 但如果条件为真(意思是你找到了一个重定向字符)你总是打开 args[2],而不是 args[i+1]。

其次(这就是重定向语法作为命令参数传递给您正在运行的命令的原因)-一旦检测到重定向语法,就不会从参数列表中删除重定向运算符或目标文件名你传递给 execvp()。

例如,如果 args[] = {"echo", "a", ">", "logfile", 0},您的代码检测到将输出发送到名为“logfile”的新文件并重定向的请求FD 正确,但它仍然将这三个参数 ["a"、">"、"logfile"] 传递给命令。

第三 - 在你的循环中,你在每个条件语句的末尾调用 execvp() - 这意味着你在启动新进程之前不会结束参数处理。您需要处理 shell 语法的所有命令参数,然后执行命令。

要解决 arg 处理的各种问题,最有效的解决方案可能是在处理用户提供的原始参数列表时构建一个新的参数列表。例如(为简洁起见,使用 a==b 作为字符串相等性测试)

if (args[i] == ">")
{
i++; //skip the arg
if (args[i]) { // check we haven't hit the end of the arg list
filename = args[i];
// then open the file, dup it to stdout or whatever, etc...
}
else if (args[i] == "<") // repeat for other redirection syntax...
else { // Finally, handle the case where we didn't identify any shell syntax:
newargs[j] = args[i]; // Copy the arg to the new list, since it isn't "special"
j++; // Size of newargs[] has been increased
}

请注意,这仍然无法处理诸如“>”字符周围没有空格之类的事情:“echo foo>file”只会打印“foo>file”……在这种情况下,语法处理会变得有点复杂,因为您必须考虑引用规则和转义字符才能正确处理参数。

关于c - 在用户创建的 Shell 中实现重定向工作不正常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22717718/

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