我正要用C语言编写一个shell。这是下面的代码:fgets()调用重定向获取异常数据流
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/wait.h>
#include <stdlib.h>
int
getcmd(char *buf, int nbuf)
{
memset(buf, 0, nbuf);
fgets(buf, nbuf, stdin);
printf("pid: %d, ppid: %d\n", getpid(), getppid());
printf("buf: %s", buf);
if(buf[0] == 0) {// EOF
printf("end of getcmd\n");
return -1;
}
return 0;
}
int
main(void)
{
static char buf[100];
int fd, r, ret;
// Read and run input commands.
while((ret = getcmd(buf, sizeof(buf))) >= 0){
if(fork() == 0)
exit(0);
wait(&r);
}
exit(0);
}
当我执行编译的可执行文件:标准输入重定向到一个名为t.sh文件,该文件的内容是“1111 \ n2222 \ n”个像./myshell<吨。 SH,输出为:
pid: 2952, ppid: 2374
buf: 1111
pid: 2952, ppid: 2374
buf: 2222
pid: 2952, ppid: 2374
buf: 2222
pid: 2952, ppid: 2374
buf: end of getcmd
显然,函数getcmd()得到3行(1111,2222,2222),而仅存在2 t.sh.线在t.sh中放置更多行时,这些情况会变得更糟。
而主进程是执行getcmd的唯一进程,我们可以通过pid的输出来判断。顺便说一下,我发现如果等待的代码行(&r)被移除,输出就会正常。
其实很有趣。我可以在* 4.10.0-19-generic#21上重现行为 - Ubuntu SMP Thu Apr 6 17:04:57 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux *。当从文件重定向时,似乎每次都会重置文件指针。 –
这可能解释代码':)'中未使用的'int fd'' –
我可以在Ubuntu 16.04 LTS上重现问题;它不会在macOS Sierra 10.12.6上重现。它在某种程度上反映了Linux库中的一个错误,但这很奇怪 - 它的另一种选择是Linux中编译器的错误。我不得不修改代码来关注Linux上'fgets()'的返回值;我用'-Werror'进行编译,并被告知'忽略'fgets'的返回值,用属性warn_unused_result'声明。 (macOS头文件不使用该功能。)我还必须处理各种其他警告(未使用的变量,变量设置但未使用等) –