Fix buffering bug: use read() for reading instead of fgets()
stdin is buffered and using fgets() invokes read(), which could read multiple lines at one, while reporting only first of them. Testcase: { echo a; echo b; while sleep 1; do :; done; } | lemonbar only outputs a.
This commit is contained in:
parent
50fe7d2083
commit
eb0e9e79b9
53
lemonbar.c
53
lemonbar.c
|
@ -1263,6 +1263,7 @@ main (int argc, char **argv)
|
||||||
xcb_expose_event_t *expose_ev;
|
xcb_expose_event_t *expose_ev;
|
||||||
xcb_button_press_event_t *press_ev;
|
xcb_button_press_event_t *press_ev;
|
||||||
char input[4096] = {0, };
|
char input[4096] = {0, };
|
||||||
|
size_t input_off = 0;
|
||||||
bool permanent = false;
|
bool permanent = false;
|
||||||
int geom_v[4] = { -1, -1, 0, 0 };
|
int geom_v[4] = { -1, -1, 0, 0 };
|
||||||
int ch, areas;
|
int ch, areas;
|
||||||
|
@ -1352,16 +1353,50 @@ main (int argc, char **argv)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (poll(pollin, 2, -1) > 0) {
|
if (poll(pollin, 2, -1) > 0) {
|
||||||
if (pollin[0].revents & POLLHUP) { // No more data...
|
if (pollin[0].revents & (POLLIN | POLLHUP)) { // New input (or no more data)
|
||||||
if (permanent) pollin[0].fd = -1; // ...null the fd and continue polling :D
|
if (input_off == sizeof(input)) {
|
||||||
else break; // ...bail out
|
input_off = 0;
|
||||||
}
|
}
|
||||||
if (pollin[0].revents & POLLIN) { // New input, process it
|
ssize_t r;
|
||||||
if (fgets(input, sizeof(input), stdin) == NULL)
|
while ((r = read(0, input + input_off, sizeof(input) - input_off)) < 0 && errno == EINTR)
|
||||||
break; // EOF received
|
;
|
||||||
|
if (r < 0) {
|
||||||
|
perror("read");
|
||||||
|
break;
|
||||||
|
} else if (r == 0) { // No more data...
|
||||||
|
if (permanent) pollin[0].fd = -1; // ...null the fd and continue polling :D
|
||||||
|
else break; // ...bail out
|
||||||
|
} else {
|
||||||
|
const size_t end = input_off + r;
|
||||||
|
// find the last occurence of \n and one before it
|
||||||
|
size_t last = -1, prelast = -1;
|
||||||
|
while (1) {
|
||||||
|
const size_t from = last + 1;
|
||||||
|
if (from == end) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const char *t = memchr(input + from, '\n', end - from);
|
||||||
|
if (!t) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
prelast = last;
|
||||||
|
last = t - input;
|
||||||
|
}
|
||||||
|
if (last == -1) {
|
||||||
|
// no newline found
|
||||||
|
input_off = end;
|
||||||
|
} else {
|
||||||
|
input[last] = '\0';
|
||||||
|
parse(input + (prelast + 1));
|
||||||
|
redraw = true;
|
||||||
|
|
||||||
parse(input);
|
const size_t n = end - (last + 1);
|
||||||
redraw = true;
|
if (n) {
|
||||||
|
memmove(input, input + (last + 1), n);
|
||||||
|
}
|
||||||
|
input_off = n;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (pollin[1].revents & POLLIN) { // The event comes from the Xorg server
|
if (pollin[1].revents & POLLIN) { // The event comes from the Xorg server
|
||||||
while ((ev = xcb_poll_for_event(c))) {
|
while ((ev = xcb_poll_for_event(c))) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user