axlisten: colors for command line

folkert folkert at vanheusden.com
Tue Nov 20 08:53:39 EST 2018


> Would it be possible to have just ^M (enter) to exit listen/axlisten,
> because if it is invoked via telnet for a ham app it wants ctrl-c to
> exit...cannot exit...

The version below has the following new features:
- colors in non-ncurses mode (-C)
- press 'q' to exit (-e to enable)

diff --git a/AUTHORS b/AUTHORS
index 7b91e72..deeee0d 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -17,6 +17,7 @@ Heikki Hannikainen OH7LZB <oh7lzb at sral.fi>
 Alan Cox GW4PTS <alan at cymru.net>
 Jean-Paul for rose decoding
 Jeroen Vreeken for INP decoding
+Folkert van Heusden <mail at vanheusden.com>
 
 call:
 Alexander Tietzel DG6XA <TIETZE_A at etech.fh-hamburg.de>
diff --git a/listen/listen.c b/listen/listen.c
index 6504ed5..fb80987 100644
--- a/listen/listen.c
+++ b/listen/listen.c
@@ -3,6 +3,8 @@
 #include <netdb.h>
 
 #include <unistd.h>
+#include <termios.h>
+#include <poll.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -202,9 +204,15 @@ int main(int argc, char **argv)
 	struct ifreq ifr;
 	int proto = ETH_P_AX25;
 	int exit_code = EXIT_SUCCESS;
+	char q_exit = 0;
+	struct pollfd fds[2];
+	struct termios oldtermios, newtermios;
 
-	while ((s = getopt(argc, argv, "8achip:rtv")) != -1) {
+	while ((s = getopt(argc, argv, "e8acChip:rtv")) != -1) {
 		switch (s) {
+		case 'e':
+			q_exit = 1;
+			break;
 		case '8':
 			sevenbit = 0;
 			break;
@@ -214,6 +222,9 @@ int main(int argc, char **argv)
 		case 'c':
 			color = 1;
 			break;
+		case 'C':
+			a_color = 1;
+			break;
 		case 'h':
 			dumpstyle = HEX;
 			break;
@@ -276,6 +287,17 @@ int main(int argc, char **argv)
 		return 1;
 	}
 
+	fds[0].fd = sock;
+	fds[0].events = POLLIN;
+
+	fds[1].fd = STDIN_FILENO;
+	fds[1].events = POLLIN;
+
+	tcgetattr(STDIN_FILENO, &oldtermios);
+	newtermios = oldtermios;
+
+	cfmakeraw(&newtermios);
+
 	if (color) {
 		color = initcolor();	/* Initialize color support */
 		if (!color)
@@ -285,93 +307,120 @@ int main(int argc, char **argv)
 	setservent(1);
 
 	while (!sigint) {
+		int rc;
+
 		asize = sizeof(sa);
 
-		signal(SIGINT, handle_sigint);
-		signal(SIGTERM, handle_sigint);
-		size = recvfrom(sock, buffer, sizeof(buffer), 0, &sa, &asize);
-		if (size == -1) {
-			/*
-			 * Signals are cared for by the handler, and we
-			 * don't want to abort on SIGWINCH
-			 */
-			if (errno == EINTR) {
-				refresh();
-				continue;
-			} else if (!(errno == EBADF && sigint)) {
-				perror("recv");
-				exit_code = errno;
-			}
+		tcsetattr(STDIN_FILENO, TCSANOW, &newtermios);
+		fds[0].events = fds[1].events = POLLIN;
+		fds[0].revents = fds[1].revents = 0;
+
+		rc = poll(fds, q_exit ? 2 : 1, -1);
+		if (rc == -1) {
+			perror("poll");
 			break;
 		}
-		gettimeofday(&t_recv, NULL);
-		signal(SIGINT, SIG_DFL);
-		signal(SIGTERM, SIG_DFL);
-		if (sock == -1 || sigint)
-			break;
 
-		if (dev != NULL && strcmp(dev, sa.sa_data) != 0)
+		if (rc == 0)
 			continue;
 
-		if (proto == ETH_P_ALL) {
-			strcpy(ifr.ifr_name, sa.sa_data);
+		if (q_exit && fds[1].revents == POLLIN) {
+			int c = getchar();
+			if (c == 'q' || c == 3)
+				break;
+		}
+
+		tcsetattr(STDIN_FILENO, TCSANOW, &oldtermios);
+
+		if (fds[0].revents == POLLIN) {
 			signal(SIGINT, handle_sigint);
 			signal(SIGTERM, handle_sigint);
-			if (ioctl(sock, SIOCGIFHWADDR, &ifr) == -1) {
-				if (!(errno == EBADF && sigint)) {
-					perror("SIOCGIFHWADDR");
+			size = recvfrom(sock, buffer, sizeof(buffer), 0, &sa, &asize);
+			if (size == -1) {
+				/*
+				 * Signals are cared for by the handler, and we
+				 * don't want to abort on SIGWINCH
+				 */
+				if (errno == EINTR) {
+					refresh();
+					continue;
+				} else if (!(errno == EBADF && sigint)) {
+					perror("recv");
 					exit_code = errno;
-					break;
 				}
+				break;
 			}
+			gettimeofday(&t_recv, NULL);
 			signal(SIGINT, SIG_DFL);
 			signal(SIGTERM, SIG_DFL);
 			if (sock == -1 || sigint)
 				break;
-			if (ifr.ifr_hwaddr.sa_family == AF_AX25) {
-                                if (size > 2 && *buffer == 0xcc) {
-                                        /* IP packets from the ax25 de-segmenter
-                                           are seen on socket "PF_PACKET,
-                                           SOCK_PACKET, ETH_P_ALL" without
-                                           AX.25 header (just the IP-frame),
-                                           prefixed by 0xcc (AX25_P_IP).
-                                           It's unclear why in the kernel code
-                                           this happens (unsegmentet AX25 PID
-                                           AX25_P_IP have not this behavior).
-                                           We have already displayed all the
-                                           segments and like to ignore this
-                                           data.
-                                           AX.25 packets start with a kiss
-                                           byte (buffer[0]); ax25_dump()
-                                           looks for it.
-                                           There's no kiss command 0xcc
-                                           defined; kiss bytes are checked
-                                           against & 0xf (= 0x0c), which is
-                                           also not defined.
-                                           Kiss commands may have one argument.
-                                           => We can make safely make the
-                                           assumption for first byte == 0xcc
-                                           and length > 2, that we safeley can
-                                           detect those IP frames, and then
-                                           ignore it.
-                                         */
-                                        continue;
-                                }
+
+			if (dev != NULL && strcmp(dev, sa.sa_data) != 0)
+				continue;
+
+			if (proto == ETH_P_ALL) {
+				strcpy(ifr.ifr_name, sa.sa_data);
+				signal(SIGINT, handle_sigint);
+				signal(SIGTERM, handle_sigint);
+				if (ioctl(sock, SIOCGIFHWADDR, &ifr) == -1) {
+					if (!(errno == EBADF && sigint)) {
+						perror("SIOCGIFHWADDR");
+						exit_code = errno;
+						break;
+					}
+				}
+				signal(SIGINT, SIG_DFL);
+				signal(SIGTERM, SIG_DFL);
+				if (sock == -1 || sigint)
+					break;
+				if (ifr.ifr_hwaddr.sa_family == AF_AX25) {
+					if (size > 2 && *buffer == 0xcc) {
+						/* IP packets from the ax25 de-segmenter
+						   are seen on socket "PF_PACKET,
+						   SOCK_PACKET, ETH_P_ALL" without
+						   AX.25 header (just the IP-frame),
+						   prefixed by 0xcc (AX25_P_IP).
+						   It's unclear why in the kernel code
+						   this happens (unsegmentet AX25 PID
+						   AX25_P_IP have not this behavior).
+						   We have already displayed all the
+						   segments and like to ignore this
+						   data.
+						   AX.25 packets start with a kiss
+						   byte (buffer[0]); ax25_dump()
+						   looks for it.
+						   There's no kiss command 0xcc
+						   defined; kiss bytes are checked
+						   against & 0xf (= 0x0c), which is
+						   also not defined.
+						   Kiss commands may have one argument.
+						   => We can make safely make the
+						   assumption for first byte == 0xcc
+						   and length > 2, that we safeley can
+						   detect those IP frames, and then
+						   ignore it.
+						 */
+						continue;
+					}
+					display_port(sa.sa_data);
+					ki_dump(buffer, size, dumpstyle);
+	/*				lprintf(T_DATA, "\n");  */
+				}
+			} else {
 				display_port(sa.sa_data);
 				ki_dump(buffer, size, dumpstyle);
-/*				lprintf(T_DATA, "\n");  */
+	/*                      lprintf(T_DATA, "\n");  */
 			}
-		} else {
-			display_port(sa.sa_data);
-			ki_dump(buffer, size, dumpstyle);
-/*                      lprintf(T_DATA, "\n");  */
+			if (color)
+				refresh();
 		}
-		if (color)
-			refresh();
 	}
 	if (color)
 		endwin();
 
+	tcsetattr(STDIN_FILENO, TCSANOW, &oldtermios);
+
 	return exit_code;
 }
 
diff --git a/listen/listen.h b/listen/listen.h
index 46ec397..72c185e 100644
--- a/listen/listen.h
+++ b/listen/listen.h
@@ -36,6 +36,7 @@
 
 /* In utils.c */
 extern int color;			/* Colorized mode */
+extern int a_color;			/* ANSI-colorized mode */
 extern int sevenbit;			/* Are we on a 7-bit terminal? */
 extern int ibmhack;			/* IBM mapping? */
 
diff --git a/listen/utils.c b/listen/utils.c
index 4d99e10..26653a4 100644
--- a/listen/utils.c
+++ b/listen/utils.c
@@ -16,6 +16,7 @@
 #include "listen.h"
 
 int color = 0;			/* Colorized? */
+int a_color = 0;		/* ANSI-colorized mode */
 int sevenbit = 1;		/* Are we on a 7-bit terminal? */
 int ibmhack = 0;		/* IBM mapping? */
 
@@ -45,7 +46,7 @@ void lprintf(int dtype, char *fmt, ...)
 	vsnprintf(str, 1024, fmt, args);
 	va_end(args);
 
-	if (color) {
+	if (color || a_color) {
 		for (p = str; *p != '\0'; p++) {
 			ch = *p;
 
@@ -63,9 +64,20 @@ void lprintf(int dtype, char *fmt, ...)
 			    || (dtype == T_TIMESTAMP))
 				ch |= A_BOLD;
 
-			ch |= COLOR_PAIR(dtype);
+			if (color) {
+				ch |= COLOR_PAIR(dtype);
+				addch(ch);
+			}
+			else { /* a_color */
+				if (ch & A_BOLD)
+					printf("\x1b[1m");
+				if (ch & A_REVERSE)
+					printf("\x1b[7m");
 
-			addch(ch);
+				printf("\x1b[%dm%c", 30 + (dtype & 7), ch & 255);
+
+				printf("\x1b[0m");
+			}
 		}
 	} else {
 		for (p = str; *p != '\0'; p++)



Folkert van Heusden

-- 
Wintips voor de staatsloterij? http://www.slimwinnen.nl/
     Meer weten over Bitcoins? http://www.vanheusden.com/bitcoins/
          Meer weten over TOR? http://www.vanheusden.com/tor/
----------------------------------------------------------------------
Phone: +31-6-41278122, PGP-key: 1F28D8AE, www.vanheusden.com


More information about the Linux-ham mailing list