[systemd-devel] [PATCH 06/11] There is no ANSI support on common 3215 consoles

Werner Fink werner at suse.de
Fri Jun 13 07:41:05 PDT 2014


Therefore strip off the ANSI escape sequences for 3215 consoles
but support 3270 consoles if found.

---
 src/core/manager.c |   24 ++++++++++++----
 src/shared/util.c  |   80 +++++++++++++++++++++++++++++++++++++++++++++++++---
 src/shared/util.h  |    1 +
 3 files changed, 96 insertions(+), 9 deletions(-)

diff --git src/core/manager.c src/core/manager.c
index 0cb2044..f78ac18 100644
--- src/core/manager.c
+++ src/core/manager.c
@@ -112,7 +112,7 @@ static int manager_watch_jobs_in_progress(Manager *m) {
 
 #define CYLON_BUFFER_EXTRA (2*(sizeof(ANSI_RED_ON)-1) + sizeof(ANSI_HIGHLIGHT_RED_ON)-1 + 2*(sizeof(ANSI_HIGHLIGHT_OFF)-1))
 
-static void draw_cylon(char buffer[], size_t buflen, unsigned width, unsigned pos) {
+static void draw_cylon(char buffer[], size_t buflen, unsigned width, unsigned pos, bool ansi_console) {
         char *p = buffer;
 
         assert(buflen >= CYLON_BUFFER_EXTRA + width + 1);
@@ -121,12 +121,14 @@ static void draw_cylon(char buffer[], size_t buflen, unsigned width, unsigned po
         if (pos > 1) {
                 if (pos > 2)
                         p = mempset(p, ' ', pos-2);
-                p = stpcpy(p, ANSI_RED_ON);
+                if (ansi_console)
+                        p = stpcpy(p, ANSI_RED_ON);
                 *p++ = '*';
         }
 
         if (pos > 0 && pos <= width) {
-                p = stpcpy(p, ANSI_HIGHLIGHT_RED_ON);
+                if (ansi_console)
+                        p = stpcpy(p, ANSI_HIGHLIGHT_RED_ON);
                 *p++ = '*';
         }
 
@@ -137,7 +139,8 @@ static void draw_cylon(char buffer[], size_t buflen, unsigned width, unsigned po
                 *p++ = '*';
                 if (pos < width-1)
                         p = mempset(p, ' ', width-1-pos);
-                strcpy(p, ANSI_HIGHLIGHT_OFF);
+                if (ansi_console)
+                        strcpy(p, ANSI_HIGHLIGHT_OFF);
         }
 }
 
@@ -154,6 +157,7 @@ void manager_flip_auto_status(Manager *m, bool enable) {
 }
 
 static void manager_print_jobs_in_progress(Manager *m) {
+        static int is_ansi_console = -1;
         _cleanup_free_ char *job_of_n = NULL;
         Iterator i;
         Job *j;
@@ -178,10 +182,20 @@ static void manager_print_jobs_in_progress(Manager *m) {
         assert(counter == print_nr + 1);
         assert(j);
 
+        if (_unlikely_(is_ansi_console < 0)) {
+                int fd = open_terminal("/dev/console", O_RDONLY|O_NOCTTY|O_CLOEXEC);
+                if (fd < 0)
+                        is_ansi_console = 0;
+                else {
+                        is_ansi_console = (int)ansi_console(fd);
+                        close(fd);
+                }
+        }
+
         cylon_pos = m->jobs_in_progress_iteration % 14;
         if (cylon_pos >= 8)
                 cylon_pos = 14 - cylon_pos;
-        draw_cylon(cylon, sizeof(cylon), 6, cylon_pos);
+        draw_cylon(cylon, sizeof(cylon), 6, cylon_pos, (bool)is_ansi_console);
 
         m->jobs_in_progress_iteration++;
 
diff --git src/shared/util.c src/shared/util.c
index a7aec5c..03b01de 100644
--- src/shared/util.c
+++ src/shared/util.c
@@ -2937,6 +2937,7 @@ int status_vprintf(const char *status, bool ellipse, bool ephemeral, const char
         struct iovec iovec[6] = {};
         int n = 0;
         static bool prev_ephemeral;
+        static int is_ansi_console = -1;
 
         assert(format);
 
@@ -2950,6 +2951,41 @@ int status_vprintf(const char *status, bool ellipse, bool ephemeral, const char
         if (fd < 0)
                 return fd;
 
+        if (_unlikely_(is_ansi_console < 0))
+                is_ansi_console = (int)ansi_console(fd);
+
+        if (status && !is_ansi_console) {
+                const char *esc, *ptr;
+                esc = strchr(status, 0x1B);
+                if (esc && (ptr = strpbrk(esc, "SOFDTI*"))) {
+                        switch(*ptr) {
+                        case 'S':
+                                status = " SKIP ";
+                                break;
+                        case 'O':
+                                status = "  OK  ";
+                                break;
+                        case 'F':
+                                status = "FAILED";
+                                break;
+                        case 'D':
+                                status = "DEPEND";
+                                break;
+                        case 'T':
+                                status = " TIME ";
+                                break;
+                        case 'I':
+                                status = " INFO ";
+                                break;
+                        case '*':
+                                status = " BUSY ";
+                                break;
+                        default:
+                                break;
+                        }
+                }
+        }
+
         if (ellipse) {
                 char *e;
                 size_t emax, sl;
@@ -2972,8 +3008,12 @@ int status_vprintf(const char *status, bool ellipse, bool ephemeral, const char
                 }
         }
 
-        if (prev_ephemeral)
-                IOVEC_SET_STRING(iovec[n++], "\r" ANSI_ERASE_TO_END_OF_LINE);
+        if (prev_ephemeral) {
+                if (is_ansi_console)
+                        IOVEC_SET_STRING(iovec[n++], "\r" ANSI_ERASE_TO_END_OF_LINE);
+                else
+                        IOVEC_SET_STRING(iovec[n++], "\r");
+        }
         prev_ephemeral = ephemeral;
 
         if (status) {
@@ -3220,8 +3260,22 @@ void columns_lines_cache_reset(int signum) {
 bool on_tty(void) {
         static int cached_on_tty = -1;
 
-        if (_unlikely_(cached_on_tty < 0))
+        if (_unlikely_(cached_on_tty < 0)) {
                 cached_on_tty = isatty(STDOUT_FILENO) > 0;
+#if defined (__s390__) || defined (__s390x__)
+                if (cached_on_tty) {
+                        const char *e = getenv("TERM");
+                        if (!e)
+                                return cached_on_tty;
+                        if (streq(e, "dumb") || strneq(e, "ibm3", 4)) {
+                                char *mode = NULL;
+                                int r = parse_env_file("/proc/cmdline", WHITESPACE, "conmode", &mode, NULL);
+                                if (r < 0 || !mode || !streq(mode, "3270"))
+                                        cached_on_tty = 0;
+                        }
+                }
+#endif
+        }
 
         return cached_on_tty;
 }
@@ -3711,7 +3765,25 @@ bool tty_is_vc_resolve(const char *tty) {
 const char *default_term_for_tty(const char *tty) {
         assert(tty);
 
-        return tty_is_vc_resolve(tty) ? "TERM=linux" : "TERM=vt102";
+        if (tty_is_vc_resolve(tty))
+                return "TERM=linux";
+
+        if (startswith(tty, "/dev/"))
+                tty += 5;
+
+#if defined (__s390__) || defined (__s390x__)
+        if (streq(tty, "ttyS0")) {
+                char *mode = NULL;
+                int r = parse_env_file("/proc/cmdline", WHITESPACE, "conmode", &mode, NULL);
+                if (r < 0 || !mode || !streq(mode, "3270"))
+                        return "TERM=dumb";
+                if (streq(mode, "3270"))
+                        return "TERM=ibm327x";
+        }
+        if (streq(tty, "ttyS1"))
+                return "TERM=vt220";
+#endif
+        return "TERM=vt102";
 }
 
 bool dirent_is_file(const struct dirent *de) {
diff --git src/shared/util.h src/shared/util.h
index 1796014..2dc918d 100644
--- src/shared/util.h
+++ src/shared/util.h
@@ -446,6 +446,7 @@ unsigned lines(void);
 void columns_lines_cache_reset(int _unused_ signum);
 
 bool on_tty(void);
+bool ansi_console(int fd);
 
 static inline const char *ansi_highlight(void) {
         return on_tty() ? ANSI_HIGHLIGHT_ON : "";
-- 
1.7.9.2



More information about the systemd-devel mailing list