watch: my_getwc(): errors when char signed/unsigned, off-by-one in ungetc(), ...

Signed-off-by: Craig Small <csmall@dropbear.xyz>
This commit is contained in:
Roman Žilka 2023-06-22 15:45:25 +02:00 committed by Craig Small
parent 03aa5d371c
commit 67284cb719

View File

@ -446,34 +446,31 @@ static watch_usec_t get_time_usec()
#ifdef WITH_WATCH8BIT #ifdef WITH_WATCH8BIT
/* read a wide character from a popen'd stream */ /* read a wide character from a popen'd stream */
wint_t my_getwc(FILE * s) wint_t my_getwc(FILE *s)
{ {
char i[MB_CUR_MAX]; int c;
int byte = 0; unsigned char i[MB_CUR_MAX];
int convert; uint8_t byte = 0;
wchar_t rval; wchar_t rval;
while (1) { mbstate_t mbstate;
i[byte] = getc(s);
if (i[byte] == EOF) { memset(&mbstate, 0, sizeof(mbstate));
return WEOF;
} while ((c = getc(s)) != EOF) {
byte++; i[byte] = c;
errno = 0; if (mbrtowc(&rval, i+byte, 1, &mbstate) <= 1)
mbtowc(NULL, NULL, 0); /* legal conversion, may be L'\0' */
convert = mbtowc(&rval, i, byte);
if (convert > 0) {
/* legal conversion */
return rval; return rval;
} if (++byte == MB_CUR_MAX) {
if (byte == MB_CUR_MAX) { while (byte)
while (byte > 1) {
/* at least *try* to fix up */ /* at least *try* to fix up */
ungetc(i[--byte], s); ungetc(i[--byte], s);
} errno = EILSEQ;
errno = -EILSEQ; break;
return WEOF;
} }
} }
return WEOF;
} }
#endif /* WITH_WATCH8BIT */ #endif /* WITH_WATCH8BIT */
@ -814,6 +811,7 @@ int main(int argc, char *argv[])
char *command; char *command;
char **command_argv; char **command_argv;
int command_length = 0; /* not including final \0 */ int command_length = 0; /* not including final \0 */
int command_exit;
watch_usec_t last_run = 0; watch_usec_t last_run = 0;
watch_usec_t next_loop = 0; /* next loop time in us, used for precise time watch_usec_t next_loop = 0; /* next loop time in us, used for precise time
* keeping only */ * keeping only */
@ -838,7 +836,7 @@ int main(int argc, char *argv[])
{"equexit", required_argument, 0, 'q'}, {"equexit", required_argument, 0, 'q'},
{"exec", no_argument, 0, 'x'}, {"exec", no_argument, 0, 'x'},
{"precise", no_argument, 0, 'p'}, {"precise", no_argument, 0, 'p'},
{"no-rerun", no_argument, 0, 'r'}, {"no-rerun", no_argument, 0, 'r'},
{"no-title", no_argument, 0, 't'}, {"no-title", no_argument, 0, 't'},
{"no-wrap", no_argument, 0, 'w'}, {"no-wrap", no_argument, 0, 'w'},
{"version", no_argument, 0, 'v'}, {"version", no_argument, 0, 'v'},
@ -885,9 +883,9 @@ int main(int argc, char *argv[])
flags |= WATCH_EQUEXIT; flags |= WATCH_EQUEXIT;
max_cycles = strtod_nol_or_err(optarg, _("failed to parse argument")); max_cycles = strtod_nol_or_err(optarg, _("failed to parse argument"));
break; break;
case 'r': case 'r':
flags |= WATCH_NORERUN; flags |= WATCH_NORERUN;
break; break;
case 't': case 't':
show_title = 0; show_title = 0;
break; break;
@ -1003,25 +1001,23 @@ int main(int argc, char *argv[])
output_header(command, interval); output_header(command, interval);
#endif /* WITH_WATCH8BIT */ #endif /* WITH_WATCH8BIT */
if (!(flags & WATCH_NORERUN) || if (!(flags & WATCH_NORERUN) ||
get_time_usec() - last_run > interval * USECS_PER_SEC) { get_time_usec() - last_run > interval * USECS_PER_SEC) {
last_run = get_time_usec(); last_run = get_time_usec();
int exit = run_command(command, command_argv); command_exit = run_command(command, command_argv);
if (flags & WATCH_EQUEXIT) { if (flags & WATCH_EQUEXIT) {
if (cycle_count == max_cycles && exit) { if (cycle_count == max_cycles && command_exit)
break; break;
} else if (exit) { else if (command_exit)
cycle_count++; cycle_count++;
} else { else
cycle_count = 0; cycle_count = 0;
} }
} else if (exit) { } else if (command_exit)
break; break;
} else
} else { refresh();
refresh();
}
if (precise_timekeeping) { if (precise_timekeeping) {
watch_usec_t cur_time = get_time_usec(); watch_usec_t cur_time = get_time_usec();