diff --git a/dvtm.c b/dvtm.c index cf48f89..7e4a54d 100644 --- a/dvtm.c +++ b/dvtm.c @@ -1657,19 +1657,10 @@ get_cmd_by_name(const char *name) { } static void -handle_cmdfifo(void) { - int r; - char *p, *s, cmdbuf[512], c; +process_cmdbuf(char *p) { + char *s, c; Cmd *cmd; - r = read(cmdfifo.fd, cmdbuf, sizeof cmdbuf - 1); - if (r <= 0) { - cmdfifo.fd = -1; - return; - } - - cmdbuf[r] = '\0'; - p = cmdbuf; while (*p) { /* find the command name */ for (; *p == ' ' || *p == '\n'; p++); @@ -1751,6 +1742,51 @@ handle_cmdfifo(void) { } } +static void +handle_cmdfifo(void) { + static char buf[4096]; + static size_t len; + static bool skipping; + ssize_t r; + size_t end; + + r = read(cmdfifo.fd, buf + len, sizeof buf - 1 - len); + if (r < 0 && (errno == EINTR || errno == EAGAIN)) + return; + if (r <= 0) { + cmdfifo.fd = -1; + return; + } + len += r; + + if (skipping) { + char *nl = memchr(buf, '\n', len); + if (!nl) { + len = 0; + return; + } + len -= nl + 1 - buf; + memmove(buf, nl + 1, len); + skipping = false; + } + + for (end = len; end > 0 && buf[end - 1] != '\n'; end--); + if (!end) { + if (len == sizeof buf - 1) { + len = 0; + skipping = true; + } + return; + } + + char next = buf[end]; + buf[end] = '\0'; + process_cmdbuf(buf); + buf[end] = next; + memmove(buf, buf + end, len - end); + len -= end; +} + static void handle_mouse(void) { #ifdef CONFIG_MOUSE diff --git a/test/test_dvtm.py b/test/test_dvtm.py index bec77be..13e326d 100644 --- a/test/test_dvtm.py +++ b/test/test_dvtm.py @@ -117,6 +117,20 @@ def test_cmd_fifo(self): self.p.expect_exact('title-x') self.p.expect_exact('from-42') + def test_cmd_fifo_split_writes(self): + fd = os.open(self.cmdfifo, os.O_WRONLY) + os.write(fd, b"create 'echo split-$((6*7)); sleep 60' ti") + time.sleep(0.5) + os.write(fd, b"tle-y\n") + os.close(fd) + self.p.expect_exact('title-y') + self.p.expect_exact('split-42') + + def test_cmd_fifo_long_input(self): + with open(self.cmdfifo, 'w') as f: + f.write("create 'echo ok-$((6*7)); sleep 60' " + 'x' * 600 + '\n') + self.p.expect_exact('ok-42') + def test_status_fifo(self): with open(self.status, 'w') as f: f.write('hello-status\n')