views:

272

answers:

2

I need to print the content of a fifo (named pipe) to standard output.
I could use the command:

cat fifo

The problem is that cat doesn't return. It stays running, waiting for more content coming from the fifo. But I know there wont be any more content coming for a while so I just want to print what's available.

Is there a command that just print the available content and exit??

EDIT:
In one end of the fifo there is a process writing every now and then the output of different commands. That process is permanently running so there wont be an EOF.

A: 

You should close the other end of the FIFO. That should send an EOF to the cat process.

0x6adb015
I know, but that's exactly the problem. There wont be an EOF never because the process at the other end will keep sending data every once in a while.
GetFree
+2  A: 

When you can't send an EOF, you could use a 'non-blocking cat'. I've included a (tested) C version i found here (credit goes to the original author over there of course). The magic is in fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK).

The first argument to this non-blocking cat is the number of seconds you want to wait before exiting again.

#include <stdio.h>
#include <fcntl.h>
#include <time.h>
#include <unistd.h>
#include <string.h>


void read_loop(int fFile, double wWait)
{
    if (fFile < 0) return;

    double max_time = wWait, total_time = 0;
    struct timespec cycle_time = { 0, 50 * 1000 * 1000 };
    double add_time = (double) cycle_time.tv_sec + (double) cycle_time.tv_nsec / 1000000000.;

    char next_line[1024];

    FILE *input_file = fdopen(fFile, "r");

    while (total_time < max_time)
    {
    while (fgets(next_line, 1024, input_file))
     {
    write(STDOUT_FILENO, next_line, strlen(next_line));
    total_time = 0;
     }

    nanosleep(&cycle_time, NULL);
    total_time += add_time;
    }

    fclose(input_file);
}


int main(int argc, char *argv[])
{
    if (argc < 2)
    {
    fprintf(stderr, "%s [max time] (files...)\n", argv[0]);
    return 1;
    }

    int max_wait = strtoul(argv[1],0, 10);

    if (argc == 2)
    {
    fprintf(stderr, "%s: using standard input\n", argv[0]);
    fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);
    read_loop(STDIN_FILENO, max_wait);
    return 0;
    }

    int current = 2;

    while (current < argc)
    {
    fprintf(stderr, "%s: switch to file '%s'\n", argv[0], argv[current]);
    int next_file = open(argv[current++], O_RDONLY | O_NONBLOCK);
    read_loop(next_file, max_wait);
    close(next_file);
    }

    return 0;
}
ChristopheD
I didn't expect to come to this extent. I was hoping there was a built-in Linux command for this. Anyway, I'm using this "non-bloking cat" already. I changed it a bit though; I didn't like the floating point arithmetics so I changed it to integer arithmetics and I also changed the time argument to accept miliseconds. Thanks.
GetFree