fixed buffer errors (reading, empty) - iomenu - interactive terminal-based selection menu
(HTM) git clone git://bitreich.org/iomenu git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/iomenu
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) Tags
(DIR) README
(DIR) LICENSE
---
(DIR) commit 9bdaa10a695ec2d8a9890c980bd5b44d5ff6f48c
(DIR) parent 8be3cf653dc554954a4170bd057a33cf2e8a0244
(HTM) Author: Josuah Demangeonā ā µ <mail@josuah.net>
Date: Sat, 18 Mar 2017 10:06:42 +0100
fixed buffer errors (reading, empty)
Diffstat:
M iomenu.c | 108 ++++++++++++++-----------------
1 file changed, 48 insertions(+), 60 deletions(-)
---
(DIR) diff --git a/iomenu.c b/iomenu.c
@@ -18,8 +18,8 @@
struct line {
- char *text; /* sent as output and matched by input */
- int match; /* whether it matches linev's input */
+ char text[BUFSIZ];
+ int match;
};
@@ -33,10 +33,8 @@ char *opt_prompt = "";
void
free_linev(struct line **linev)
{
- for (; linec > 0; linec--) {
- free(linev[linec - 1]->text);
+ for (; linec > 0; linec--)
free(linev[linec - 1]);
- }
free(linev);
}
@@ -75,19 +73,19 @@ read_lines(void)
extern struct line **linev;
extern size_t linec, matching;
- char s[BUFSIZ];
- size_t size = 1 << 4;
+ char buffer[BUFSIZ];
+ size_t size = 1 << 6;
if (!(linev = malloc(sizeof(struct line *) * size)))
die("malloc");
linev[0] = NULL;
/* read the file into an array of lines */
- for (; fgets(s, BUFSIZ, stdin); linec++, matching++) {
- size_t len = strlen(s);
+ for (; fgets(buffer, sizeof buffer, stdin); linec++, matching++) {
+ size_t len = strlen(buffer);
- if (len > 0 && s[len - 1] == '\n')
- s[len - 1] = '\0';
+ if (len > 0 && buffer[len - 1] == '\n')
+ buffer[len - 1] = '\0';
if (linec > size) {
size *= 2;
@@ -99,17 +97,15 @@ read_lines(void)
if (!(linev[linec] = malloc(sizeof(struct line))))
die("malloc");
- if (!(linev[linec]->text = malloc(len)))
- die("malloc");
- strcpy(linev[linec]->text, s);
+ strcpy(linev[linec]->text, buffer);
linev[linec]->match = 1;
}
}
int
-line_matches(struct line *line, char **tokv, size_t tokc)
+match_line(struct line *line, char **tokv, size_t tokc)
{
for (size_t i = 0; i < tokc; i++)
if (strstr(line->text, tokv[i]) == NULL)
@@ -119,20 +115,16 @@ line_matches(struct line *line, char **tokv, size_t tokc)
}
-/*
- * If inc is 1, it will only check already matching lines.
- * If inc is 0, it will only check non-matching lines.
- */
void
-filter_lines(int inc)
+filter_lines(void)
{
char **tokv = NULL;
- char *s, buf[sizeof(input)];
+ char *s, buffer[sizeof(input)];
size_t n = 0, tokc = 0;
/* tokenize input from space characters, this comes from dmenu */
- strcpy(buf, input);
- for (s = strtok(buf, " "); s; s = strtok(NULL, " "), tokc++) {
+ strcpy(buffer, input);
+ for (s = strtok(buffer, " "); s; s = strtok(NULL, " "), tokc++) {
if (tokc >= n) {
tokv = realloc(tokv, ++n * sizeof(*tokv));
@@ -144,12 +136,8 @@ filter_lines(int inc)
tokv[tokc] = s;
}
- /* match lines */
- matching = 0;
- for (size_t i = 0; i < linec; i++)
- /* if (!(inc ^ linev[i]->match)) */
- matching += linev[i]->match =
- line_matches(linev[i], tokv, tokc);
+ for (size_t i = 0, matching = 0; i < linec; i++)
+ matching += linev[i]->match = match_line(linev[i], tokv, tokc);
}
@@ -175,7 +163,7 @@ matching_next(size_t pos)
void
-draw_line(size_t pos, const size_t cols)
+print_line(size_t pos, const size_t cols)
{
fprintf(stderr, pos == current ?
"\n\033[30;47m\033[K%s\033[m" : "\n\033[K%s",
@@ -185,13 +173,13 @@ draw_line(size_t pos, const size_t cols)
void
-draw_lines(size_t count, size_t cols)
+print_lines(size_t count, size_t cols)
{
size_t printed = 0;
for (size_t i = offset; printed < count && i < linec; i++) {
if (linev[i]->match) {
- draw_line(i, cols);
+ print_line(i, cols);
printed++;
}
}
@@ -202,7 +190,7 @@ draw_lines(size_t count, size_t cols)
int
-draw_column(size_t pos, size_t col, size_t cols)
+print_column(size_t pos, size_t col, size_t cols)
{
fputs(pos == current ? "\033[30;47m " : " ", stderr);
@@ -229,17 +217,17 @@ draw_column(size_t pos, size_t col, size_t cols)
void
-draw_columns(size_t cols)
+print_columns(size_t cols)
{
size_t col = 20;
for (size_t i = offset; col < cols; i++)
- col = draw_column(i, col, cols);
+ col = print_column(i, col, cols);
}
void
-draw_prompt(size_t cols)
+print_prompt(size_t cols)
{
size_t limit = opt_lines ? cols : 20;
@@ -252,7 +240,7 @@ draw_prompt(size_t cols)
void
-draw_screen(int tty_fd)
+print_screen(int tty_fd)
{
struct winsize w;
size_t count;
@@ -263,18 +251,18 @@ draw_screen(int tty_fd)
count = MIN(opt_lines, w.ws_row - 2);
if (opt_lines) {
- draw_lines(count, w.ws_col);
+ print_lines(count, w.ws_col);
fprintf(stderr, "\033[%ldA", count);
} else {
- draw_columns(w.ws_col);
+ print_columns(w.ws_col);
}
- draw_prompt(w.ws_col);
+ print_prompt(w.ws_col);
}
void
-draw_clear(size_t lines)
+print_clear(size_t lines)
{
for (size_t i = 0; i < lines + 1; i++)
fputs("\r\033[K\n", stderr);
@@ -306,9 +294,9 @@ add_character(char key)
input[len + 1] = '\0';
}
- filter_lines(1);
+ filter_lines();
- current = linev[0]->match ? 0 : matching_next(0);
+ current = linec == 0 || linev[0]->match ? 0 : matching_next(0);
}
@@ -316,15 +304,14 @@ add_character(char key)
* Send the selection to stdout.
*/
void
-print_selection(int return_input)
+print_selection(void)
{
fputs("\r\033[K", stderr);
- if (return_input || !matching) {
- puts(input);
-
- } else if (matching > 0) {
+ if (matching > 0) {
puts(linev[current]->text);
+ } else {
+ puts(input);
}
}
@@ -340,32 +327,32 @@ input_key(FILE *tty_fp)
char key = fgetc(tty_fp);
if (key == '\n') {
- print_selection(0);
+ print_selection();
return EXIT_SUCCESS;
}
switch (key) {
case CONTROL('C'):
- draw_clear(opt_lines);
+ print_clear(opt_lines);
return EXIT_FAILURE;
case CONTROL('U'):
input[0] = '\0';
current = 0;
- filter_lines(0);
+ filter_lines();
break;
case CONTROL('W'):
remove_word_input();
- filter_lines(0);
+ filter_lines();
break;
case 127:
case CONTROL('H'): /* backspace */
input[strlen(input) - 1] = '\0';
- filter_lines(0);
- current = linev[0]->match ? 0 : matching_next(0);
+ filter_lines();
+ current = linec == 0 || linev[0]->match ? 0 : matching_next(0);
break;
case CONTROL('N'):
@@ -377,13 +364,14 @@ input_key(FILE *tty_fp)
break;
case CONTROL('I'): /* tab */
- strcpy(input, linev[current]->text);
- filter_lines(1);
+ if (linec > 0)
+ strcpy(input, linev[current]->text);
+ filter_lines();
break;
case CONTROL('J'):
case CONTROL('M'): /* enter */
- print_selection(0);
+ print_selection();
return EXIT_SUCCESS;
default:
@@ -407,7 +395,7 @@ input_get(int tty_fd)
input[0] = '\0';
while ((exit_code = input_key(tty_fp)) == CONTINUE)
- draw_screen(tty_fd);
+ print_screen(tty_fd);
/* resets the terminal to the previous state. */
tcsetattr(tty_fd, TCSANOW, &termio_old);
@@ -456,12 +444,12 @@ main(int argc, char *argv[])
read_lines();
/* set the interface */
- draw_screen(tty_fd);
+ print_screen(tty_fd);
/* listen and interact to input */
exit_code = input_get(tty_fd);
- draw_clear(opt_lines);
+ print_clear(opt_lines);
/* close files descriptors and pointers, and free memory */
close(tty_fd);