tquery

Interactive command query tool
git clone https://git.sinitax.com/sinitax/tquery
Log | Files | Refs | LICENSE | sfeed.txt

commit 6fd3dd30b0f770da97721851bda47ddea678c1b2
parent f7f1e147b5dbbf34617b8727e53acecbad67c24a
Author: Louis Burda <quent.burda@gmail.com>
Date:   Sat,  8 Jul 2023 11:24:26 +0200

Fix reading out-of-bounds entries + improvements

Diffstat:
MMakefile | 6+++---
Mtquery.c | 81++++++++++++++++++++++++++++++++++++++++---------------------------------------
2 files changed, 44 insertions(+), 43 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,9 +1,9 @@ PREFIX ?= /usr/local BINDIR ?= /bin -CFLAGS = -std=c99 -D_XOPEN_SOURCE=700 -Og -g \ - -Wunused-function -Wunused-variable -Wconversion -Wsign-compare -LDLIBS = -lcurses +CFLAGS = -std=c99 -D_XOPEN_SOURCE=700 -Og -g -Wunused-function \ + -Wunused-variable -Wconversion -Wsign-compare -Wuninitialized +LDFLAGS = -lcurses all: tquery diff --git a/tquery.c b/tquery.c @@ -12,19 +12,24 @@ #include <stdio.h> #include <stdlib.h> +#define LOAD_BUFSIZ 16384 +#define INPUT_BUFSIZ 2048 + #define CTRL(x) ((x) & 0x1f) #define MIN(a, b) ((a) > (b) ? (b) : (a)) #define MAX(a, b) ((a) > (b) ? (a) : (b)) struct nav { - int wmin, wmax, wlen; - int sel, min, max; + ssize_t wmin, wmax, wlen; + ssize_t sel, min, max; }; static int child_fd = -1; static pid_t child_pid = 0; +static char *loadbuf = NULL; + static char *output = NULL; static size_t output_len = 0; static size_t output_cap = 0; @@ -35,7 +40,7 @@ static size_t delims_cap = 0; static struct nav output_nav; -static char inputbuf[2048] = { 0 }; +static char *inputbuf = NULL; static size_t inputlen = 0; static bool splitargs = false; @@ -50,12 +55,10 @@ die(const char *fmt, ...) { va_list ap; - /* stdout because of swapped fds */ - - fputs("tquery: ", stdout); + fputs("tquery: ", stderr); va_start(ap, fmt); - vfprintf(stdout, fmt, ap); + vfprintf(stderr, fmt, ap); va_end(ap); if (fmt[0] && fmt[strlen(fmt)-1] == ':') { @@ -82,20 +85,6 @@ sigint(int sig) } static void -swapfd(int fd1, int fd2) -{ - int fd, rc; - - fd = dup(fd1); - if (fd < 0) die("dup:"); - rc = dup2(fd2, fd1); - if (rc == -1) die("dup2:"); - rc = dup2(fd, fd2); - if (rc == -1) die("dup2:"); - close(fd); -} - -static void nav_update_win(struct nav *nav) { nav->wmin = MAX(nav->wmax - nav->wlen, nav->min); @@ -123,14 +112,14 @@ nav_update_bounds(struct nav *nav, int min, int max) } static void -nav_update_wlen(struct nav *nav, int wlen) +nav_update_wlen(struct nav *nav, ssize_t wlen) { nav->wlen = wlen; nav_update_win(nav); } static void -nav_update_sel(struct nav *nav, int sel) +nav_update_sel(struct nav *nav, ssize_t sel) { nav->sel = MAX(MIN(sel, nav->max - 1), nav->min); if (nav->sel >= nav->wmax) { @@ -211,7 +200,6 @@ spawn(const char **prefix, const char *query) if (!child_pid) { close(0); if (childerr) { - swapfd(1, 2); close(1); } else { close(1); @@ -274,12 +262,11 @@ addcap(void *alloc, size_t dsize, size_t min, size_t *cap) static void load(void) { - char buf[BUFSIZ]; ssize_t nread; - size_t i, len; + size_t i; char *start; - nread = read(child_fd, buf, BUFSIZ); + nread = read(child_fd, loadbuf, LOAD_BUFSIZ); if (nread <= 0) { child_pid = 0; close(child_fd); @@ -288,12 +275,11 @@ load(void) } output = addcap(output, 1, output_len + (size_t) nread, &output_cap); - memcpy(output + output_len, buf, (size_t) nread); + memcpy(output + output_len, loadbuf, (size_t) nread); start = output + output_len; - output_len += (size_t) nread; - for (i = len; i < len + (size_t) nread; i++, start++) { + for (i = output_len; i < output_len + (size_t) nread; i++, start++) { if (*start == delim) { *start = '\0'; delims = addcap(delims, sizeof(size_t), @@ -301,6 +287,8 @@ load(void) delims[delims_len++] = i; } } + + output_len += (size_t) nread; } static char * @@ -321,13 +309,14 @@ update(void) width = getmaxx(stdscr); height = getmaxy(stdscr); - mvprintw(1, 1, "%lu %lu %i", output_len, delims_len, child_pid); + mvprintw(1, 1, "%lu %li %lu %i", output_len, + output_nav.sel, delims_len, child_pid); mvprintw(2, 1, "> %.*s", width - 1, inputbuf); - if (output_len) { - nav_update_bounds(&output_nav, 0, (int) delims_len); - nav_update_wlen(&output_nav, (int) (height - miny)); + nav_update_bounds(&output_nav, 0, (int) delims_len); + nav_update_wlen(&output_nav, (int) (height - miny)); + if (output_len) { i = output_nav.wmin; for (y = miny; y < height && i < output_nav.wmax; y++, i++) { if (i == output_nav.sel) @@ -397,8 +386,16 @@ input(void) clear(); dirty = true; break; + case CTRL('b'): + nav_update_sel(&output_nav, output_nav.min); + dirty = true; + break; + case CTRL('g'): + nav_update_sel(&output_nav, output_nav.max-1); + dirty = true; + break; case '\n': - if (output_nav.sel >= 0) { + if (output_nav.max > 0 && output_nav.sel >= 0) { fputs(entry((size_t) output_nav.sel), stderr); if (single) exit(0); } @@ -462,9 +459,8 @@ parse(int argc, const char **argv) } } - if (!child_argv || !*child_argv) { + if (!child_argv || !*child_argv) usage(0, false); - } if (*child_argv[0] != '/' && strncmp(child_argv[0], "./", 2)) { cmd_path = findbin(child_argv[0]); @@ -481,14 +477,13 @@ main(int argc, const char **argv) parse(argc, argv); - swapfd(1, 2); - nav_init(&output_nav); signal(SIGINT, sigint); atexit((void (*)()) endwin); - initscr(); + if (!newterm(NULL, stderr, stdin)) + die("newterm stdin -> stderr"); cbreak(); noecho(); keypad(stdscr, true); @@ -499,6 +494,12 @@ main(int argc, const char **argv) spawn(child_argv, ""); + inputbuf = malloc(INPUT_BUFSIZ); + if (!inputbuf) die("malloc inputbuf:"); + + loadbuf = malloc(LOAD_BUFSIZ); + if (!loadbuf) die("malloc loadbuf:"); + inputlen = 0; while (1) { maxfd = 0;