Skip to content

Instantly share code, notes, and snippets.

@osa1
Last active November 27, 2020 19:37
Show Gist options
  • Save osa1/aede6d2d80b5c2992294ef9522ab03a5 to your computer and use it in GitHub Desktop.
Save osa1/aede6d2d80b5c2992294ef9522ab03a5 to your computer and use it in GitHub Desktop.
// clang -Wall main.c -o main -DNONBLOCK
#include <errno.h>
#include <fcntl.h>
#include <poll.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
void main_loop();
bool read_until_empty();
int main()
{
#if defined(NONBLOCK)
int old_stdin_flags = fcntl(STDIN_FILENO, F_GETFL);
fcntl(STDIN_FILENO, F_SETFL, old_stdin_flags | O_NONBLOCK);
printf("Enabled non-blocking mode\n");
#endif
bool fail = false;
int tty = open("/dev/tty", O_RDWR);
if (tty == -1) {
printf("Unable to open /dev/tty\n");
fail = true;
goto cleanup;
}
struct termios old_termios;
if (tcgetattr(STDIN_FILENO, &old_termios) == -1) {
printf("tcgetattr failed\n");
fail = true;
goto cleanup;
}
struct termios new_termios = old_termios;
cfmakeraw(&new_termios);
// These really need to be after cfmakeraw() !!!!
new_termios.c_cc[VMIN] = 0;
new_termios.c_cc[VTIME] = 0;
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &new_termios) == -1) {
printf("tcsetattr failed\n");
fail = true;
goto cleanup;
}
printf("Type 'q' to quit.\n");
main_loop();
cleanup:
tcsetattr(STDIN_FILENO, TCSAFLUSH, &old_termios);
#if defined(NONBLOCK)
fcntl(STDIN_FILENO, F_SETFL, old_stdin_flags);
printf("Restored stdin flags\n");
#endif
if (fail) {
return 1;
}
}
void main_loop()
{
printf("main_loop\n");
struct pollfd fds[1] = { { .fd = STDIN_FILENO, .events = POLLIN } };
for (;;)
{
printf("Calling poll()...\n");
int poll_ret = poll(fds, 1, -1);
if (poll_ret > 0)
{
printf("stdin ready for reading\n");
if (read_until_empty())
{
return;
}
}
}
}
bool read_until_empty()
{
uint8_t buf[10000];
for (;;)
{
printf("Calling read()...\n");
ssize_t n_read = read(STDIN_FILENO, buf, 10000);
if (n_read == -1)
{
if (errno == EAGAIN || errno == EWOULDBLOCK)
{
printf("EAGAIN or EWOULDBLOCK\n");
return false;
}
else
{
printf("Error %d: %s\n", errno, strerror(errno));
return false;
}
}
else if (n_read == 0)
{
printf("stdin is empty\n");
return false;
}
else
{
printf("Read %zd bytes\n", n_read);
if (buf[0] == 3 || buf[0] == 113)
{
return true;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment