如何在C中区分以下两种情况

时间:2017-04-09 06:24:14

标签: c unix

我目前正在制作猫计划,必须区分以下情况:

./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;没有考虑到。你会怎么做?

3 个答案:

答案 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

顺便说一下,您可能需要使用poll(2)。阅读Advanced Linux Programming

问题看起来像XY problem