#include <stdio.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
#include <poll.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>

static int pipe_fds[2];

static void print_rate(int sig)
{
        char foo = 0;
        write(pipe_fds[1], &foo, sizeof(foo));
}

int main(int argc, char **argv)
{
        struct itimerval itv;
        struct sigaction sa;
        struct pollfd pollfds[2];
        unsigned int count;
        int fd, ret;

        if (argc > 1) {
                ret = open(argv[1], O_RDONLY);
                if (ret < 0) {
                        perror("open");
                        return ret;
                }
                fd = ret;
        } else
                fd = 0; /* STDIN */

        ret = pipe(pipe_fds);
        if (ret < 0) {
                perror("pipe");
                return ret;
        }

        sigemptyset(&sa.sa_mask);
        sa.sa_flags = 0;
        sa.sa_handler = print_rate;
        ret = sigaction(SIGALRM, &sa, NULL);
        if (ret < 0) {
                perror("sigaction");
                return ret;
        }

        itv.it_value.tv_sec = 1;
        itv.it_value.tv_usec = 0;
        itv.it_interval.tv_sec = 1;
        itv.it_interval.tv_usec = 0;
        ret = setitimer(ITIMER_REAL, &itv, 0);
        if (ret < 0) {
                perror("setitimer");
                return ret;
        }

        for (;;) {
                char buf[256];

                pollfds[0].fd = fd;
                pollfds[0].events = POLLIN;
                pollfds[0].revents = 0;

                pollfds[1].fd = pipe_fds[0];
                pollfds[1].events = POLLIN;
                pollfds[1].revents = 0;

                ret = poll(pollfds, 2, 0);
                if (ret < 0) {
                        if (errno == EAGAIN || errno == EINTR)
                                continue;
                        break;
                }

                if (pollfds[0].revents & POLLIN) {
                        ret = read(fd, buf, sizeof(buf));
                        if (ret >= 0)
                                count += ret;
                        else
                                break;
                }

                if (pollfds[1].revents & POLLIN) {
                        read(pipe_fds[0], buf, 1);
                        printf("Rate: %u bytes/s\n", count);
                        count = 0;
                }
        }

        return ret;
}