This seems to work for me:
#include <fcntl.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
static void set_non_blocking(int fd)
{
    int flags  = fcntl(fd, F_GETFL, 0 );
    flags |= O_NONBLOCK;
    flags = fcntl(fd, F_SETFL, flags);
}
int main(int argc, char ** argv)
{
    int fd = fileno(stdin);
    char buf[10];
    set_non_blocking(fd);
    while (read(fd, buf, sizeof buf) < 0) {
        perror("read");
        sleep(1);
    }
    return 0;
}
or you could use select:
int main(int argc, char ** argv)
{
    int fd = fileno(stdin);
    struct timeval tv = {0,0};
    fd_set fdset;
    int s;
    do {
        sleep(1);
        FD_ZERO(&fdset);
        FD_SET(fd, &fdset);
    } while ((s = select(fd+1, &fdset, NULL, NULL, &tv)) == 0);
    if (s < 0) {
        perror("select");
    }
    return 0;
}
Poll works too :-)
int main(int argc, char ** argv)
{
    struct pollfd pfd;
    int s;
    pfd.fd = fileno(stdin);
    pfd.events = POLLRDNORM;
    while ((s = poll(&pfd, 1, 0)) == 0) {
        perror("polling");
        sleep(1);
    }
    if (s < 0) {
        perror("poll");
    }
    return 0;
}
One last way is to set the terminal in 'raw' mode.  Note that this upsets output to the terminal (at least on mine on OS-X) in that \r becomes necessary after \n.  Note also that it needs to be undone at the end (the terminating tcsetattr call).  This is the only one that does not need a \n (ie any keypress will do)
#include <poll.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <termios.h>
static void set_non_blocking(int fd)
{
    int flags = fcntl(fd, F_GETFL, 0) | O_NONBLOCK;
    if (fcntl(fd, F_SETFL, flags) < 0) {
        perror("fcntl");
        exit(EXIT_FAILURE);
    }
}
int main(int argc, char ** argv)
{
    struct termios params;
    struct termios params_orig;
    char buf[10];
    int fd = fileno(stdin);
    if (tcgetattr(fd, ¶ms) < 0) {
        perror("tcgetattr");
        exit(EXIT_FAILURE);
    }
    params_orig = params;
    cfmakeraw(¶ms);
    if (tcsetattr(fd, TCSANOW, ¶ms) < 0) {
        perror("tcsetattr");
        exit(EXIT_FAILURE);
    }
    set_non_blocking(fd);
    while (read(fd, buf, sizeof buf) < 0) {
        perror("\rread");
        sleep(1);
    }
    (void) tcsetattr(fd, TCSANOW, ¶ms_orig);
    return 0;
}