我目前正在制作猫计划,必须区分以下情况:
./cat
和
./cat < file1 > file2.txt
这是代码
while((fileFD=read(STDIN_FILENO,str,1000))!=0)// If we just execute the command cat, it will receive input from the stdin and put it in the stdout.
{
write(STDOUT_FILENO,str,fileFD);// Write it to the standard output
if(fileFD==-1)
{
perror("error");
exit(1);
}
}
break;
我使用参数argv和argc来跟踪参数。在这两种情况下,argc = 1,因为&lt;没有考虑到。你会怎么做?
答案 0 :(得分:2)
给定两个文件描述符,一个用于输入,一个用于输出,以下函数可以合理可靠地将数据从输入复制到输出。
#include <unistd.h>
/* Copy file from input file descriptor ifd to output file descriptor ofd */
extern int copy_file(int ifd, int ofd);
int copy_file(int ifd, int ofd)
{
char buffer[65536]; // Resize to suit your requirements
ssize_t i_bytes;
while ((i_bytes = read(ifd, buffer, sizeof(buffer))) > 0)
{
ssize_t bytes_left = i_bytes;
char *posn = buffer;
ssize_t o_bytes;
while ((o_bytes = write(ofd, posn, bytes_left)) > 0)
{
bytes_left -= o_bytes;
posn += o_bytes;
}
if (o_bytes < 0)
return -1;
}
if (i_bytes < 0)
return -1;
return 0;
}
一个简单的最小测试程序可能是:
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
…declaration or definition of file_copy()…
int main(void)
{
int rc = EXIT_SUCCESS;
if (copy_file(STDIN_FILENO, STDOUT_FILENO) != 0)
{
int errnum = errno;
rc = EXIT_FAILURE;
fprintf(stderr, "copy_file failed: (%d) %s\n", errnum, strerror(errnum));
}
return rc;
}
这可以正确地将文件从标准输入复制到标准输出。我还没有明确地测试过短写“#”。这是一种非常罕见的情况,最可能的情况是输出文件描述符是套接字。测试错误路径也更难。我打电话给程序cf89
。一项测试是:
$ (trap '' 13; ./cf89 < /dev/zero) | (sleep 1)
copy_file failed: (32) Broken pipe
$
trap
忽略了SIGPIPE(13),因此写入块因为没有任何东西正在读取管道。当sleep
退出时,写入过程会从write()
收到错误 - 因为信号被忽略 - 并且它会生成错误消息。
顺便说一句,有些人反对在安全方面报告错误号和错误消息 - 如果他们设法触发错误,它会告诉攻击者太多关于系统的信息。我不在那个营地;攻击者在攻击诸如此类的程序时已经知道了系统类型。它可能与其他环境相关,例如可能是Web服务器。
答案 1 :(得分:0)
此命令行:
cat < file1 > file2.txt
只是重定向stdin和stdout,程序不需要做任何特殊的事情。
但是,如果命令行是:
cat file1
然后代码需要重新打开()stdin到文件
如果reopen()失败,可能会向stderr发送消息
在任一组命令行参数中,所有I / O都是从stdin到stdout
答案 2 :(得分:0)
你忘记了其他案件。那么pipelines怎么样,比如
date | ./cat | wc
也许你想测试stdin是否是伪tty(或不是)。首先阅读tty demystified(使用termios(3) ...)。然后考虑使用isatty(3)作为isatty(STDIN_FILENO)
进行测试。但是你应该提供一些覆盖测试的选项。请参阅L. Serrni's deleted answer。
问题看起来像XY problem。