diff --git a/Makefile.am b/Makefile.am index 3c21658e..e49dc10f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -276,7 +276,6 @@ proc_libprocps_la_includedir = $(includedir)/procps/ proc_libprocps_la_include_HEADERS = \ proc/devname.h \ proc/diskstats.h \ - proc/escape.h \ proc/meminfo.h \ proc/namespace.h \ proc/numa.h \ diff --git a/proc/escape.c b/proc/escape.c index 9546ed77..8d358403 100644 --- a/proc/escape.c +++ b/proc/escape.c @@ -17,21 +17,19 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include +#include #include #include -#include +#include /* MB_CUR_MAX */ #include +#include +#include +#include #include "escape.h" #include "readproc.h" -#if (__GNU_LIBRARY__ >= 6) && (!defined(__UCLIBC__) || defined(__UCLIBC_HAS_WCHAR__)) -# include -# include -# include /* MB_CUR_MAX */ -# include -# include -#endif #define SECURE_ESCAPE_ARGS(dst, bytes, cells) do { \ if ((bytes) <= 0) return 0; \ @@ -42,8 +40,7 @@ } while (0) -#if (__GNU_LIBRARY__ >= 6) && (!defined(__UCLIBC__) || defined(__UCLIBC_HAS_WCHAR__)) -static int escape_str_utf8(char *restrict dst, const char *restrict src, int bufsize, int *maxcells){ +static int escape_str_utf8 (char *dst, const char *src, int bufsize, int *maxcells) { int my_cells = 0; int my_bytes = 0; mbstate_t s; @@ -107,10 +104,9 @@ static int escape_str_utf8(char *restrict dst, const char *restrict src, int buf 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 *maxcells){ +int escape_str (char *dst, const char *src, int bufsize, int *maxcells) { unsigned char c; int my_cells = 0; int my_bytes = 0; @@ -124,7 +120,6 @@ int escape_str(char *restrict dst, const char *restrict src, int bufsize, int *m "????????????????????????????????" "????????????????????????????????"; -#if (__GNU_LIBRARY__ >= 6) && (!defined(__UCLIBC__) || defined(__UCLIBC_HAS_WCHAR__)) static int utf_init=0; if(utf_init==0){ @@ -136,7 +131,6 @@ int escape_str(char *restrict dst, const char *restrict src, int bufsize, int *m /* UTF8 locales */ return escape_str_utf8(dst, src, bufsize, maxcells); } -#endif SECURE_ESCAPE_ARGS(dst, bufsize, *maxcells); @@ -163,7 +157,7 @@ int escape_str(char *restrict dst, const char *restrict src, int bufsize, int *m // escape an argv or environment string array // // bytes arg means sizeof(buf) -static int escape_strlist(char *restrict dst, char *restrict const *restrict src, size_t bytes, int *cells){ +static int escape_strlist (char *dst, const char **src, size_t bytes, int *cells) { size_t i = 0; for(;;){ @@ -180,12 +174,12 @@ static int escape_strlist(char *restrict dst, char *restrict const *restrict src /////////////////////////////////////////////////// -int escape_command(char *restrict const outbuf, const proc_t *restrict const pp, int bytes, int *cells, unsigned flags){ +int escape_command (char *const outbuf, const proc_t *pp, int bytes, int *cells, unsigned flags) { int overhead = 0; int end = 0; if(flags & ESC_ARGS){ - char **lc = (char**)pp->cmdline; + const char **lc = (const char**)pp->cmdline; if(lc && *lc) return escape_strlist(outbuf, lc, bytes, cells); } if(flags & ESC_BRACKETS){ @@ -217,4 +211,3 @@ int escape_command(char *restrict const outbuf, const proc_t *restrict const pp, outbuf[end] = '\0'; return end; // bytes, not including the NUL } - diff --git a/proc/escape.h b/proc/escape.h index 75e830bf..684eba1d 100644 --- a/proc/escape.h +++ b/proc/escape.h @@ -3,14 +3,12 @@ #include "readproc.h" - #define ESC_ARGS 0x1 // try to use cmdline instead of cmd #define ESC_BRACKETS 0x2 // if using cmd, put '[' and ']' around it #define ESC_DEFUNCT 0x4 // mark zombies with " " -int escape_command(char *__restrict const outbuf, const proc_t *__restrict const pp, int bytes, int *cells, unsigned flags); +int escape_command (char *outbuf, const proc_t *pp, int bytes, int *cells, unsigned flags); -#define ESC_STRETCH 1 // since we mangle to '?' this is 1 (would be 4 for octal escapes) -int escape_str(char *__restrict dst, const char *__restrict src, int bufsize, int *maxcells); +int escape_str (char *dst, const char *src, int bufsize, int *maxcells); #endif diff --git a/proc/libprocps.sym b/proc/libprocps.sym index 8853048d..9cdbd248 100644 --- a/proc/libprocps.sym +++ b/proc/libprocps.sym @@ -1,6 +1,5 @@ LIBPROCPS_0 { global: - escape_str; fatal_proc_unmounted; procps_cpu_count; procps_diskstats_new; diff --git a/ps/common.h b/ps/common.h index 097b89d2..9511c32c 100644 --- a/ps/common.h +++ b/ps/common.h @@ -13,7 +13,6 @@ #define PROCPS_PS_H #include "../include/nls.h" -#include #include #include #include @@ -204,7 +203,6 @@ makEXT(noop) * Try not to overflow the output buffer: * 32 pages for env+cmd * 64 kB pages on IA-64 - * 4 chars for "\377", or 1 when mangling to '?' (ESC_STRETCH) * plus some slack for other stuff * That is about 8.5 MB on IA-64, or 0.6 MB on i386 * @@ -214,7 +212,7 @@ makEXT(noop) */ /* output buffer size */ -#define OUTBUF_SIZE (2 * 64*1024 * ESC_STRETCH) +#define OUTBUF_SIZE (2 * 64*1024) /******************* PS DEFINE *******************/ diff --git a/ps/output.c b/ps/output.c index b5945924..20f9a534 100644 --- a/ps/output.c +++ b/ps/output.c @@ -49,8 +49,10 @@ #if ENABLE_LIBSELINUX #include #endif +#include #include #include +#include #include #include #include @@ -58,13 +60,14 @@ #include #include #include +#include +#include #include #include #include #include - #include "../include/c.h" #include "common.h" @@ -79,7 +82,6 @@ static unsigned max_rightward = OUTBUF_SIZE-1; /* space for RIGHT stuff */ static unsigned max_leftward = OUTBUF_SIZE-1; /* space for LEFT stuff */ - static int wide_signals; /* true if we have room */ static time_t seconds_since_1970; @@ -135,6 +137,117 @@ static int escaped_copy(char *restrict dst, const char *restrict src, int bufsiz return n; } +// duplicated from proc/escape.c so both can be made private +static int escape_str_utf8 (char *dst, const char *src, int bufsize, int *maxcells) { + int my_cells = 0; + int my_bytes = 0; + mbstate_t s; + + SECURE_ESCAPE_ARGS(dst, bufsize, *maxcells); + + 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 - maybe, kinda "printable" */ + int wlen = wcwidth(wc); + // Got space? + if (wlen > *maxcells-my_cells || len >= bufsize-(my_bytes+1)) break; + // safe multibyte + memcpy(dst, src, len); + dst += len; + src += len; + my_bytes += len; + if (wlen > 0) my_cells += wlen; + } + //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 +} + +// duplicated from proc/escape.c so both can be made private +static int escape_str (char *dst, const char *src, int bufsize, int *maxcells) { + unsigned char c; + int my_cells = 0; + int my_bytes = 0; + const char codes[] = + "Z..............................." + "||||||||||||||||||||||||||||||||" + "||||||||||||||||||||||||||||||||" + "|||||||||||||||||||||||||||||||." + "????????????????????????????????" + "????????????????????????????????" + "????????????????????????????????" + "????????????????????????????????"; + 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 && MB_CUR_MAX>1) { + /* UTF8 locales */ + return escape_str_utf8(dst, src, bufsize, maxcells); + } + + SECURE_ESCAPE_ARGS(dst, bufsize, *maxcells); + + if(bufsize > *maxcells+1) bufsize=*maxcells+1; // FIXME: assumes 8-bit locale + + for(;;){ + if(my_cells >= *maxcells || my_bytes+1 >= bufsize) + break; + c = (unsigned char) *(src++); + if(!c) break; + if(codes[c]!='|') c=codes[c]; + my_cells++; + my_bytes++; + *(dst++) = c; + } + *dst = '\0'; + + *maxcells -= my_cells; + return my_bytes; // bytes of text, excluding the NUL +} + /***************************************************************************/ /************ Lots of format functions, starting with the NOP **************/