我应该在C中编写一个简单的自定义shell,它可以只使用“<”处理重定向和“>”命令。
要做到这一点,我正在解析每个命令(在一个字符串数组中),检查字符'<'和'>'然后打开一个文件名open(fd, filename, flags)
来读取或写入。
如果我发出这些命令(%表示我的shell),我希望得到以下输出:
% echo hello > output.txt
% cat output.txt
hello
然而,当我发出这些命令,以及任何命令时,它似乎忽略(但不是忽略?)我的重定向。当我发出相同的命令时会发生这种情况:
% echo hello > output.txt
% cat output.txt
hello > output.txt
奇怪的是,它确实创建了一个名为“output.txt”的文件,并写入“hello> output.txt”
输入和输出重定向器都会发生这种情况。这是打开和执行输出命令的代码。
int fd;
open_write_file(&fd, commands[index]);
dup2(fd, 1);
execvpe(commands[0], commands, envp);
close(fd);
请注意open_write_file()
打开文件名,标记为O_WRONLY | O_TRUNC | O_CREAT, S_RUSR | S_IRGRP | S_IWGRP | S_IWUSR
,并进行错误检查以确保正确打开。我怎样才能解决这个问题并让它真正执行我想要的实际命令?
答案 0 :(得分:2)
open
的语法是fd = open(path, flags, [mode]);
如果是>
,您最好使用fd = creat(path, mode);
系统调用,默认情况下会覆盖并创建。
解析时,execvpe
的argv数组应包含第一个重定向符号>
或<
的参数,但不包括这些参数。 argv数组应该有一个最后一个NULL指针元素来表示它的结束。
重定向应该在子进程中的fork()
系统调用之后发生,否则你的shell会失去其标准IO,而exec
将完全擦除它。
/* Parse input line, create argv array, and inputfile/outputfile names */
...
if (fork() == 0) {
/* Child process: stdin redirection */
fd_in = open(inputfile, O_RDONLY);
close(0);
dup(fd_in);
close(fd_in);
/* Child process: stdout redirection */
fd_out = creat(outputfile, 0644);
close(1);
dup(fd_out);
close(fd_out);
/* Child process: exec other program */
execvp(argv[0], argv); /* Does NOT return */
} else {
/* Parent process: wait until child process exits */
wait();
}
对exec
系统调用系列的作用存在一般性误解。他们只是丢弃当前程序并将其替换为CURRENT PROCESS中的另一个程序。他们没有回来,因为无处可回。
人们通常的意思是,可以使用fork
exec
wait
系统调用来完成,见上文。