[Asterisk-code-review] term.c: Add support for extended number format terminfo files. (asterisk[master])

Friendly Automation asteriskteam at digium.com
Wed Sep 8 19:10:54 CDT 2021


Friendly Automation has submitted this change. ( https://gerrit.asterisk.org/c/asterisk/+/16441 )

Change subject: term.c: Add support for extended number format terminfo files.
......................................................................

term.c: Add support for extended number format terminfo files.

ncurses 6.1 introduced an extended number format for terminfo files
which the terminfo parsing in Asterisk is not able to parse. This
results in some TERM values that do support color (screen-256color on
Ubuntu 20.04 for example) to not get a color console.

ASTERISK-29630 #close

Change-Id: I27a4fcfab502219924af2d6b1c46feba92903cb3
---
M main/term.c
1 file changed, 78 insertions(+), 27 deletions(-)

Approvals:
  Joshua Colp: Looks good to me, but someone else must approve
  Kevin Harwell: Looks good to me, approved
  Friendly Automation: Approved for Submit



diff --git a/main/term.c b/main/term.c
index 617f82e..be10163 100644
--- a/main/term.c
+++ b/main/term.c
@@ -74,7 +74,7 @@
 }
 
 /* Ripped off from Ross Ridge, but it's public domain code (libmytinfo) */
-static short convshort(char *s)
+static short convshort(unsigned char *s)
 {
 	register int a, b;
 
@@ -89,11 +89,83 @@
 	return a + b * 256;
 }
 
+static inline int convint(unsigned char *s)
+{
+	return s[0]
+		| s[1] << 8
+		| s[2] << 16
+		| s[3] << 24;
+}
+
+#define MAGIC_LEGACY (00432)
+#define MAGIC_EXTNUM (01036)
+
+#define HEADER_LEN (12)
+#define MAX_COLORS_INDEX (13)
+
+static int parse_terminfo_file(int fd)
+{
+	int bytes_read, bytes_needed, num_size;
+	short magic, sz_names, sz_bools;
+	unsigned char buffer[1024];
+
+	bytes_read = read(fd, buffer, sizeof(buffer));
+	if (bytes_read < HEADER_LEN) {
+		return 0;
+	}
+
+	magic = convshort(buffer);
+
+	if (magic == MAGIC_LEGACY) {
+		num_size = 2;
+	} else if (magic == MAGIC_EXTNUM) {
+		/* Extended number format (ncurses 6.1) */
+		num_size = 4;
+	} else {
+		/* We don't know how to parse this file */
+		return 0;
+	}
+
+	sz_names = convshort(buffer + 2);
+	sz_bools = convshort(buffer + 4);
+
+	/* From term(5):
+	 * Between the boolean section and the number section, a null byte will be
+	 * inserted, if necessary, to ensure that the number section begins on an
+	 * even byte. */
+	if ((sz_names + sz_bools) & 1) {
+		sz_bools++;
+	}
+
+	bytes_needed = HEADER_LEN + sz_names + sz_bools + ((MAX_COLORS_INDEX + 1) * num_size);
+	if (bytes_needed <= bytes_read) {
+		/* Offset 13 is defined in /usr/include/term.h, though we do not
+		 * include it here, as it conflicts with include/asterisk/term.h */
+		int max_colors;
+		int offset = HEADER_LEN + sz_names + sz_bools + MAX_COLORS_INDEX * num_size;
+
+		if (num_size == 2) {
+			/* In the legacy terminfo format, numbers are signed shorts */
+			max_colors = convshort(buffer + offset);
+		} else {
+			/* Extended number format makes them signed ints */
+			max_colors = convint(buffer + offset);
+		}
+
+		if (max_colors > 0) {
+			vt100compat = 1;
+		}
+
+		return 1;
+	}
+
+	return 0;
+}
+
 int ast_term_init(void)
 {
 	char *term = getenv("TERM");
 	char termfile[256] = "";
-	char buffer[512] = "";
 	int termfd = -1, parseokay = 0, i;
 
 	if (ast_opt_no_color) {
@@ -110,36 +182,15 @@
 		return 0;
 	}
 
-	for (i = 0;; i++) {
-		if (termpath[i] == NULL) {
-			break;
-		}
+	for (i = 0; !parseokay && termpath[i]; i++) {
 		snprintf(termfile, sizeof(termfile), "%s/%c/%s", termpath[i], *term, term);
+
 		termfd = open(termfile, O_RDONLY);
 		if (termfd > -1) {
-			break;
+			parseokay = parse_terminfo_file(termfd);
+			close(termfd);
 		}
 	}
-	if (termfd > -1) {
-		int actsize = read(termfd, buffer, sizeof(buffer) - 1);
-		short sz_names = convshort(buffer + 2);
-		short sz_bools = convshort(buffer + 4);
-		short n_nums   = convshort(buffer + 6);
-
-		/* if ((sz_names + sz_bools) & 1)
-			sz_bools++; */
-
-		if (sz_names + sz_bools + n_nums < actsize) {
-			/* Offset 13 is defined in /usr/include/term.h, though we do not
-			 * include it here, as it conflicts with include/asterisk/term.h */
-			short max_colors = convshort(buffer + 12 + sz_names + sz_bools + 13 * 2);
-			if (max_colors > 0) {
-				vt100compat = 1;
-			}
-			parseokay = 1;
-		}
-		close(termfd);
-	}
 
 	if (!parseokay) {
 		/* These comparisons should not be substrings nor case-insensitive, as

-- 
To view, visit https://gerrit.asterisk.org/c/asterisk/+/16441
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-Change-Id: I27a4fcfab502219924af2d6b1c46feba92903cb3
Gerrit-Change-Number: 16441
Gerrit-PatchSet: 4
Gerrit-Owner: Sean Bright <sean at seanbright.com>
Gerrit-Reviewer: Friendly Automation
Gerrit-Reviewer: Joshua Colp <jcolp at sangoma.com>
Gerrit-Reviewer: Kevin Harwell <kharwell at digium.com>
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20210908/97077df6/attachment-0001.html>


More information about the asterisk-code-review mailing list