diff --git a/NEWS b/NEWS index 6e67b3c8..4a89b482 100644 --- a/NEWS +++ b/NEWS @@ -3,7 +3,9 @@ procps-3.2.3 --> procps-3.2.4 support 64-bit MIPS with n32 binary sparc32 optimized for sparc32 again pwdx: new command -- thanks Nicholas Miell +ps: UTF-8 username + command -- thanks Karel Zak rh134763,rh112518,rh134780 ps: more room for some columns +ps: tolerate SubDomain security module CONTEXT/LABEL data #277401 watch: passes COLUMNS and LINES in environment top: in batch mode, tolerate unknown $TERM -- thanks Daniel Walsh pkill: quiet about processes that die before kill() diff --git a/pmap.c b/pmap.c index bbf278d8..a5ade691 100644 --- a/pmap.c +++ b/pmap.c @@ -113,11 +113,6 @@ static const char *mapping_name(proc_t *p, unsigned KLONG addr, unsigned KLONG l return cp; } - -// Overkill, but who knows what is proper? The "w" prog -// uses the tty width to determine this. -#define maxcmd 0xfffff - static int one_proc(proc_t *p){ char buf[32]; char mapbuf[9600]; @@ -126,10 +121,14 @@ static int one_proc(proc_t *p){ unsigned long total_private_readonly = 0ul; unsigned long total_private_writeable = 0ul; + // Overkill, but who knows what is proper? The "w" prog + // uses the tty width to determine this. + int maxcmd = 0xfffff; + sprintf(buf,"/proc/%u/maps",p->tgid); if(!freopen(buf, "r", stdin)) return 1; - escape_command(cmdbuf, p, sizeof cmdbuf, maxcmd, ESC_ARGS|ESC_BRACKETS); + escape_command(cmdbuf, p, sizeof cmdbuf, &maxcmd, ESC_ARGS|ESC_BRACKETS); printf("%u: %s\n", p->tgid, cmdbuf); if(!q_option && (x_option|d_option)){ diff --git a/proc/escape.c b/proc/escape.c index 83aee9db..d93d8d8c 100644 --- a/proc/escape.c +++ b/proc/escape.c @@ -8,77 +8,110 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details. */ +#include #include #include #include "procps.h" #include "escape.h" #include "readproc.h" -// What it would be for a UTF-8 locale: -// "Z-------------------------------" -// "********************************" -// "********************************" -// "*******************************-" -// "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" Trailing UTF-8, and badness in 8-bit. -// "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy" Trailing UTF-8, and safe in 8-bit. -// "--222222222222222222222222222222" -// ".333333333333.3.44444444555566--" The '.' means '3', with problem chars. -// -// Problems include non-shortest forms, UTF-16, and non-characters. -// The 4-byte, 5-byte, and 6-byte sequences are full of trouble too. - -#if 0 -/* sanitize a string, without the nice BSD library function: */ -/* strvis(vis_args, k->ki_args, VIS_TAB | VIS_NL | VIS_NOSLASH) */ -int octal_escape_str(char *restrict dst, const char *restrict src, size_t n){ - unsigned char c; - char d; - size_t i; - const char codes[] = - "Z------abtnvfr-------------e----" - " *******************************" /* better: do not print any space */ - "****************************\\***" - "*******************************-" - "--------------------------------" - "********************************" - "********************************" - "********************************"; - for(i=0; i n) goto leave; - i += 4; - *(dst++) = '\\'; - *(dst++) = "01234567"[c>>6]; - *(dst++) = "01234567"[(c>>3)&07]; - *(dst++) = "01234567"[c&07]; - break; - default: - if(i+2 > n) goto leave; - i += 2; - *(dst++) = '\\'; - *(dst++) = d; - break; - } - } -leave: - *(dst++) = '\0'; - return i; -} +#if (__GNU_LIBRARY__ >= 6) +# include +# include +# include /* MB_CUR_MAX */ +# include +# include #endif +#if (__GNU_LIBRARY__ >= 6) +static int escape_str_utf8(char *restrict dst, const char *restrict src, int bufsize, int *maxcells){ + int my_cells = 0; + int my_bytes = 0; + mbstate_t s; + + memset(&s, 0, sizeof (s)); + + for(;;) { + wchar_t wc; + int len = 0; + + if(my_cells >= *maxcells || my_bytes+1 >= bufsize) + break; + + if (!(len = mbrtowc (&wc, src, MB_CUR_MAX, &s))) + /* 'str' contains \0 */ + break; + + if (len < 0) { + /* invalid multibyte sequence -- zeroize state */ + memset (&s, 0, sizeof (s)); + *(dst++) = '?'; + src++; + my_cells++; + my_bytes++; + + } else if (len==1) { + /* non-multibyte */ + *(dst++) = isprint(*src) ? *src : '?'; + src++; + my_cells++; + my_bytes++; + + } else if (!iswprint(wc)) { + /* multibyte - no printable */ + *(dst++) = '?'; + src+=len; + my_cells++; + my_bytes++; + + } else { + /* multibyte - printable */ + int wlen = wcwidth(wc); + + if (wlen==0) { + // invisible multibyte -- we don't ignore it, because some terminal + // interpret it wrong and more safe is replace it with '?' + *(dst++) = '?'; + src+=len; + my_cells++; + my_bytes++; + } else { + // multibyte - printable + // Got space? + if (my_cells+wlen > *maxcells || my_bytes+1+len >= bufsize) break; + // 0x9b is control byte for some terminals + if (memchr(src, 0x9B, len)) { + // unsafe multibyte + *(dst++) = '?'; + src+=len; + my_cells++; + my_bytes++; + } else { + // safe multibyte + memcpy(dst, src, len); + my_cells += wlen; + dst += len; + my_bytes += len; + src += len; + } + } + } + //fprintf(stdout, "cells: %d\n", my_cells); + } + *(dst++) = '\0'; + + // fprintf(stderr, "maxcells: %d, my_cells; %d\n", *maxcells, my_cells); + + *maxcells -= my_cells; + return my_bytes; // bytes of text, excluding the NUL +} + +#endif /* __GNU_LIBRARY__ */ + /* sanitize a string via one-way mangle */ -int escape_str(char *restrict dst, const char *restrict src, int bufsize, int maxglyphs){ +int escape_str(char *restrict dst, const char *restrict src, int bufsize, int *maxcells){ unsigned char c; - int my_glyphs = 0; + int my_cells = 0; int my_bytes = 0; const char codes[] = "Z-------------------------------" @@ -89,20 +122,35 @@ int escape_str(char *restrict dst, const char *restrict src, int bufsize, int ma "********************************" "********************************" "********************************"; - - if(bufsize > maxglyphs+1) bufsize=maxglyphs+1; // FIXME: assumes 8-bit locale + +#if (__GNU_LIBRARY__ >= 6) + static int utf_init=0; + + if(utf_init==0){ + /* first call -- check if UTF stuff is usable */ + char *enc = nl_langinfo(CODESET); + utf_init = enc && strcasecmp(enc, "UTF-8")==0 ? 1 : -1; + } + if (utf_init==1) + /* UTF8 locales */ + return escape_str_utf8(dst, src, bufsize, maxcells); +#endif + + if(bufsize > *maxcells+1) bufsize=*maxcells+1; // FIXME: assumes 8-bit locale for(;;){ - if(my_glyphs >= maxglyphs) break; - if(my_bytes+1 >= bufsize) break; + if(my_cells >= *maxcells || my_bytes+1 >= bufsize) + break; c = (unsigned char) *(src++); if(!c) break; if(codes[c]=='-') c='?'; - my_glyphs++; + my_cells++; my_bytes++; *(dst++) = c; } *(dst++) = '\0'; + + *maxcells -= my_cells; return my_bytes; // bytes of text, excluding the NUL } @@ -111,34 +159,30 @@ int escape_str(char *restrict dst, const char *restrict src, int bufsize, int ma // escape an argv or environment string array // // bytes arg means sizeof(buf) -int escape_strlist(char *restrict dst, const char *restrict const *restrict src, size_t bytes){ +int escape_strlist(char *restrict dst, const char *restrict const *restrict src, size_t bytes, size_t *cells){ size_t i = 0; -//if(!*src){ just never call this function without checking first -// do something nice -//} - for(;;){ - i += escape_str(dst+i, *src, bytes-i, bytes-i); // FIXME: byte/glyph + i += escape_str(dst+i, *src, bytes-i, cells); if(bytes-i < 3) break; // need room for space, a character, and the NUL src++; if(!*src) break; // need something to print + if (*cells<=1) break; // need room for printed size of text dst[i++] = ' '; + --*cells; } - return i; // bytes of text, excluding the NUL + return i; // bytes, excluding the NUL } /////////////////////////////////////////////////// -int escape_command(char *restrict const outbuf, const proc_t *restrict const pp, int bytes, int glyphs, unsigned flags){ +int escape_command(char *restrict const outbuf, const proc_t *restrict const pp, int bytes, int *cells, unsigned flags){ int overhead = 0; int end = 0; - if(bytes > glyphs+1) bytes=glyphs+1; // FIXME: assumes 8-bit locale - if(flags & ESC_ARGS){ const char **lc = (const char**)pp->cmdline; - if(lc && *lc) return escape_strlist(outbuf, lc, bytes); + if(lc && *lc) return escape_strlist(outbuf, lc, bytes, cells); } if(flags & ESC_BRACKETS){ overhead += 2; @@ -147,16 +191,17 @@ int escape_command(char *restrict const outbuf, const proc_t *restrict const pp, if(pp->state=='Z') overhead += 10; // chars in " " else flags &= ~ESC_DEFUNCT; } - if(overhead + 1 >= bytes){ // if no room for even one byte of the command name + if(overhead + 1 >= *cells){ // if no room for even one byte of the command name // you'd damn well better have _some_ space - outbuf[0] = '-'; +// outbuf[0] = '-'; // Oct23 outbuf[1] = '\0'; return 1; } if(flags & ESC_BRACKETS){ outbuf[end++] = '['; } - end += escape_str(outbuf+end, pp->cmd, bytes-overhead, glyphs-overhead); + *cells -= overhead; + end += escape_str(outbuf+end, pp->cmd, bytes-overhead, cells); // Hmmm, do we want "[foo] " or "[foo ]"? if(flags & ESC_BRACKETS){ @@ -166,7 +211,6 @@ int escape_command(char *restrict const outbuf, const proc_t *restrict const pp, memcpy(outbuf+end, " ", 10); end += 10; } - outbuf[end] = '\0'; - return end; // bytes or glyphs, not including the NUL + return end; // bytes, not including the NUL } diff --git a/proc/escape.h b/proc/escape.h index 04cfbed2..34cf3296 100644 --- a/proc/escape.h +++ b/proc/escape.h @@ -12,9 +12,9 @@ EXTERN_C_BEGIN #define ESC_BRACKETS 0x2 // if using cmd, put '[' and ']' around it #define ESC_DEFUNCT 0x4 // mark zombies with " " -extern int escape_strlist(char *restrict dst, const char *restrict const *restrict src, size_t n); -extern int escape_str(char *restrict dst, const char *restrict src, int bufsize, int maxglyphs); -extern int escape_command(char *restrict const outbuf, const proc_t *restrict const pp, int bytes, int glyphs, unsigned flags); +extern int escape_strlist(char *restrict dst, const char *restrict const *restrict src, size_t n, size_t *cells); +extern int escape_str(char *restrict dst, const char *restrict src, int bufsize, int *maxcells); +extern int escape_command(char *restrict const outbuf, const proc_t *restrict const pp, int bytes, int *cells, unsigned flags); EXTERN_C_END #endif diff --git a/proc/library.map b/proc/library.map index 810bb4b7..f8cf9c7e 100644 --- a/proc/library.map +++ b/proc/library.map @@ -1,7 +1,7 @@ # for --version-script # WTF is the syntax for this file? # Give me a BNF, man! -_3_1_14 { +_3_2_4 { global: __cyg_profile_func_enter; __cyg_profile_func_exit; main; diff --git a/proc/readproc.c b/proc/readproc.c index d11fea17..581069f4 100644 --- a/proc/readproc.c +++ b/proc/readproc.c @@ -982,8 +982,7 @@ proc_data_t *readproctab2(int(*want_proc)(proc_t *buf), int(*want_task)(proc_t * * On failure, returns NULL. On success, returns 'p' and 'p' is a valid * and filled out proc_t structure. */ -proc_t * get_proc_stats(pid_t pid, proc_t *p) -{ +proc_t * get_proc_stats(pid_t pid, proc_t *p) { static char path[PATH_MAX], sbuf[1024]; struct stat statbuf; diff --git a/proc/whattime.c b/proc/whattime.c index a14eaf7b..d2785a82 100644 --- a/proc/whattime.c +++ b/proc/whattime.c @@ -82,7 +82,6 @@ char *sprint_uptime(void) { return buf; } -void print_uptime(void) -{ +void print_uptime(void) { printf("%s\n", sprint_uptime()); } diff --git a/ps/display.c b/ps/display.c index 25c73e79..0b46f89b 100644 --- a/ps/display.c +++ b/ps/display.c @@ -14,6 +14,10 @@ #include #include +#if (__GNU_LIBRARY__ >= 6) +# include +#endif + /* username lookups */ #include #include @@ -541,6 +545,10 @@ static void fancy_spew(void){ /***** no comment */ int main(int argc, char *argv[]){ +#if (__GNU_LIBRARY__ >= 6) + setlocale (LC_CTYPE, ""); +#endif + #ifdef DEBUG init_stack_trace(argv[0]); #else diff --git a/ps/output.c b/ps/output.c index 48529c04..47442062 100644 --- a/ps/output.c +++ b/ps/output.c @@ -276,6 +276,7 @@ STIME stime hms or md time format static int forest_helper(char *restrict const outbuf){ char *p = forest_prefix; char *q = outbuf; + int rightward=max_rightward; if(!*p) return 0; /* Arrrgh! somebody defined unix as 1 */ if(forest_type == 'u') goto unixy; @@ -287,7 +288,12 @@ static int forest_helper(char *restrict const outbuf){ case '|': strcpy(q, " | "); break; case '\0': return q-outbuf; /* redundant & not used */ } + if (rightward-4 < 0) { + *(q+rightward)='\0'; + return max_rightward; + } q += 4; + rightward -= 4; p++; } return q-outbuf; /* gcc likes this here */ @@ -300,7 +306,12 @@ unixy: case '|': strcpy(q, " "); break; case '\0': return q-outbuf; /* redundant & not used */ } + if (rightward-2 < 0) { + *(q+rightward)='\0'; + return max_rightward; + } q += 2; + rightward -= 2; p++; } return q-outbuf; /* gcc likes this here */ @@ -322,49 +333,73 @@ Modifications to the arguments are not shown. /* "command" is the same thing: long unless c */ static int pr_args(char *restrict const outbuf, const proc_t *restrict const pp){ - char *endp; + char *endp = outbuf; unsigned flags; + int rightward=max_rightward; - endp = outbuf + forest_helper(outbuf); + if(forest_prefix){ + int fh = forest_helper(outbuf); + endp += fh; + rightward -= fh; + } if(bsd_c_option) flags = ESC_DEFUNCT; else flags = ESC_DEFUNCT | ESC_BRACKETS | ESC_ARGS; - endp += escape_command(endp, pp, OUTBUF_SIZE, OUTBUF_SIZE, flags); + endp += escape_command(endp, pp, OUTBUF_SIZE, &rightward, flags); - if(bsd_e_option){ + if(bsd_e_option && rightward>1){ const char **env = (const char**)pp->environ; if(env && *env){ *endp++ = ' '; - endp += escape_strlist(endp, env, OUTBUF_SIZE); + rightward--; + endp += escape_strlist(endp, env, OUTBUF_SIZE, &rightward); } } - return endp - outbuf; + //return endp - outbuf; + return max_rightward-rightward; } /* "ucomm" is the same thing: short unless -f */ static int pr_comm(char *restrict const outbuf, const proc_t *restrict const pp){ - char *endp; + char *endp = outbuf; unsigned flags; - - endp = outbuf + forest_helper(outbuf); + int rightward=max_rightward; + + if(forest_prefix){ + int fh = forest_helper(outbuf); + endp += fh; + rightward -= fh; + } if(unix_f_option) flags = ESC_DEFUNCT | ESC_BRACKETS | ESC_ARGS; else flags = ESC_DEFUNCT; - endp += escape_command(endp, pp, OUTBUF_SIZE, OUTBUF_SIZE, flags); + endp += escape_command(endp, pp, OUTBUF_SIZE, &rightward, flags); - if(bsd_e_option){ + if(bsd_e_option && rightward>1){ const char **env = (const char**)pp->environ; if(env && *env){ *endp++ = ' '; - endp += escape_strlist(endp, env, OUTBUF_SIZE); + rightward--; + endp += escape_strlist(endp, env, OUTBUF_SIZE, &rightward); } } - return endp - outbuf; + //return endp - outbuf; + return max_rightward-rightward; } /* Non-standard, from SunOS 5 */ static int pr_fname(char *restrict const outbuf, const proc_t *restrict const pp){ - char *endp; - endp = outbuf + forest_helper(outbuf); - endp += escape_str(endp, pp->cmd, OUTBUF_SIZE, 8); - return endp - outbuf; + char *endp = outbuf; + int rightward = max_rightward; + + if(forest_prefix){ + int fh = forest_helper(outbuf); + endp += fh; + rightward -= fh; + } + if (rightward>8) /* 8=default, but forest maybe feeds more */ + rightward = 8; + + endp += escape_str(endp, pp->cmd, OUTBUF_SIZE, &rightward); + //return endp - outbuf; + return max_rightward-rightward; } /* elapsed wall clock time, [[dd-]hh:]mm:ss format (not same as "time") */ @@ -609,10 +644,13 @@ static int pr_wchan(char *restrict const outbuf, const proc_t *restrict const pp * AIX uses '-' for running processes, the location when there is * only one thread waiting in the kernel, and '*' when there is * more than one thread waiting in the kernel. + * + * The output should be truncated to maximal columns width -- overflow + * is not supported for the "wchan". */ - if(!(pp->wchan & 0xffffff)) return snprintf(outbuf, COLWID, "-"); - if(wchan_is_number) return snprintf(outbuf, COLWID, "%x", (unsigned)(pp->wchan) & 0xffffffu); - return snprintf(outbuf, COLWID, "%s", lookup_wchan(pp->wchan, pp->XXXID)); + if(!(pp->wchan & 0xffffff)) return snprintf(outbuf, max_rightward+1, "-"); + if(wchan_is_number) return snprintf(outbuf, max_rightward+1, "%x", (unsigned)(pp->wchan) & 0xffffffu); + return snprintf(outbuf, max_rightward+1, "%s", lookup_wchan(pp->wchan, pp->XXXID)); } /* Terrible trunctuation, like BSD crap uses: I999 J999 K999 */ @@ -824,14 +862,17 @@ static int pr_wname(char *restrict const outbuf, const proc_t *restrict const pp * We use '-' for running processes, the location when there is * only one thread waiting in the kernel, and '*' when there is * more than one thread waiting in the kernel. + * + * The output should be truncated to maximal columns width -- overflow + * is not supported for the "wchan". */ - if(!(pp->wchan & 0xffffff)) return snprintf(outbuf, COLWID, "-"); - return snprintf(outbuf, COLWID, "%s", lookup_wchan(pp->wchan, pp->XXXID)); + if(!(pp->wchan & 0xffffff)) return snprintf(outbuf, max_rightward+1, "-"); + return snprintf(outbuf, max_rightward+1, "%s", lookup_wchan(pp->wchan, pp->XXXID)); } static int pr_nwchan(char *restrict const outbuf, const proc_t *restrict const pp){ - if(!(pp->wchan & 0xffffff)) return snprintf(outbuf, COLWID, "-"); - return snprintf(outbuf, COLWID, "%x", (unsigned)(pp->wchan) & 0xffffffu); + if(!(pp->wchan & 0xffffff)) return snprintf(outbuf, max_rightward+1, "-"); + return snprintf(outbuf, max_rightward+1, "%x", (unsigned)(pp->wchan) & 0xffffffu); } static int pr_rss(char *restrict const outbuf, const proc_t *restrict const pp){ @@ -971,11 +1012,14 @@ static int pr_fuid(char *restrict const outbuf, const proc_t *restrict const pp) // static int do_pr_name(char *restrict const outbuf, const char *restrict const name, unsigned u){ if(!user_is_number){ - size_t len = strlen(name); - if(len <= max_rightward) { - memcpy(outbuf, name, len+1); - return len; - } + int rightward = OUTBUF_SIZE; /* max cells */ + int len; /* real cells */ + + escape_str(outbuf, name, OUTBUF_SIZE, &rightward); + len = OUTBUF_SIZE-rightward; + + if(len <= (int)max_rightward) + return len; /* returns number of cells */ } return snprintf(outbuf, COLWID, "%u", u); } @@ -1070,12 +1114,12 @@ fail: static int pr_t_unlimited(char *restrict const outbuf, const proc_t *restrict const pp){ static const char *const vals[] = {"[123456789-12345] ","ps","123456789-123456"}; (void)pp; - return snprintf(outbuf, COLWID, "%s", vals[lines_to_next_header%3u]); + return snprintf(outbuf, max_rightward+1, "%s", vals[lines_to_next_header%3u]); } static int pr_t_unlimited2(char *restrict const outbuf, const proc_t *restrict const pp){ static const char *const vals[] = {"unlimited", "[123456789-12345] ","ps","123456789-123456"}; (void)pp; - return snprintf(outbuf, COLWID, "%s", vals[lines_to_next_header%4u]); + return snprintf(outbuf, max_rightward+1, "%s", vals[lines_to_next_header%4u]); } // like "etime" @@ -1656,6 +1700,8 @@ void show_one_proc(const proc_t *restrict const p, const format_node *restrict f int space = 0; /* amount of space we actually need to print */ int dospace = 0; /* previous column determined that we need a space */ int legit = 0; /* legitimately stolen extra space */ + int sz = 0; /* real size of data in outbuffer */ + int tmpspace = 0; char *restrict const outbuf = saved_outbuf; static int did_stuff = 0; /* have we ever printed anything? */ @@ -1682,12 +1728,30 @@ void show_one_proc(const proc_t *restrict const p, const format_node *restrict f for(;;){ legit = 0; /* set width suggestion which might be ignored */ - if(likely(fmt->next)) max_rightward = fmt->width; - else max_rightward = active_cols-((correct>actual) ? correct : actual); +// if(likely(fmt->next)) max_rightward = fmt->width; +// else max_rightward = active_cols-((correct>actual) ? correct : actual); + + if(likely(fmt->next)){ + max_rightward = fmt->width; + tmpspace = 0; + }else{ + tmpspace = correct-actual; + if (tmpspace<1){ + tmpspace = dospace; + max_rightward = active_cols-actual-tmpspace; + }else{ + max_rightward = active_cols - ( (correct>actual) ? correct : actual ); + } + } max_leftward = fmt->width + actual - correct; /* TODO check this */ + +// fprintf(stderr, "cols: %d, max_rightward: %d, max_leftward: %d, actual: %d, correct: %d\n", +// active_cols, max_rightward, max_leftward, actual, correct); + /* prepare data and calculate leftpad */ if(likely(p) && likely(fmt->pr)) amount = (*fmt->pr)(outbuf,p); else amount = strlen(strcpy(outbuf, fmt->name)); /* AIX or headers */ + switch((fmt->flags) & CF_JUST_MASK){ case 0: /* for AIX, assigned outside this file */ leftpad = 0; @@ -1720,34 +1784,18 @@ void show_one_proc(const proc_t *restrict const p, const format_node *restrict f if(leftpad < 0) leftpad = 0; break; }else{ - if(fmt->next){ - outbuf[fmt->width] = '\0'; /* Must chop, more columns! */ - }else{ - int chopspot; /* place to chop */ - int tmpspace; /* need "space" before it is calculated below */ - tmpspace = correct - actual; - if(tmpspace<1) tmpspace = dospace; - chopspot = active_cols-actual-tmpspace; - if(chopspot<1) chopspot=1; /* oops, we (mostly) lose this column... */ - outbuf[chopspot] = '\0'; /* chop at screen/buffer limit */ - } + if ((active_cols-actual-tmpspace)<1) + outbuf[1] = '\0'; /* oops, we (mostly) lose this column... */ leftpad = 0; break; } case CF_UNLIMITED: - if(unlikely(fmt->next)){ - outbuf[fmt->width] = '\0'; /* Must chop, more columns! */ - }else{ - int chopspot; /* place to chop */ - int tmpspace; /* need "space" before it is calculated below */ - tmpspace = correct - actual; - if(tmpspace<1) tmpspace = dospace; - chopspot = active_cols-actual-tmpspace; - if(chopspot<1) chopspot=1; /* oops, we (mostly) lose this column... */ - outbuf[chopspot] = '\0'; /* chop at screen/buffer limit */ - } + { + if(active_cols-actual-tmpspace < 1) + outbuf[1] = '\0'; /* oops, we (mostly) lose this column... */ leftpad = 0; break; + } default: fprintf(stderr, "bad alignment code\n"); break; @@ -1766,16 +1814,18 @@ void show_one_proc(const proc_t *restrict const p, const format_node *restrict f if(space<1) space=dospace; if(unlikely(space>SPACE_AMOUNT)) space=SPACE_AMOUNT; // only so much available + /* real size -- don't forget in 'amount' is number of cells */ + sz = strlen(outbuf); + /* print data, set x position stuff */ - amount = strlen(outbuf); /* post-chop data width */ if(unlikely(!fmt->next)){ /* Last column. Write padding + data + newline all together. */ - outbuf[amount] = '\n'; - fwrite(outbuf-space, space+amount+1, 1, stdout); + outbuf[sz] = '\n'; + fwrite(outbuf-space, space+sz+1, 1, stdout); break; } /* Not the last column. Write padding + data together. */ - fwrite(outbuf-space, space+amount, 1, stdout); + fwrite(outbuf-space, space+sz, 1, stdout); actual += space+amount; correct += fmt->width; correct += legit; /* adjust for SIGNAL expansion */ diff --git a/top.c b/top.c index b711f517..25ee2f45 100644 --- a/top.c +++ b/top.c @@ -2912,9 +2912,10 @@ static void task_show (const WIN_t *q, const proc_t *p) case P_CMD: { char tmp[ROWBUFSIZ]; unsigned flags; + int maxcmd = q->maxcmdln; if (CHKw(q, Show_CMDLIN)) flags = ESC_DEFUNCT | ESC_BRACKETS | ESC_ARGS; else flags = ESC_DEFUNCT; - escape_command(tmp, p, sizeof tmp, q->maxcmdln, flags); + escape_command(tmp, p, sizeof tmp, &maxcmd, flags); MKCOL(q->maxcmdln, q->maxcmdln, tmp); } break; diff --git a/w.c b/w.c index cebb4c98..7fddd1d8 100644 --- a/w.c +++ b/w.c @@ -218,7 +218,7 @@ static void showinfo(utmp_t *u, int formtype, int maxcmd, int from) { fputs(" ", stdout); if (likely(best)) { char cmdbuf[512]; - escape_command(cmdbuf, best, sizeof cmdbuf, maxcmd, ESC_ARGS); + escape_command(cmdbuf, best, sizeof cmdbuf, &maxcmd, ESC_ARGS); fputs(cmdbuf,stdout); } else { printf("-");