leftovers in the 3.2.4 release
This commit is contained in:
208
proc/escape.c
208
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 <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#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;){
|
||||
c = (unsigned char) *(src++);
|
||||
d = codes[c];
|
||||
switch(d){
|
||||
case 'Z':
|
||||
goto leave;
|
||||
case '*':
|
||||
i++;
|
||||
*(dst++) = c;
|
||||
break;
|
||||
case '-':
|
||||
if(i+4 > 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 <wchar.h>
|
||||
# include <wctype.h>
|
||||
# include <stdlib.h> /* MB_CUR_MAX */
|
||||
# include <ctype.h>
|
||||
# include <langinfo.h>
|
||||
#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 " <defunct>"
|
||||
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] <defunct>" or "[foo <defunct>]"?
|
||||
if(flags & ESC_BRACKETS){
|
||||
@ -166,7 +211,6 @@ int escape_command(char *restrict const outbuf, const proc_t *restrict const pp,
|
||||
memcpy(outbuf+end, " <defunct>", 10);
|
||||
end += 10;
|
||||
}
|
||||
|
||||
outbuf[end] = '\0';
|
||||
return end; // bytes or glyphs, not including the NUL
|
||||
return end; // bytes, not including the NUL
|
||||
}
|
||||
|
Reference in New Issue
Block a user