summary refs log tree commit diff
path: root/shared/systemd/src/basic/string-util.c
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2019-12-18 18:29:24 +0100
committerMichael Biebl <biebl@debian.org>2019-12-18 18:29:24 +0100
commit28028b26b3371756811e95d894f709f4b1207c00 (patch)
tree6fe7316fd743b51042db47601a8ef8814b3134ac /shared/systemd/src/basic/string-util.c
parente22609983008e1a669196ad64ba3a59ae8c76e0d (diff)
New upstream version 1.22.0 upstream/1.22.0
Diffstat (limited to 'shared/systemd/src/basic/string-util.c')
-rw-r--r--shared/systemd/src/basic/string-util.c26
1 files changed, 20 insertions, 6 deletions
diff --git a/shared/systemd/src/basic/string-util.c b/shared/systemd/src/basic/string-util.c
index 2d34603e..3d2feb18 100644
--- a/shared/systemd/src/basic/string-util.c
+++ b/shared/systemd/src/basic/string-util.c
@@ -7,7 +7,6 @@
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <string.h>
 
 #include "alloc-util.h"
 #include "escape.h"
@@ -750,7 +749,7 @@ static void advance_offsets(
 }
 
 char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
-        const char *i, *begin = NULL;
+        const char *begin = NULL;
         enum {
                 STATE_OTHER,
                 STATE_ESCAPE,
@@ -758,7 +757,7 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
                 STATE_CSO,
         } state = STATE_OTHER;
         char *obuf = NULL;
-        size_t osz = 0, isz, shift[2] = {};
+        size_t osz = 0, isz, shift[2] = {}, n_carriage_returns = 0;
         FILE *f;
 
         assert(ibuf);
@@ -769,6 +768,8 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
          * 1. Replaces TABs by 8 spaces
          * 2. Strips ANSI color sequences (a subset of CSI), i.e. ESC '[' … 'm' sequences
          * 3. Strips ANSI operating system sequences (CSO), i.e. ESC ']' … BEL sequences
+         * 4. Strip trailing \r characters (since they would "move the cursor", but have no
+         *    other effect).
          *
          * Everything else will be left as it is. In particular other ANSI sequences are left as they are, as
          * are any other special characters. Truncated ANSI sequences are left-as is too. This call is
@@ -784,14 +785,24 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
         if (!f)
                 return NULL;
 
-        for (i = *ibuf; i < *ibuf + isz + 1; i++) {
+        for (const char *i = *ibuf; i < *ibuf + isz + 1; i++) {
 
                 switch (state) {
 
                 case STATE_OTHER:
                         if (i >= *ibuf + isz) /* EOT */
                                 break;
-                        else if (*i == '\x1B')
+
+                        if (*i == '\r') {
+                                n_carriage_returns++;
+                                break;
+                        } else if (*i == '\n')
+                                /* Ignore carriage returns before new line */
+                                n_carriage_returns = 0;
+                        for (; n_carriage_returns > 0; n_carriage_returns--)
+                                fputc('\r', f);
+
+                        if (*i == '\x1B')
                                 state = STATE_ESCAPE;
                         else if (*i == '\t') {
                                 fputs("        ", f);
@@ -802,6 +813,8 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
                         break;
 
                 case STATE_ESCAPE:
+                        assert(n_carriage_returns == 0);
+
                         if (i >= *ibuf + isz) { /* EOT */
                                 fputc('\x1B', f);
                                 advance_offsets(i - *ibuf, highlight, shift, 1);
@@ -822,6 +835,7 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
                         break;
 
                 case STATE_CSI:
+                        assert(n_carriage_returns == 0);
 
                         if (i >= *ibuf + isz || /* EOT … */
                             !strchr("01234567890;m", *i)) { /* … or invalid chars in sequence */
@@ -836,6 +850,7 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
                         break;
 
                 case STATE_CSO:
+                        assert(n_carriage_returns == 0);
 
                         if (i >= *ibuf + isz || /* EOT … */
                             (*i != '\a' && (uint8_t) *i < 32U) || (uint8_t) *i > 126U) { /* … or invalid chars in sequence */
@@ -855,7 +870,6 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
                 fclose(f);
                 return mfree(obuf);
         }
-
         fclose(f);
 
         free_and_replace(*ibuf, obuf);