diff --git a/Makefile b/Makefile index 24c138e..a251050 100644 --- a/Makefile +++ b/Makefile @@ -191,8 +191,8 @@ slattach: $(NET_LIB) slattach.o plipconfig: $(NET_LIB) plipconfig.o $(CC) $(CFLAGS) $(LDFLAGS) -o $@ plipconfig.o $(NLIB) $(LDLIBS) -netstat: $(NET_LIB) netstat.o statistics.o - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ netstat.o statistics.o $(NLIB) $(SELIB) $(LDLIBS) +netstat: $(NET_LIB) netstat.o statistics.o lib/escape.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ netstat.o statistics.o lib/escape.o $(NLIB) $(SELIB) $(LDLIBS) iptunnel: $(NET_LIB) iptunnel.o $(CC) $(CFLAGS) $(LDFLAGS) -o $@ iptunnel.o $(NLIB) $(LDLIBS) diff --git a/include/escape.h b/include/escape.h new file mode 100644 index 0000000..0238c68 --- /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 ESCAPE_H +#define ESCAPE_H + +void escape_str_inplace (char *string, int len); + +#endif diff --git a/lib/Makefile b/lib/Makefile index 8347645..90f767f 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -22,6 +22,7 @@ AFGROBJS = inet_gr.o inet6_gr.o ipx_gr.o ddp_gr.o netrom_gr.o ax25_gr.o rose_gr. 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 +EXTRA = escape.o # Default Name NET_LIB_NAME = net-tools @@ -41,7 +42,7 @@ SONAME=libnet-tools.so.0 .SUFFIXES: .a .so -all: lib$(NET_LIB_NAME).a # lib$(NET_LIB_NAME).so +all: lib$(NET_LIB_NAME).a escape.o # lib$(NET_LIB_NAME).so lib$(NET_LIB_NAME).a: Makefile $(TOPDIR)/config.h $(OBJS) @echo Building $@ diff --git a/lib/escape.c b/lib/escape.c new file mode 100644 index 0000000..1d7e367 --- /dev/null +++ b/lib/escape.c @@ -0,0 +1,111 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Escape character print handling derived from procps + * Copyright 1998-2002 by Albert Cahalan + * Copyright 2020-2022 Jim Warner + * + * Simplification for procps ps: + * Stephen Hemminger , 2025 + * Inplace modification: + * Stanislav Brabec , 2026 + * + */ + +#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; + } +} + +void escape_str_inplace(char *string, int len) +{ + static int utf_sw; + + if (utf_sw == 0) { + char *enc = nl_langinfo(CODESET); + + utf_sw = enc && strcasecmp(enc, "UTF-8") == 0 ? 1 : -1; + } + + if (utf_sw < 0) + esc_all((unsigned char *)string); + else + esc_ctl((unsigned char *)string, len); +} diff --git a/netstat.c b/netstat.c index b8be850..5a7d97a 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 @@ -468,13 +469,7 @@ static void prg_cache_load(void) // cmdlbuf[sizeof(cmdlbuf) - 1) is already \0 cmdllen = sizeof(cmdlbuf) - 1; // remove all embedded controls - for(int i=0; i < cmdllen; i++) { - char c = cmdlbuf[i]; - if (c == 0) // we dont process arguments - break; - if (c < ' ' || c > '~') // safe 7bit ASCII - cmdlbuf[i] = '.'; - } + escape_str_inplace (cmdlbuf, strlen(cmdlbuf)); if (cmdlbuf[0] == '/' && (cmdlp = strrchr(cmdlbuf, '/'))) cmdlp++; else