sacc

sacc(omys), simple console gopher client (mirror)
git clone https://git.parazyd.org/sacc
Log | Files | Refs | LICENSE

commit 2e31e44ffa614c5202edfe2abcc05a7880902640
parent d90036de3c72730ae2797844b36eb5ae9fd3843f
Author: Quentin Rameau <quinq@fifth.space>
Date:   Fri, 29 Dec 2017 10:52:39 +0100

Truncate output to the terminal size

Thanks to Hiltjo for his input, making this patch a little better.

Diffstat:
Mui_ti.c | 71+++++++++++++++++++++++++++++++++++++++++++++++++----------------------
Mui_txt.c | 58+++++++++++++++++++++++++++++++++++++++++++---------------
2 files changed, 92 insertions(+), 37 deletions(-)

diff --git a/ui_ti.c b/ui_ti.c @@ -13,6 +13,7 @@ #define C(c) #c #define S(c) C(c) +static char bufout[256]; static struct termios tsave; static struct termios tsacc; #if defined(__NetBSD__) @@ -50,8 +51,8 @@ uiprompt(char *fmt, ...) { va_list ap; char *input = NULL; - size_t n = 0; - ssize_t r = 0; + size_t n; + ssize_t r; putp(tparm(save_cursor)); @@ -60,19 +61,23 @@ uiprompt(char *fmt, ...) putp(tparm(enter_standout_mode)); va_start(ap, fmt); - r += vprintf(fmt, ap); + if (vsnprintf(bufout, sizeof(bufout), fmt, ap) >= sizeof(bufout)) + bufout[sizeof(bufout)-1] = '\0'; va_end(ap); + printf("%.*s", columns, bufout); putp(tparm(exit_standout_mode)); - printf("%*s", columns-r, " "); + if ((n = strlen(bufout)) < columns) + printf("%*s", columns - n, " "); - putp(tparm(cursor_address, lines-1, r)); + putp(tparm(cursor_address, lines-1, n)); tsacc.c_lflag |= (ECHO|ICANON); tcsetattr(0, TCSANOW, &tsacc); fflush(stdout); + n = 0; r = getline(&input, &n, stdin); tsacc.c_lflag &= ~(ECHO|ICANON); @@ -93,7 +98,10 @@ uiprompt(char *fmt, ...) static void printitem(Item *item) { - printf("%s %s\r", typedisplay(item->type), item->username); + if (snprintf(bufout, sizeof(bufout), "%s %s", typedisplay(item->type), + item->username) >= sizeof(bufout)) + bufout[sizeof(bufout)-1] = '\0'; + printf("%.*s\r", columns, bufout); } static Item * @@ -127,7 +135,7 @@ void uistatus(char *fmt, ...) { va_list ap; - int n = 0; + size_t n; putp(tparm(save_cursor)); @@ -135,12 +143,20 @@ uistatus(char *fmt, ...) putp(tparm(enter_standout_mode)); va_start(ap, fmt); - n += vprintf(fmt, ap); + n = vsnprintf(bufout + n, sizeof(bufout) - n, fmt, ap); va_end(ap); - n += printf(" [Press a key to continue ☃]"); + if (n < sizeof(bufout)-1) { + n += snprintf(bufout + n, sizeof(bufout) - n, + " [Press a key to continue ☃]"); + } + if (n >= sizeof(bufout)) + bufout[sizeof(bufout)-1] = '\0'; + + printf("%.*s", columns, bufout); putp(tparm(exit_standout_mode)); - printf("%*s", columns-n, " "); + if ((n = strlen(bufout)) < columns) + printf("%*s", columns - n, " "); putp(tparm(restore_cursor)); fflush(stdout); @@ -153,9 +169,8 @@ displaystatus(Item *item) { Dir *dir = item->dat; char *fmt; - size_t nitems = dir ? dir->nitems : 0; + size_t n, nitems = dir ? dir->nitems : 0; unsigned long long printoff = dir ? dir->printoff : 0; - int n; putp(tparm(save_cursor)); @@ -163,12 +178,16 @@ displaystatus(Item *item) putp(tparm(enter_standout_mode)); fmt = (strcmp(item->port, "70") && strcmp(item->port, "gopher")) ? "%1$3lld%%| %2$s:%5$s/%3$c%4$s" : "%3lld%%| %s/%c%s"; - n = printf(fmt, - (printoff + lines-1 >= nitems) ? 100 : - (printoff + lines-1) * 100 / nitems, - item->host, item->type, item->selector, item->port); + if (snprintf(bufout, sizeof(bufout), fmt, + (printoff + lines-1 >= nitems) ? 100 : + (printoff + lines-1) * 100 / nitems, + item->host, item->type, item->selector, item->port) + >= sizeof(bufout)) + bufout[sizeof(bufout)-1] = '\0'; + printf("%.*s", columns, bufout); putp(tparm(exit_standout_mode)); - printf("%*s", columns-n, " "); + if ((n = strlen(bufout)) < columns) + printf("%*s", columns - n, " "); putp(tparm(restore_cursor)); fflush(stdout); @@ -178,7 +197,7 @@ static void displayuri(Item *item) { char *fmt; - int n; + size_t n; if (item->type == 0 || item->type == 'i') return; @@ -189,18 +208,26 @@ displayuri(Item *item) putp(tparm(enter_standout_mode)); switch (item->type) { case 'h': - n = printf("%s: %s", item->username, item->selector); + n = snprintf(bufout, sizeof(bufout), "%s: %s", + item->username, item->selector); break; default: fmt = strcmp(item->port, "70") ? "%1$s: gopher://%2$s:%5$s/%3$c%4$s" : "%s: gopher://%s/%c%s"; - n = printf(fmt, item->username, - item->host, item->type, item->selector, item->port); + n = snprintf(bufout, sizeof(bufout), fmt, + item->username, item->host, item->type, + item->selector, item->port); break; } + + if (n >= sizeof(bufout)) + bufout[sizeof(bufout)-1] = '\0'; + + printf("%.*s", columns, bufout); putp(tparm(exit_standout_mode)); - printf("%*s", columns-n, " "); + if ((n = strlen(bufout)) < columns) + printf("%*s", columns - n, " "); putp(tparm(restore_cursor)); fflush(stdout); diff --git a/ui_txt.c b/ui_txt.c @@ -10,6 +10,7 @@ #include "common.h" +static char bufout[256]; int lines, columns; static void @@ -67,12 +68,20 @@ void uistatus(char *fmt, ...) { va_list arg; + int n; va_start(arg, fmt); - vprintf(fmt, arg); + n = vsnprintf(bufout, sizeof(bufout), fmt, arg); va_end(arg); - printf(" [Press Enter to continue ☃]"); + if (n < sizeof(bufout)-1) { + n += snprintf(bufout + n, sizeof(bufout) - n, + " [Press Enter to continue ☃]"); + } + if (n >= sizeof(bufout)) + bufout[sizeof(bufout)-1] = '\0'; + + printf("%.*s", columns, bufout); fflush(stdout); getchar(); @@ -89,9 +98,13 @@ printstatus(Item *item, char c) fmt = (strcmp(item->port, "70") && strcmp(item->port, "gopher")) ? "%1$3lld%%%*2$3$c %4$s:%8$s/%5$c%6$s [%7$c]: " : "%3lld%%%*c %s/%c%s [%c]: "; - printf(fmt, (printoff + lines-1 >= nitems) ? 100 : - (printoff + lines) * 100 / nitems, ndigits(nitems)+2, '|', - item->host, item->type, item->selector, c, item->port); + if (snprintf(bufout, sizeof(bufout), fmt, + (printoff + lines-1 >= nitems) ? 100 : + (printoff + lines) * 100 / nitems, ndigits(nitems)+2, '|', + item->host, item->type, item->selector, c, item->port) + >= sizeof(bufout)) + bufout[sizeof(bufout)-1] = '\0'; + printf("%.*s", columns, bufout); } char * @@ -103,9 +116,12 @@ uiprompt(char *fmt, ...) ssize_t r; va_start(ap, fmt); - vprintf(fmt, ap); + if (vsnprintf(bufout, sizeof(bufout), fmt, ap) >= sizeof(bufout)) + bufout[sizeof(bufout)-1] = '\0'; va_end(ap); + printf("%.*s", columns, bufout); + fflush(stdout); if ((r = getline(&input, &n, stdin)) < 0) { @@ -138,8 +154,12 @@ uidisplay(Item *entry) nd = ndigits(nitems); for (i = dir->printoff; i < nitems && i < nlines; ++i) { - printf("%*zu %s %s\n", - nd, i+1, typedisplay(items[i].type), items[i].username); + if (snprintf(bufout, sizeof(bufout), "%*zu %s %s", + nd, i+1, typedisplay(items[i].type), + items[i].username) + >= sizeof(bufout)) + bufout[sizeof(bufout)-1] = '\0'; + printf("%.*s\n", columns, bufout); } fflush(stdout); @@ -149,27 +169,35 @@ void printuri(Item *item, size_t i) { char *fmt; + int n; if (!item) return; switch (item->type) { case 0: - break; + return; case 'i': - printf("%zu: %s\n", i, item->username); + n = snprintf(bufout, sizeof(bufout), "%zu: %s", + i, item->username); break; case 'h': - printf("%zu: %s: %s\n", i, item->username, item->selector); + n = snprintf(bufout, sizeof(bufout), "%zu: %s: %s", + i, item->username, item->selector); break; default: fmt = strcmp(item->port, "70") ? - "%1$zu: %2$s: gopher://%3$s:%6$s/%4$c%5$s\n" : - "%zu: %s: gopher://%s/%c%s\n"; - printf(fmt, i, item->username, - item->host, item->type, item->selector, item->port); + "%1$zu: %2$s: gopher://%3$s:%6$s/%4$c%5$s" : + "%zu: %s: gopher://%s/%c%s"; + n = snprintf(bufout, sizeof(bufout), fmt, i, item->username, + item->host, item->type, item->selector, item->port); break; } + + if (n >= sizeof(bufout)) + bufout[sizeof(bufout)-1] = '\0'; + + printf("%.*s\n", columns, bufout); } void