diff --git a/c/by-line/Makefile b/c/by-line/Makefile new file mode 100644 index 0000000..56b42f6 --- /dev/null +++ b/c/by-line/Makefile @@ -0,0 +1,9 @@ +CC ?= clang +CFLAGS ?= -Wall -Wextra -std=c11 + +all: compilation + +compilation: by-line + +by-line: by-line.c + $(Q)$(CC) -o by-line $(CFLAGS) $(LDFLAGS) $^ diff --git a/c/by-line/by-line.c b/c/by-line/by-line.c new file mode 100644 index 0000000..cf8db61 --- /dev/null +++ b/c/by-line/by-line.c @@ -0,0 +1,104 @@ +#include // printf +#include +#include // memchr +#include // read write +#include // uint32_t +#include // exit +#include // poll + +// OUTPUT: line-by-line strings + +#define line_size_exceeded "line exeeded max buffer size\n" +#define MAXBUFFER 64000 + +char buf[MAXBUFFER]; + +void err(int error, const char *str) { + fprintf (stderr, "%s\n", str); + exit(error); +} + +int main(int argc, const char **argv) +{ + if (argc > 1) { + printf ("usage: %s\n", argv[0]); + return 0; + } + + // fcntl(0, F_SETFL, O_SYNC); + + uint32_t tot_read = 0; + uint32_t n_read = 0; + struct pollfd pfd[1]; + int nready; + + pfd[0].fd = 0; + + while (1) { + pfd[0].events = POLLIN; + nready = poll(pfd, 1, 60 * 1000); + + if (nready == -1) + err (1, "poll"); + + if (nready == 0) { + fprintf (stderr, "time out\n"); + } + + if ((pfd[0].revents & (POLLERR|POLLNVAL))) { + fprintf (stderr, "bad fd %d", pfd[0].fd); + err (1, "bad fd"); + } + + if ((pfd[0].revents & (POLLIN|POLLHUP))) { + n_read = read(0, buf, sizeof(buf)); + if (n_read > 0) { + // fprintf (stderr, "read %u characters\n", n_read); + + tot_read += n_read; + // fprintf(stderr, "total read %u\n", tot_read); + // fprintf(stderr, "could still read %u\n", MAXBUFFER - tot_read); + if (tot_read == MAXBUFFER) { + // print anyway + write (1, buf, tot_read); + write (2, line_size_exceeded, strlen(line_size_exceeded)); + printf(buf); + n_read = 0; + tot_read = 0; + continue; + } + + // print line by line (if any) + char * p = NULL; + while ((p = memchr(buf, '\n', tot_read)) != NULL) { + uint32_t remaining = tot_read - (p - buf) - 1; + write (1, buf, tot_read - remaining); + // fprintf (stderr, "found retline, %u remaining chars\n", remaining); + + for (uint32_t i = 0; i < remaining ; i++) { + buf[i] = buf[i + tot_read - remaining]; + } + tot_read = remaining; + n_read = 0; + } + + } + else if (n_read == 0) { + // fprintf (stderr, "EOF\n"); + break; + } + else { + err (1, "read"); + } + } + } + + if (tot_read > 0) { + // fprintf(stderr, "print the %u characters remaining in the buffer\n", tot_read); + write (1, buf, tot_read); + } + + // fprintf (stderr, "end of the loop\n"); + + return 0; +}