Emit dedicated bright terminal color codes if supported
[babeltrace.git] / src / common / common.c
index 404357a38beed46ebf55e086c17542c14cdf3e3a..86c703411497d96518dd586723844ee54f88a3d4 100644 (file)
@@ -63,6 +63,13 @@ static const char *bt_common_color_code_fg_blue = "";
 static const char *bt_common_color_code_fg_magenta = "";
 static const char *bt_common_color_code_fg_cyan = "";
 static const char *bt_common_color_code_fg_light_gray = "";
+static const char *bt_common_color_code_fg_bright_red = "";
+static const char *bt_common_color_code_fg_bright_green = "";
+static const char *bt_common_color_code_fg_bright_yellow = "";
+static const char *bt_common_color_code_fg_bright_blue = "";
+static const char *bt_common_color_code_fg_bright_magenta = "";
+static const char *bt_common_color_code_fg_bright_cyan = "";
+static const char *bt_common_color_code_fg_bright_light_gray = "";
 static const char *bt_common_color_code_bg_default = "";
 static const char *bt_common_color_code_bg_red = "";
 static const char *bt_common_color_code_bg_green = "";
@@ -76,6 +83,10 @@ static
 void __attribute__((constructor)) bt_common_color_ctor(void)
 {
        if (bt_common_colors_supported()) {
+               const char *term_env_var;
+               const char *bright_means_bold_env_var;
+               bool bright_means_bold = true;
+
                bt_common_color_code_reset = BT_COMMON_COLOR_RESET;
                bt_common_color_code_bold = BT_COMMON_COLOR_BOLD;
                bt_common_color_code_fg_default = BT_COMMON_COLOR_FG_DEFAULT;
@@ -86,6 +97,78 @@ void __attribute__((constructor)) bt_common_color_ctor(void)
                bt_common_color_code_fg_magenta = BT_COMMON_COLOR_FG_MAGENTA;
                bt_common_color_code_fg_cyan = BT_COMMON_COLOR_FG_CYAN;
                bt_common_color_code_fg_light_gray = BT_COMMON_COLOR_FG_LIGHT_GRAY;
+
+               /*
+                * Check whether or not the terminal supports having
+                * bold foreground colors which do _not_ become bright
+                * colors, that is, the lines
+                *
+                *     $ echo -e "\033[31mTHIS\n\033[1mTHAT\033[0m"
+                *
+                * have the _same_ color, but `THAT` uses a bold font.
+                *
+                * This is the case of the kitty terminal emulator.
+                *
+                * It's also possible with GNOME Terminal since 3.27.2
+                * and xfce4-terminal since 0.8.7 (and GNOME VTE since
+                * 0.51.2), but it's user-configurable. Since we don't
+                * have this configuration value here, assume it's not
+                * the case to support old versions of GNOME Terminal.
+                *
+                * Any user can set the
+                * `BABELTRACE_TERM_COLOR_BRIGHT_MEANS_BOLD` environment
+                * variable to `0` to use the bright foreground color
+                * codes instead of making the normal foreground color
+                * codes bold.
+                *
+                * Summary:
+                *
+                * With kitty or when
+                * `BABELTRACE_TERM_COLOR_BRIGHT_MEANS_BOLD` is `0`:
+                *     Output bright colors using dedicated SGR codes
+                *     90 to 97.
+                *
+                * Otherwise:
+                *     Output bright colors with bold + SGR codes 30 to
+                *     37.
+                */
+               term_env_var = getenv("TERM");
+               BT_ASSERT(term_env_var);
+
+               if (strcmp(term_env_var, "xterm-kitty") == 0) {
+                       /*
+                        * The kitty terminal emulator supports
+                        * non-bright bold foreground colors.
+                        */
+                       bright_means_bold = false;
+               }
+
+               bright_means_bold_env_var =
+                       getenv("BABELTRACE_TERM_COLOR_BRIGHT_MEANS_BOLD");
+
+               if (bright_means_bold_env_var) {
+                       bright_means_bold =
+                               !(strcmp(bright_means_bold_env_var, "0") == 0);
+               }
+
+               if (bright_means_bold) {
+                       bt_common_color_code_fg_bright_red = BT_COMMON_COLOR_FG_BOLD_RED;
+                       bt_common_color_code_fg_bright_green = BT_COMMON_COLOR_FG_BOLD_GREEN;
+                       bt_common_color_code_fg_bright_yellow = BT_COMMON_COLOR_FG_BOLD_YELLOW;
+                       bt_common_color_code_fg_bright_blue = BT_COMMON_COLOR_FG_BOLD_BLUE;
+                       bt_common_color_code_fg_bright_magenta = BT_COMMON_COLOR_FG_BOLD_MAGENTA;
+                       bt_common_color_code_fg_bright_cyan = BT_COMMON_COLOR_FG_BOLD_CYAN;
+                       bt_common_color_code_fg_bright_light_gray = BT_COMMON_COLOR_FG_BOLD_LIGHT_GRAY;
+               } else {
+                       bt_common_color_code_fg_bright_red = BT_COMMON_COLOR_FG_BRIGHT_RED;
+                       bt_common_color_code_fg_bright_green = BT_COMMON_COLOR_FG_BRIGHT_GREEN;
+                       bt_common_color_code_fg_bright_yellow = BT_COMMON_COLOR_FG_BRIGHT_YELLOW;
+                       bt_common_color_code_fg_bright_blue = BT_COMMON_COLOR_FG_BRIGHT_BLUE;
+                       bt_common_color_code_fg_bright_magenta = BT_COMMON_COLOR_FG_BRIGHT_MAGENTA;
+                       bt_common_color_code_fg_bright_cyan = BT_COMMON_COLOR_FG_BRIGHT_CYAN;
+                       bt_common_color_code_fg_bright_light_gray = BT_COMMON_COLOR_FG_BRIGHT_LIGHT_GRAY;
+               }
+
                bt_common_color_code_bg_default = BT_COMMON_COLOR_BG_DEFAULT;
                bt_common_color_code_bg_red = BT_COMMON_COLOR_BG_RED;
                bt_common_color_code_bg_green = BT_COMMON_COLOR_BG_GREEN;
@@ -388,6 +471,48 @@ const char *bt_common_color_fg_light_gray(void)
        return bt_common_color_code_fg_light_gray;
 }
 
+BT_HIDDEN
+const char *bt_common_color_fg_bright_red(void)
+{
+       return bt_common_color_code_fg_bright_red;
+}
+
+BT_HIDDEN
+const char *bt_common_color_fg_bright_green(void)
+{
+       return bt_common_color_code_fg_bright_green;
+}
+
+BT_HIDDEN
+const char *bt_common_color_fg_bright_yellow(void)
+{
+       return bt_common_color_code_fg_bright_yellow;
+}
+
+BT_HIDDEN
+const char *bt_common_color_fg_bright_blue(void)
+{
+       return bt_common_color_code_fg_bright_blue;
+}
+
+BT_HIDDEN
+const char *bt_common_color_fg_bright_magenta(void)
+{
+       return bt_common_color_code_fg_bright_magenta;
+}
+
+BT_HIDDEN
+const char *bt_common_color_fg_bright_cyan(void)
+{
+       return bt_common_color_code_fg_bright_cyan;
+}
+
+BT_HIDDEN
+const char *bt_common_color_fg_bright_light_gray(void)
+{
+       return bt_common_color_code_fg_bright_light_gray;
+}
+
 BT_HIDDEN
 const char *bt_common_color_bg_default(void)
 {
@@ -512,6 +637,7 @@ set_end_pos:
 error:
        if (output) {
                g_string_free(output, TRUE);
+               output = NULL;
        }
 
 end:
@@ -579,7 +705,7 @@ bool bt_common_string_is_printable(const char *input)
 {
        const char *ch;
        bool printable = true;
-       BT_ASSERT(input);
+       BT_ASSERT_DBG(input);
 
        for (ch = input; *ch != '\0'; ch++) {
                if (!isprint(*ch) && *ch != '\n' && *ch != '\r' &&
@@ -672,7 +798,7 @@ struct bt_common_lttng_live_url_parts bt_common_parse_lttng_live_url(
 
        at += end_pos;
 
-       /* :// */
+       /* `://` */
        if (strncmp(at, "://", 3) != 0) {
                if (error_buf) {
                        snprintf(error_buf, error_buf_size,
@@ -682,6 +808,7 @@ struct bt_common_lttng_live_url_parts bt_common_parse_lttng_live_url(
                goto error;
        }
 
+       /* Skip `://` */
        at += 3;
 
        /* Hostname */
@@ -731,12 +858,13 @@ struct bt_common_lttng_live_url_parts bt_common_parse_lttng_live_url(
        }
 
        if (at[end_pos] == '\0') {
+               /* Relay daemon hostname and ports provided only */
                goto end;
        }
 
        at += end_pos;
 
-       /* /host/ */
+       /* `/host/` */
        if (strncmp(at, "/host/", 6) != 0) {
                if (error_buf) {
                        snprintf(error_buf, error_buf_size,
@@ -760,9 +888,16 @@ struct bt_common_lttng_live_url_parts bt_common_parse_lttng_live_url(
        }
 
        if (at[end_pos] == '\0') {
-               goto end;
+               if (error_buf) {
+                       snprintf(error_buf, error_buf_size,
+                               "Missing `/` after target hostname (`%s`)",
+                               parts.target_hostname->str);
+               }
+
+               goto error;
        }
 
+       /* Skip `/` */
        at += end_pos + 1;
 
        /* Session name */
@@ -1246,7 +1381,7 @@ size_t bt_common_get_page_size(int log_level)
        if (page_size < 0) {
                BT_LOGF("Cannot get system's page size: ret=%d",
                        page_size);
-               abort();
+               bt_common_abort();
        }
 
        return page_size;
@@ -1261,7 +1396,7 @@ size_t bt_common_get_page_size(int log_level)
                strncpy(_tmp_fmt, *out_fmt_ch, _tmp_fmt_size);          \
                _tmp_fmt[_tmp_fmt_size] = '\0';                         \
                _count = snprintf(*buf_ch, _size, _tmp_fmt, __VA_ARGS__); \
-               BT_ASSERT(_count >= 0);                                 \
+               BT_ASSERT_DBG(_count >= 0);                                     \
                *buf_ch += MIN(_count, _size);                          \
        } while (0)
 
@@ -1403,13 +1538,11 @@ static inline void handle_conversion_specifier_std(char *buf, char **buf_ch,
 
                switch (length_mod) {
                case LENGTH_MOD_NONE:
-                       BUF_STD_APPEND_SINGLE_ARG(int);
-                       break;
                case LENGTH_MOD_LOW_L:
-                       BUF_STD_APPEND_SINGLE_ARG(wint_t);
+                       BUF_STD_APPEND_SINGLE_ARG(int);
                        break;
                default:
-                       abort();
+                       bt_common_abort();
                }
                break;
        }
@@ -1424,7 +1557,7 @@ static inline void handle_conversion_specifier_std(char *buf, char **buf_ch,
                        BUF_STD_APPEND_SINGLE_ARG(wchar_t *);
                        break;
                default:
-                       abort();
+                       bt_common_abort();
                }
                break;
        case 'd':
@@ -1447,7 +1580,7 @@ static inline void handle_conversion_specifier_std(char *buf, char **buf_ch,
                        BUF_STD_APPEND_SINGLE_ARG(size_t);
                        break;
                default:
-                       abort();
+                       bt_common_abort();
                }
                break;
        case 'o':
@@ -1472,7 +1605,7 @@ static inline void handle_conversion_specifier_std(char *buf, char **buf_ch,
                        BUF_STD_APPEND_SINGLE_ARG(size_t);
                        break;
                default:
-                       abort();
+                       bt_common_abort();
                }
                break;
        case 'f':
@@ -1491,7 +1624,7 @@ static inline void handle_conversion_specifier_std(char *buf, char **buf_ch,
                        BUF_STD_APPEND_SINGLE_ARG(long double);
                        break;
                default:
-                       abort();
+                       bt_common_abort();
                }
                break;
        case 'p':
@@ -1500,11 +1633,11 @@ static inline void handle_conversion_specifier_std(char *buf, char **buf_ch,
                if (length_mod == LENGTH_MOD_NONE) {
                        BUF_STD_APPEND_SINGLE_ARG(void *);
                } else {
-                       abort();
+                       bt_common_abort();
                }
                break;
        default:
-               abort();
+               bt_common_abort();
        }
 
 update_rw_fmt:
@@ -1520,13 +1653,13 @@ void bt_common_custom_vsnprintf(char *buf, size_t buf_size,
        const char *fmt_ch = fmt;
        char *buf_ch = buf;
 
-       BT_ASSERT(buf);
-       BT_ASSERT(fmt);
+       BT_ASSERT_DBG(buf);
+       BT_ASSERT_DBG(fmt);
 
        while (*fmt_ch != '\0') {
                switch (*fmt_ch) {
                case '%':
-                       BT_ASSERT(fmt_ch[1] != '\0');
+                       BT_ASSERT_DBG(fmt_ch[1] != '\0');
 
                        if (fmt_ch[1] == intro) {
                                handle_specifier(priv_data, &buf_ch,
@@ -1578,12 +1711,12 @@ void bt_common_sep_digits(char *str, unsigned int digits_per_group, char sep)
        uint64_t sep_count;
        uint64_t new_len;
 
-       BT_ASSERT(digits_per_group > 0);
-       BT_ASSERT(sep != '\0');
+       BT_ASSERT_DBG(digits_per_group > 0);
+       BT_ASSERT_DBG(sep != '\0');
 
        /* Compute new length of `str` */
        orig_len = strlen(str);
-       BT_ASSERT(orig_len > 0);
+       BT_ASSERT_DBG(orig_len > 0);
        sep_count = (orig_len - 1) / digits_per_group;
        new_len = strlen(str) + sep_count;
 
@@ -1683,10 +1816,10 @@ GString *bt_common_fold(const char *str, unsigned int total_length,
        gchar * const *line;
        unsigned int i;
 
-       BT_ASSERT(str);
-       BT_ASSERT(indent < total_length);
-       BT_ASSERT(tmp_line);
-       BT_ASSERT(folded);
+       BT_ASSERT_DBG(str);
+       BT_ASSERT_DBG(indent < total_length);
+       BT_ASSERT_DBG(tmp_line);
+       BT_ASSERT_DBG(folded);
 
        if (strlen(str) == 0) {
                /* Empty input string: empty output string */
@@ -1695,7 +1828,7 @@ GString *bt_common_fold(const char *str, unsigned int total_length,
 
        /* Split lines */
        lines = g_strsplit(str, "\n", 0);
-       BT_ASSERT(lines);
+       BT_ASSERT_DBG(lines);
 
        /* For each source line */
        for (line = lines; *line; line++) {
@@ -1712,7 +1845,7 @@ GString *bt_common_fold(const char *str, unsigned int total_length,
 
                /* Split words */
                line_words = g_strsplit(*line, " ", 0);
-               BT_ASSERT(line_words);
+               BT_ASSERT_DBG(line_words);
 
                /*
                 * Indent for first line (we know there's at least one
@@ -1780,7 +1913,7 @@ end:
                g_strfreev(lines);
        }
 
-       BT_ASSERT(!line_words);
+       BT_ASSERT_DBG(!line_words);
 
        if (tmp_line) {
                g_string_free(tmp_line, TRUE);
@@ -1852,3 +1985,65 @@ int bt_common_g_string_append_printf(GString *str, const char *fmt, ...)
        }
        return print_len;
 }
+
+BT_HIDDEN
+int bt_common_append_file_content_to_g_string(GString *str, FILE *fp)
+{
+       const size_t chunk_size = 4096;
+       int ret = 0;
+       char *buf;
+       size_t read_len;
+       gsize orig_len = str->len;
+
+       BT_ASSERT(str);
+       BT_ASSERT(fp);
+       buf = g_malloc(chunk_size);
+       if (!buf) {
+               ret = -1;
+               goto end;
+       }
+
+       while (true) {
+               if (ferror(fp)) {
+                       ret = -1;
+                       goto end;
+               }
+
+               if (feof(fp)) {
+                       break;
+               }
+
+               read_len = fread(buf, 1, chunk_size, fp);
+               g_string_append_len(str, buf, read_len);
+       }
+
+end:
+       if (ret) {
+               /* Remove what was appended */
+               g_string_truncate(str, orig_len);
+       }
+
+       g_free(buf);
+       return ret;
+}
+
+BT_HIDDEN
+void bt_common_abort(void)
+{
+       static const char * const exec_on_abort_env_name =
+               "BABELTRACE_EXEC_ON_ABORT";
+       const char *env_exec_on_abort;
+
+       env_exec_on_abort = getenv(exec_on_abort_env_name);
+       if (env_exec_on_abort) {
+               if (bt_common_is_setuid_setgid()) {
+                       goto do_abort;
+               }
+
+               (void) g_spawn_command_line_sync(env_exec_on_abort,
+                           NULL, NULL, NULL, NULL);
+       }
+
+do_abort:
+       abort();
+}
This page took 0.029439 seconds and 4 git commands to generate.