diff --git a/include/escape.h b/include/escape.h new file mode 100644 index 0000000..e1a4e47 --- /dev/null +++ b/include/escape.h @@ -0,0 +1,28 @@ +/* + * escape.h - printing handling + * + * Copyright © 2011-2023 Jim Warner + * Copyright © 2016-2023 Craig Small + * Copyright © 1998-2005 Albert Cahalan + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef PROCPS_PROC_ESCAPE_H +#define PROCPS_PROC_ESCAPE_H + +int escape_str (char *dst, const char *src, int bufsize); + +#endif diff --git a/lib/Makefile b/lib/Makefile index 8347645..c16332e 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -21,7 +21,7 @@ AFOBJS = unix.o inet.o inet6.o ax25.o ipx.o ddp.o ipx.o netrom.o af.o rose.o ec AFGROBJS = inet_gr.o inet6_gr.o ipx_gr.o ddp_gr.o netrom_gr.o ax25_gr.o rose_gr.o getroute.o x25_gr.o AFSROBJS = inet_sr.o inet6_sr.o netrom_sr.o ipx_sr.o setroute.o x25_sr.o ACTOBJS = slip_ac.o ppp_ac.o activate.o -VARIA = getargs.o masq_info.o proc.o util.o nstrcmp.o interface.o sockets.o +VARIA = getargs.o masq_info.o proc.o util.o nstrcmp.o interface.o sockets.o escape.o # Default Name NET_LIB_NAME = net-tools diff --git a/lib/escape.c b/lib/escape.c new file mode 100644 index 0000000..1c3d0eb --- /dev/null +++ b/lib/escape.c @@ -0,0 +1,109 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Escape character print handling derived from procps + * Copyright 1998-2002 by Albert Cahalan + * Copyright 2020-2022 Jim Warner + * + */ + +#include +#include +#include +#include + +static const char UTF_tab[] = { + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, // 0x00 - 0x0F + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, // 0x10 - 0x1F + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, // 0x20 - 0x2F + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, // 0x30 - 0x3F + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, // 0x40 - 0x4F + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, // 0x50 - 0x5F + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, // 0x60 - 0x6F + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 - 0x7F + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, // 0x80 - 0x8F + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, // 0x90 - 0x9F + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, // 0xA0 - 0xAF + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, // 0xB0 - 0xBF + -1, -1, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, // 0xC0 - 0xCF + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, // 0xD0 - 0xDF + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, // 0xE0 - 0xEF + 4, 4, 4, 4, 4, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, // 0xF0 - 0xFF +}; + +static const unsigned char ESC_tab[] = { + "@..............................." // 0x00 - 0x1F + "||||||||||||||||||||||||||||||||" // 0x20 - 0x3F + "||||||||||||||||||||||||||||||||" // 0x40 - 0x5f + "|||||||||||||||||||||||||||||||." // 0x60 - 0x7F + "????????????????????????????????" // 0x80 - 0x9F + "????????????????????????????????" // 0xA0 - 0xBF + "????????????????????????????????" // 0xC0 - 0xDF + "????????????????????????????????" // 0xE0 - 0xFF +}; + +static void esc_all(unsigned char *str) +{ + // if bad locale/corrupt str, replace non-printing stuff + while (*str) { + unsigned char c = ESC_tab[*str]; + + if (c != '|') + *str = c; + ++str; + } +} + +static void esc_ctl(unsigned char *str, int len) +{ + int i; + + for (i = 0; i < len;) { + // even with a proper locale, strings might be corrupt + int n = UTF_tab[*str]; + + if (n < 0 || i + n > len) { + esc_all(str); + return; + } + // and eliminate those non-printing control characters + if (*str < 0x20 || *str == 0x7f) + *str = '?'; + str += n; + i += n; + } +} + +int escape_str(char *dst, const char *src, int bufsize) +{ + static int utf_sw; + + if (utf_sw == 0) { + char *enc = nl_langinfo(CODESET); + + utf_sw = enc && strcasecmp(enc, "UTF-8") == 0 ? 1 : -1; + } + + int n = strlcpy(dst, src, bufsize); + + if (utf_sw < 0) + esc_all((unsigned char *)dst); + else + esc_ctl((unsigned char *)dst, n); + return n; +} diff --git a/netstat.c b/netstat.c index 8475ee7..8dcab6b 100644 --- a/netstat.c +++ b/netstat.c @@ -96,6 +96,7 @@ #include "interface.h" #include "util.h" #include "proc.h" +#include "escape.h" #if HAVE_SELINUX #include @@ -397,7 +398,7 @@ static void prg_cache_load(void) { char line[LINE_MAX], eacces=0; int procfdlen, fd, cmdllen, lnamelen; - char lname[30], cmdlbuf[512], finbuf[PROGNAME_WIDTH]; + char lname[30], cmdlbuf[512], ecmdlbuf[512], finbuf[PROGNAME_WIDTH]; unsigned long inode; const char *cs, *cmdlp; DIR *dirproc = NULL, *dirfd = NULL; @@ -467,10 +468,11 @@ static void prg_cache_load(void) cmdlp++; else cmdlp = cmdlbuf; + escape_str (ecmdlbuf, cmdlp, 512); } // pid can be up to 10, use rest from commandline start. // #pragma GCC diagnostic ignored "-Wformat-truncation"? - snprintf(finbuf, sizeof(finbuf), "%s/%s", direproc->d_name, cmdlp); + snprintf(finbuf, sizeof(finbuf), "%s/%s", direproc->d_name, ecmdlbuf); #if HAVE_SELINUX if (getpidcon(atoi(direproc->d_name), &scon) == -1) { scon=xstrdup("-");