summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDominique Martinet <asmadeus@codewreck.org>2022-01-28 16:25:03 +0900
committerDominique Martinet <asmadeus@coderweck.org>2022-01-28 16:25:17 +0900
commitd1726fd170b088e45e439e5b8308a650ddbf2ee3 (patch)
treed88af697c32c987e28fbfe0fec2fe555816ecfa6
parenta444771cb5d3dc1f7696cdc9262bf84f5c1bfab3 (diff)
fix more bugs than could be enumerated...
- would overwrite to-be-printed content with memmove occasionally - empty lines (n) would be considered as EOF early and make tailburst exit - if no line was found in a read buffer would be grown even if not required (e.g. no current usage check before growing :|)
-rw-r--r--tailburst.c91
1 files changed, 58 insertions, 33 deletions
diff --git a/tailburst.c b/tailburst.c
index 1c621f2..b5b919e 100644
--- a/tailburst.c
+++ b/tailburst.c
@@ -30,59 +30,83 @@ ssize_t fdgetline(int fd, struct getline_states *line) {
return -ENOMEM;
line->base[0] = '\0';
line->read = 0;
- line->next = NULL;
+ line->next = line->base;
+ line->cur = NULL;
}
- /* Skip after previously returned line */
- if (line->next)
- line->cur = line->next;
- else
- line->cur = line->base;
-
/* Do we already have a full line in buffer? */
- if ((str = strchr(line->cur, '\n'))) {
+ if (line->read > 0 && (str = strchr(line->next, '\n'))) {
+ line->cur = line->next;
line->next = str+1;
str[0] = '\0';
pr_debug("next already buffered, %p %p: %s\n", str, line->cur, line->cur);
- return str - line->cur;
+ return 1;
}
/* No such luck, move current to base and read what we can */
- if (line->cur != line->base) {
- pr_debug("moving cur: %p, base: %p, read: %zd, moving %zd\n", line->cur, line->base, line->read, line->cur - line->base);
+ if (line->cur && line->cur != line->base) {
+ pr_debug("moving cur: %p, base: %p, read: %zd, moving %zd\n",
+ line->cur, line->base, line->read, line->cur - line->base);
line->read -= line->cur - line->base;
- memmove(line->base, line->cur, line->read);
+ line->next -= line->cur - line->base;
+ memmove(line->base, line->cur, line->read + 1); /* also move trailing \0 */
line->cur = line->base;
}
- /* clear errno before read */
- errno = 0;
-
- while ((nread = read(fd, line->base + line->read, line->size - line->read)) > 0 ) {
+ /* search from here */
+ while (1) {
+ errno = 0;
+ nread = read(fd, line->base + line->read, line->size - line->read - 1);
+ if (nread < 0) {
+ if (errno == EAGAIN)
+ return 0;
+ break;
+ }
+ if (nread == 0) {
+ /* EOF */
+ return -1;
+ }
pr_debug("read %zd\n", nread);
line->read += nread;
+ line->base[line->read] = '\0';
/* Check if we have a full line now */
- if ((str = strchr(line->base, '\n'))) {
- line->next = str+1;
+ if ((str = strchr(line->next, '\n'))) {
+ line->cur = line->next;
+ line->next = str + 1;
str[0] = '\0';
pr_debug("found stuff, %p %p %p: %s\n", str, line->base, line->cur, line->cur);
- return str - line->base;
+ return 1;
}
- /* realloc bigger buffer and try again */
+ /* realloc bigger buffer and try again if sensible */
+ if (line->size - line->read > 100)
+ continue;
+ if (line->size > 1024) {
+ /* pretend this was a full line.. */
+ line->cur = line->next;
+ line->next = line->base + line->read;
+ return 1;
+ }
line->size *= 2;
- line->base = realloc(line->base, line->size);
- if (line->base == NULL)
+ pr_debug("growing buffer to %zd\n", line->size);
+
+ char *newbase = realloc(line->base, line->size);
+ if (newbase == NULL)
return -ENOMEM;
+ if (line->cur) {
+ pr_debug("base-cur was %p-%p, new %p-%p\n", line->base, line->cur, newbase, newbase + (line->cur - line->base));
+ line->cur = newbase + (line->cur - line->base);
+ }
+ line->next = newbase + (line->next - line->base);
+ line->base = newbase;
}
- pr_debug("got here? %zd %d\n", nread, errno);
+ pr_debug("read failed? %zd %d\n", nread, errno);
- line->next = line->cur;
if (errno)
return -errno;
- return 0; /* no line read */
+ return -1; /* unknown error? */
}
@@ -92,7 +116,6 @@ int main(int argc, char **argv)
ssize_t nread;
struct pollfd pollfd;
struct getline_states line = { 0 };
- char *cur;
/* non-buffered output */
setlinebuf(stdout);
@@ -105,16 +128,18 @@ int main(int argc, char **argv)
pollfd.fd = fd;
pollfd.events = POLLIN;
while (poll(&pollfd, 1, -1) > 0) {
- cur = NULL;
- while ((nread = fdgetline(fd, &line)) > 0)
- cur = line.cur;
+ line.cur = NULL;
+ while ((nread = fdgetline(fd, &line)) > 0);
- if (cur)
- printf("%s\n", cur);
+ if (line.cur)
+ printf("%s\n", line.cur);
- /* eof */
- if (nread == 0)
+ /* eof or error */
+ if (nread < 0)
break;
+
+ /* throttle in case something tries to wake us up every few ms... */
+ sleep(1);
}
return 0;