【发布时间】:2015-02-15 14:36:32
【问题描述】:
我目前有一个用 C 编写的 Bash 的基本实现。但是,当我尝试两次重定向标准输出时遇到了问题。以下是相关代码:
读取每个命令:
for ( ; ; ) {
printf ("(%d)$ ", nCmd); // Prompt for command
fflush (stdout);
if ((line = getLine (stdin)) == NULL) // Read line
break; // Break on end of file
list = lex (line);
free (line);
if (list == NULL) {
continue;
} else if (getenv ("DUMP_LIST")) { // Dump token list only if
dumpList (list); // environment variable set
printf ("\n");
}
cmd = parse (list); // Parsed command?
freeList (list);
if (cmd == NULL) {
continue;
} else if (getenv ("DUMP_TREE")) { // Dump command tree only if
dumpTree (cmd, 0); // environment variable set
printf ("\n");
}
process (cmd); // Execute command
freeCMD (cmd); // Free associated storage
nCmd++; // Adjust prompt
}
我们是我的代码的外壳部分搞砸了:
if (cmdList->type==SIMPLE)
{
pid_t fork_result;
fork_result = fork();
if (fork_result < 0) {
fprintf(stderr, "Fork failure");
exit(EXIT_FAILURE);
}
if (fork_result == 0) {
if (cmdList->fromType==RED_IN)
{
int fe = open(cmdList->fromFile, O_RDONLY, 0);
dup2(fe, 0);
close(fe);
}
if ((cmdList->toType==RED_OUT) || (cmdList->fromType==RED_APP))
{
int fd = open(cmdList->toFile, O_CREAT | O_WRONLY, 0666);
dup2(fd, 1);
close(fd);
}
execvp(cmdList->argv[0],cmdList->argv);
exit(EXIT_FAILURE);
}
else {
int status;
wait(&status);
}
}
当我阅读一个简单的命令时,这最后的 sn-p 代码完全按照我的意图工作。但是,当我使用 for 循环尝试重定向 stout 两次时,问题就出现了。例如,我尝试运行:
cat Tests/star.wars > +Bash.tmp
cat +Bash.tmp
cat Tests/stk.txt > +Bash.tmp
cat +Bash.tmp
第一个命令将“ABC”写入 Bash.tmp。但是,当我运行第二个命令时,我希望它返回“DE”。但是,我得到“DEC”作为输出。怎么了?
【问题讨论】:
-
你没有在
open调用中使用O_TRUNC? -
我应该这样做吗?我听说 O_WRONLY 应该可以解决问题。
-
O_WRONLY是“只写”权限。O_TRUNC是在打开文件时截断文件的原因。 -
Bash shell 是一个庞大而复杂的代码库(具有许多超出 POSIX 所需的功能)。我认为说你正在实现一个 Unix 或 Bourne 兼容的 shell 会更正确。
-
你的
getLine()只接受一个参数,所以它不是POSIXssize_t getline(char **lineptr, size_t *n, FILE *stream);。你的如何工作?