X-Git-Url: https://git.danieliu.xyz/?a=blobdiff_plain;f=st.c;h=2ecf8f3b93135169172ee76141514de61a303f1e;hb=fbae700a3f32db76106b0ff6f49a73ecf0c2b4fe;hp=a8f8232e3539f31cc39e599ebabd2f144058e6c1;hpb=ea4d933ed9d8ce16699c84892a29e070c70b2eb9;p=st.git diff --git a/st.c b/st.c index a8f8232..2ecf8f3 100644 --- a/st.c +++ b/st.c @@ -135,7 +135,7 @@ typedef struct { /* ESC '[' [[ [] [;]] []] */ typedef struct { char buf[ESC_BUF_SIZ]; /* raw string */ - int len; /* raw string length */ + size_t len; /* raw string length */ char priv; int arg[ESC_ARG_SIZ]; int narg; /* nb of args */ @@ -146,8 +146,9 @@ typedef struct { /* ESC type [[ [] [;]] ] ESC '\' */ typedef struct { char type; /* ESC type ... */ - char buf[STR_BUF_SIZ]; /* raw string */ - int len; /* raw string length */ + char *buf; /* allocated raw string */ + size_t siz; /* allocation size */ + size_t len; /* raw string length */ char *args[STR_ARG_SIZ]; int narg; /* nb of args */ } STREscape; @@ -365,7 +366,8 @@ static const char base64_digits[] = { char base64dec_getc(const char **src) { - while (**src && !isprint(**src)) (*src)++; + while (**src && !isprint(**src)) + (*src)++; return **src ? *((*src)++) : '='; /* emulate padding if string ends */ } @@ -663,7 +665,7 @@ die(const char *errstr, ...) void execsh(char *cmd, char **args) { - char *sh, *prog; + char *sh, *prog, *arg; const struct passwd *pw; errno = 0; @@ -677,13 +679,17 @@ execsh(char *cmd, char **args) if ((sh = getenv("SHELL")) == NULL) sh = (pw->pw_shell[0]) ? pw->pw_shell : cmd; - if (args) + if (args) { prog = args[0]; - else if (utmp) - prog = utmp; - else + arg = NULL; + } else if (scroll || utmp) { + prog = scroll ? scroll : utmp; + arg = scroll ? utmp : NULL; + } else { prog = sh; - DEFAULT(args, ((char *[]) {prog, NULL})); + arg = NULL; + } + DEFAULT(args, ((char *[]) {prog, arg, NULL})); unsetenv("COLUMNS"); unsetenv("LINES"); @@ -818,17 +824,24 @@ ttyread(void) int ret; /* append read bytes to unprocessed bytes */ - if ((ret = read(cmdfd, buf+buflen, LEN(buf)-buflen)) < 0) - die("couldn't read from shell: %s\n", strerror(errno)); - buflen += ret; + ret = read(cmdfd, buf+buflen, LEN(buf)-buflen); - written = twrite(buf, buflen, 0); - buflen -= written; - /* keep any uncomplete utf8 char for the next call */ - if (buflen > 0) - memmove(buf, buf + written, buflen); + switch (ret) { + case 0: + fputs("Found EOF in input\n", stderr); + exit(0); + case -1: + die("couldn't read from shell: %s\n", strerror(errno)); + default: + buflen += ret; + written = twrite(buf, buflen, 0); + buflen -= written; + /* keep any uncomplete utf8 char for the next call */ + if (buflen > 0) + memmove(buf, buf + written, buflen); + return ret; - return ret; + } } void @@ -1803,7 +1816,7 @@ csihandle(void) void csidump(void) { - int i; + size_t i; uint c; fprintf(stderr, "ESC["); @@ -1921,7 +1934,7 @@ strparse(void) void strdump(void) { - int i; + size_t i; uint c; fprintf(stderr, "ESC%c", strescseq.type); @@ -1948,7 +1961,10 @@ strdump(void) void strreset(void) { - memset(&strescseq, 0, sizeof(strescseq)); + strescseq = (STREscape){ + .buf = xrealloc(strescseq.buf, STR_BUF_SIZ), + .siz = STR_BUF_SIZ, + }; } void @@ -2330,7 +2346,7 @@ tputc(Rune u) if (term.esc&ESC_DCS && strescseq.len == 0 && u == 'q') term.mode |= MODE_SIXEL; - if (strescseq.len+len >= sizeof(strescseq.buf)-1) { + if (strescseq.len+len >= strescseq.siz) { /* * Here is a bug in terminals. If the user never sends * some code to stop the str or esc command, then st @@ -2344,7 +2360,10 @@ tputc(Rune u) * term.esc = 0; * strhandle(); */ - return; + if (strescseq.siz > (SIZE_MAX - UTF_SIZ) / 2) + return; + strescseq.siz *= 2; + strescseq.buf = xrealloc(strescseq.buf, strescseq.siz); } memmove(&strescseq.buf[strescseq.len], c, len);