我目前正在开发一个cat程序,必须区分以下情况:
./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 因为 < 右侧的任何内容都不会被考虑在内。你会怎么做?
最佳答案
给定两个文件描述符,一个用于输入,一个用于输出,以下函数将数据从输入相当可靠地复制到输出。
#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 服务器。
关于c - C语言中如何区分以下两种情况,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43303710/